diff --git a/SMCode/SM.Base/Drawing/MaterialShader.cs b/SMCode/SM.Base/Drawing/MaterialShader.cs index 758a69d..bb14df0 100644 --- a/SMCode/SM.Base/Drawing/MaterialShader.cs +++ b/SMCode/SM.Base/Drawing/MaterialShader.cs @@ -42,15 +42,14 @@ namespace SM.Base.Drawing CleanUp(); GL.UseProgram(0); + + context.ShaderArguments.Clear(); } /// /// Draws the context. /// /// - protected virtual void DrawProcess(DrawContext context) - { - - } + protected abstract void DrawProcess(DrawContext context); } } \ No newline at end of file diff --git a/SMCode/SM.Base/Objects/Mesh.cs b/SMCode/SM.Base/Objects/Mesh.cs index f01ef79..dad91e2 100644 --- a/SMCode/SM.Base/Objects/Mesh.cs +++ b/SMCode/SM.Base/Objects/Mesh.cs @@ -12,7 +12,7 @@ namespace SM.Base.Objects /// /// While initializing, it will add the to the data index. /// - protected Mesh() + public Mesh() { Attributes.Add(3, "color", Color); } diff --git a/SMCode/SM.Base/PostProcess/PostProcessEffect.cs b/SMCode/SM.Base/PostProcess/PostProcessEffect.cs index f71cf94..9e0836a 100644 --- a/SMCode/SM.Base/PostProcess/PostProcessEffect.cs +++ b/SMCode/SM.Base/PostProcess/PostProcessEffect.cs @@ -24,7 +24,7 @@ namespace SM.Base.PostProcess Init(); } - public virtual void Draw(Framebuffer main) + public virtual void Draw(Framebuffer main, Framebuffer target) { } diff --git a/SMCode/SM.Base/PostProcess/PostProcessShader.cs b/SMCode/SM.Base/PostProcess/PostProcessShader.cs index 9bd24e9..27b25c5 100644 --- a/SMCode/SM.Base/PostProcess/PostProcessShader.cs +++ b/SMCode/SM.Base/PostProcess/PostProcessShader.cs @@ -53,12 +53,11 @@ namespace SM.Base.PostProcess Uniforms["MVP"].SetMatrix4(PostProcessEffect.Mvp); Uniforms["ModelMatrix"].SetMatrix4(PostProcessEffect.Model); - Uniforms["renderedTexture"].SetTexture(color, 0); + Uniforms["renderedTexture"].SetTexture(color); GL.DrawArrays(PrimitiveType.Quads, 0, 4); - GL.BindTexture(TextureTarget.Texture2D, 0); - GL.BindVertexArray(0); + CleanUp(); GL.UseProgram(0); } @@ -74,14 +73,13 @@ namespace SM.Base.PostProcess Uniforms["MVP"].SetMatrix4(PostProcessEffect.Mvp); Uniforms["ModelMatrix"].SetMatrix4(PostProcessEffect.Model); - Uniforms["renderedTexture"].SetTexture(color, 0); + Uniforms["renderedTexture"].SetTexture(color); setUniformAction(Uniforms); GL.DrawArrays(PrimitiveType.Quads, 0, 4); - GL.BindTexture(TextureTarget.Texture2D, 0); - GL.BindVertexArray(0); + CleanUp(); GL.UseProgram(0); } } diff --git a/SMCode/SM.Base/Window/Contexts/DrawContext.cs b/SMCode/SM.Base/Window/Contexts/DrawContext.cs index 1d31a22..8e7d68d 100644 --- a/SMCode/SM.Base/Window/Contexts/DrawContext.cs +++ b/SMCode/SM.Base/Window/Contexts/DrawContext.cs @@ -1,6 +1,7 @@ #region usings using System.Collections.Generic; +using System.Dynamic; using OpenTK; using SM.Base.Drawing; using SM.Base.Scene; @@ -71,6 +72,11 @@ namespace SM.Base.Contexts /// public object LastPassthough; + /// + /// Arguments for shaders + /// + public IDictionary ShaderArguments; + /// /// Returns the appropriate shader. /// diff --git a/SMCode/SM.Base/Window/GenericWindow.cs b/SMCode/SM.Base/Window/GenericWindow.cs index 39b14e3..e1f0294 100644 --- a/SMCode/SM.Base/Window/GenericWindow.cs +++ b/SMCode/SM.Base/Window/GenericWindow.cs @@ -268,6 +268,7 @@ namespace SM.Base new Instance {ModelMatrix = Matrix4.Identity, TexturePosition = Vector2.Zero, TextureScale = Vector2.One} }, + ShaderArguments = new Dictionary(), Mesh = Plate.Object, ForceViewport = ForceViewportCamera, WorldScale = _worldScale, diff --git a/SMCode/SM.Base/Window/RenderPipeline.cs b/SMCode/SM.Base/Window/RenderPipeline.cs index fd87991..df43851 100644 --- a/SMCode/SM.Base/Window/RenderPipeline.cs +++ b/SMCode/SM.Base/Window/RenderPipeline.cs @@ -88,9 +88,9 @@ namespace SM.Base { } - protected Framebuffer CreateWindowFramebuffer() + public static Framebuffer CreateWindowFramebuffer() { - Framebuffer framebuffer = new Framebuffer(window: _window); + Framebuffer framebuffer = new Framebuffer(window: SMRenderer.CurrentWindow); framebuffer.Append("color", 0); framebuffer.Compile(); return framebuffer; diff --git a/SMCode/SM.OGL/Shaders/Uniform.cs b/SMCode/SM.OGL/Shaders/Uniform.cs index 9d21661..2136aa1 100644 --- a/SMCode/SM.OGL/Shaders/Uniform.cs +++ b/SMCode/SM.OGL/Shaders/Uniform.cs @@ -458,7 +458,7 @@ namespace SM.OGL.Shaders /// public void SetTexture(TextureBase texture) { - if (Parent != null) SetTexture(texture, Parent.NextTexture++); + if (Parent != null) SetTexture(texture, Parent.NextTexture); } /// @@ -468,6 +468,7 @@ namespace SM.OGL.Shaders /// public void SetTexture(TextureBase texture, int texturePos) { + Parent.NextTexture = texturePos + 1; GL.ActiveTexture(TextureUnit.Texture0 + texturePos); GL.BindTexture(TextureTarget.Texture2D, texture); SetUniform1(texturePos); diff --git a/SMCode/SM.OGL/Shaders/UniformCollection.cs b/SMCode/SM.OGL/Shaders/UniformCollection.cs index 310536c..e033861 100644 --- a/SMCode/SM.OGL/Shaders/UniformCollection.cs +++ b/SMCode/SM.OGL/Shaders/UniformCollection.cs @@ -10,7 +10,7 @@ namespace SM.OGL.Shaders { public class UniformCollection : Dictionary { - internal int NextTexture = 0; + public int NextTexture = 0; internal string KeyString = ""; public GenericShader ParentShader { get; internal set; } diff --git a/SMCode/SM2D/Drawing/DrawObject2D.cs b/SMCode/SM2D/Drawing/DrawObject2D.cs index 436a173..d1c8540 100644 --- a/SMCode/SM2D/Drawing/DrawObject2D.cs +++ b/SMCode/SM2D/Drawing/DrawObject2D.cs @@ -16,6 +16,8 @@ namespace SM2D.Drawing { public int ZIndex { get; set; } + public bool ShadowCaster = false; + public Texture Texture { get => (Texture) _material.Texture; @@ -31,6 +33,7 @@ namespace SM2D.Drawing protected override void DrawContext(ref DrawContext context) { base.DrawContext(ref context); + context.ShaderArguments["occluder"] = ShadowCaster; context.Shader.Draw(context); } @@ -64,5 +67,6 @@ namespace SM2D.Drawing _mesh = pol; return pol; } + } } \ No newline at end of file diff --git a/SMCode/SM2D/GLWindow2D.cs b/SMCode/SM2D/GLWindow2D.cs index 834cd66..6f18668 100644 --- a/SMCode/SM2D/GLWindow2D.cs +++ b/SMCode/SM2D/GLWindow2D.cs @@ -38,7 +38,7 @@ namespace SM2D base.OnLoaded(); SMRenderer.DefaultMaterialShader = Default2DShader.MaterialShader; - SetRenderPipeline(new Basic2DPipeline()); + SetRenderPipeline(Default2DPipeline.Pipeline); } protected override void OnRenderFrame(FrameEventArgs e) diff --git a/SMCode/SM2D/Light/LightObjects/LightObject.cs b/SMCode/SM2D/Light/LightObjects/LightObject.cs index 0dfad7f..d460c84 100644 --- a/SMCode/SM2D/Light/LightObjects/LightObject.cs +++ b/SMCode/SM2D/Light/LightObjects/LightObject.cs @@ -1,5 +1,7 @@ using System.Collections.Generic; +using OpenTK; using OpenTK.Graphics; +using SM.Base; using SM.Base.Types; using SM.OGL.Shaders; @@ -7,6 +9,7 @@ namespace SM2D.Light { public abstract class LightObject { + private Vector2 _posNorm => Vector2.Divide(Position, (SMRenderer.CurrentWindow as GLWindow2D).WorldScale); internal abstract int Type { get; } public CVector2 Position = new CVector2(0); diff --git a/SMCode/SM2D/Light/LightObjects/PointLight.cs b/SMCode/SM2D/Light/LightObjects/PointLight.cs index 8042983..ae4f1e7 100644 --- a/SMCode/SM2D/Light/LightObjects/PointLight.cs +++ b/SMCode/SM2D/Light/LightObjects/PointLight.cs @@ -8,12 +8,16 @@ namespace SM2D.Light internal override int Type { get; } = 0; public float Power = 5; + public float InnerCircle = 1; + public float OuterCircle = 1; internal override void SetUniforms(Dictionary uniforms) { base.SetUniforms(uniforms); uniforms["Power"].SetUniform1(Power); + uniforms["Inner"].SetUniform1(1 / InnerCircle); + uniforms["Outer"].SetUniform1(1 / OuterCircle); } } } \ No newline at end of file diff --git a/SMCode/SM2D/Light/LightPostEffect.cs b/SMCode/SM2D/Light/LightPostEffect.cs index a978b1e..da3f205 100644 --- a/SMCode/SM2D/Light/LightPostEffect.cs +++ b/SMCode/SM2D/Light/LightPostEffect.cs @@ -1,9 +1,11 @@ using System.Reflection; +using SM.Base; using SM.Base.PostProcess; using SM.Base.Scene; using SM.OGL.Framebuffer; using SM.OGL.Shaders; using SM.Utility; +using SM2D.Scene; namespace SM2D.Light { @@ -12,14 +14,25 @@ namespace SM2D.Light private PostProcessShader _shader = new PostProcessShader(AssemblyUtility.ReadAssemblyFile("SM2D.Light.light.frag")); private LightSceneExtension sceneExtension; - public override void Draw(Framebuffer main) + public override void Init(Framebuffer main) { - base.Draw(main); - + base.Init(main); + main.Append("occluder", 1); + } + + public override void Draw(Framebuffer main, Framebuffer target) + { + base.Draw(main, target); + _shader.Draw(main.ColorAttachments["color"], collection => { + collection["FragSize"].SetUniform2((SMRenderer.CurrentWindow as GLWindow2D).WorldScale); + collection["Ambient"].SetUniform4(sceneExtension.Ambient); collection["LightCount"].SetUniform1(sceneExtension.Lights.Count); + collection["OccluderMap"].SetTexture(main.ColorAttachments["occluder"]); + collection["ShadowSensitivty"].SetUniform1(1f); + UniformArray array = collection.GetArray("Lights"); for (int i = 0; i < sceneExtension.Lights.Count; i++) diff --git a/SMCode/SM2D/Light/light.frag b/SMCode/SM2D/Light/light.frag index 7b01fd9..8d45503 100644 --- a/SMCode/SM2D/Light/light.frag +++ b/SMCode/SM2D/Light/light.frag @@ -8,15 +8,22 @@ struct Light { // pointStuff; float Power; + float Inner; + float Outer; }; in vec2 vTexture; in vec2 FragPos; +uniform vec2 FragSize; + uniform vec4 Ambient = vec4(1); uniform Light[24] Lights; uniform int LightCount; +uniform float ShadowSensitivty; +uniform sampler2D OccluderMap; + layout(location = 0) out vec4 color; vec4 GetRenderColor(); @@ -24,10 +31,27 @@ vec4 GetRenderColor(); vec3 calcPointLight(Light light) { vec2 diff = light.Position - FragPos; - float dif = light.Power / length(diff); - float intensity = 4 * PI * dif * (dif * dif); + float dif = 20 / length(diff); + float intensity = light.Power * (dif) * (dif * dif); - return vec3(intensity); + return vec3(light.Color * intensity); +} + +float occluded(Light light) { + float occluder = 1 - length(texture(OccluderMap, vTexture).rgb); + + if (occluder != 0) { + vec2 diff = light.Position - FragPos; + vec2 dir = normalize(diff); + + float steps = length(diff) / ShadowSensitivty; + + vec2 curPos = FragPos; + for(int i = 0; i < steps; i++) { + curPos += dir * i * ShadowSensitivty; + } + } + return occluder; } vec3 calcLight() { @@ -36,11 +60,13 @@ vec3 calcLight() { for(int i = 0; i < LightCount; i++) { Light light = Lights[i]; + vec3 lightColor; switch(light.Type) { case 0: - addedLight += calcPointLight(light); + lightColor += calcPointLight(light); break; } + addedLight += lightColor * occluded(light); } return addedLight; @@ -51,5 +77,5 @@ void main() { color = render * Ambient; - color += vec4(calcLight() * render.xyz, 1); + color += vec4(calcLight(), 1); } \ No newline at end of file diff --git a/SMCode/SM2D/Pipelines/Basic2DPipeline.cs b/SMCode/SM2D/Pipelines/Basic2DPipeline.cs index f9277a6..4d2f60e 100644 --- a/SMCode/SM2D/Pipelines/Basic2DPipeline.cs +++ b/SMCode/SM2D/Pipelines/Basic2DPipeline.cs @@ -1,52 +1,30 @@ -#region usings - +using System; using OpenTK.Graphics.OpenGL4; using SM.Base; using SM.Base.Contexts; -using SM.Base.Scene; +using SM.Base.Drawing; using SM.OGL.Framebuffer; -using SM2D.Light; using SM2D.Shader; -#endregion - namespace SM2D.Pipelines { public class Basic2DPipeline : RenderPipeline { - private Framebuffer _tempWindow; - private Light.LightPostEffect _lightEffect; + public static Basic2DPipeline Pipeline = new Basic2DPipeline(); - protected override void Initialization(GenericWindow window) + protected override MaterialShader _defaultShader { get; } = Basic2DShader.Shader; + + private Basic2DPipeline() { - _tempWindow = CreateWindowFramebuffer(); - _lightEffect = new LightPostEffect(); + Console.WriteLine(); } protected override void Render(ref DrawContext context, Scene.Scene scene) { base.Render(ref context, scene); - _tempWindow.Activate(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); - - if (scene != null) - { - scene.DrawBackground(context); - - scene.DrawMainObjects(context); - - Framebuffer.Screen.Activate(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); - _lightEffect.Draw(_tempWindow); - - scene.DrawHUD(context); - scene.DrawDebug(context); - } - } - - protected override void SceneChanged(Scene.Scene scene) - { - base.SceneChanged(scene); - _lightEffect.SceneChanged(scene); + Framebuffer.Screen.Activate(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); + if (scene != null) scene.Draw(context); } } } \ No newline at end of file diff --git a/SMCode/SM2D/Pipelines/Default2DPipeline.cs b/SMCode/SM2D/Pipelines/Default2DPipeline.cs new file mode 100644 index 0000000..cb41d6e --- /dev/null +++ b/SMCode/SM2D/Pipelines/Default2DPipeline.cs @@ -0,0 +1,65 @@ +#region usings + +using System.Collections.Generic; +using OpenTK.Graphics.OpenGL4; +using SM.Base; +using SM.Base.Contexts; +using SM.Base.Scene; +using SM.OGL.Framebuffer; +using SM2D.Light; +using SM2D.Shader; + +#endregion + +namespace SM2D.Pipelines +{ + public class Default2DPipeline : RenderPipeline + { + public static Default2DPipeline Pipeline = new Default2DPipeline(); + + private Framebuffer _tempWindow; + private Light.LightPostEffect _lightEffect; + + protected override List _framebuffers { get; } = new List(); + + private Default2DPipeline() + { + + } + + protected override void Initialization(GenericWindow window) + { + _tempWindow = CreateWindowFramebuffer(); + _lightEffect = new LightPostEffect(); + + _framebuffers.Add(_tempWindow); + + _lightEffect.Init(_tempWindow); + } + + protected override void Render(ref DrawContext context, Scene.Scene scene) + { + base.Render(ref context, scene); + + if (scene != null) + { + _tempWindow.Activate(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); + scene.DrawBackground(context); + + scene.DrawMainObjects(context); + + Framebuffer.Screen.Activate(); + _lightEffect.Draw(_tempWindow, Framebuffer.Screen); + + scene.DrawHUD(context); + scene.DrawDebug(context); + } + } + + protected override void SceneChanged(Scene.Scene scene) + { + base.SceneChanged(scene); + _lightEffect.SceneChanged(scene); + } + } +} \ No newline at end of file diff --git a/SMCode/SM2D/SM2D.csproj b/SMCode/SM2D/SM2D.csproj index eaf7fef..d33d248 100644 --- a/SMCode/SM2D/SM2D.csproj +++ b/SMCode/SM2D/SM2D.csproj @@ -53,11 +53,13 @@ + + @@ -82,6 +84,8 @@ - + + + \ No newline at end of file diff --git a/SMCode/SM2D/Shader/Basic2DShader.cs b/SMCode/SM2D/Shader/Basic2DShader.cs new file mode 100644 index 0000000..7e9b128 --- /dev/null +++ b/SMCode/SM2D/Shader/Basic2DShader.cs @@ -0,0 +1,40 @@ +using SM.Base.Contexts; +using SM.Base.Drawing; +using SM.OGL.Shaders; +using SM.Utility; + +namespace SM2D.Shader +{ + public class Basic2DShader : MaterialShader + { + + public static Basic2DShader Shader = new Basic2DShader(); + private Basic2DShader() : base(AssemblyUtility.ReadAssemblyFile("SM2D.Shader.ShaderFiles.basic.glsl")) + { + } + + protected override void DrawProcess(DrawContext context) + { + // Vertex Uniforms + Uniforms["MVP"].SetMatrix4(context.ModelMaster * context.View * context.World); + Uniforms["HasVColor"] + .SetUniform1(context.Mesh.Attributes["color"] != null); + + UniformArray instances = Uniforms.GetArray("Instances"); + for (int i = 0; i < context.Instances.Count; i++) + { + var shaderInstance = instances[i]; + var instance = context.Instances[i]; + shaderInstance["ModelMatrix"].SetMatrix4(instance.ModelMatrix); + shaderInstance["TextureOffset"].SetUniform2(instance.TexturePosition); + shaderInstance["TextureScale"].SetUniform2(instance.TextureScale); + } + + // Fragment Uniforms + Uniforms["Tint"].SetUniform4(context.Material.Tint); + Uniforms["Texture"].SetTexture(context.Material.Texture, Uniforms["UseTexture"]); + + DrawObject(context.Mesh, context.Instances.Count); + } + } +} \ No newline at end of file diff --git a/SMCode/SM2D/Shader/Default2DShader.cs b/SMCode/SM2D/Shader/Default2DShader.cs index 0b770da..3a54736 100644 --- a/SMCode/SM2D/Shader/Default2DShader.cs +++ b/SMCode/SM2D/Shader/Default2DShader.cs @@ -27,6 +27,7 @@ namespace SM2D.Shader Uniforms["MVP"].SetMatrix4(context.ModelMaster * context.View * context.World); Uniforms["HasVColor"] .SetUniform1(context.Mesh.Attributes["color"] != null); + Uniforms["occlude"].SetUniform1(context.ShaderArguments.ContainsKey("occluder")); UniformArray instances = Uniforms.GetArray("Instances"); for (int i = 0; i < context.Instances.Count; i++) diff --git a/SMCode/SM2D/Shader/ShaderFiles/basic.glsl b/SMCode/SM2D/Shader/ShaderFiles/basic.glsl new file mode 100644 index 0000000..10978de --- /dev/null +++ b/SMCode/SM2D/Shader/ShaderFiles/basic.glsl @@ -0,0 +1,28 @@ +#version 330 +//# region vertex + +//# import SM_base_vertex_basic +void ApplyTexModifier(); +void CheckVertexColor(); +void ApplyModelTransformation(); + +void vmain() { + ApplyTexModifier(); + CheckVertexColor(); + ApplyModelTransformation(); +} + +//# region fragment +in vec2 vTexture; +in vec4 vColor; + +uniform vec4 Tint; +uniform bool UseTexture; +uniform sampler2D Texture; + +layout(location = 0) out vec4 color; + +void fmain() { + color = vColor * Tint; + if (UseTexture) color *= texture(Texture, vTexture); +} \ No newline at end of file diff --git a/SMCode/SM2D/Shader/ShaderFiles/default.glsl b/SMCode/SM2D/Shader/ShaderFiles/default.glsl index efab3a6..97734bf 100644 --- a/SMCode/SM2D/Shader/ShaderFiles/default.glsl +++ b/SMCode/SM2D/Shader/ShaderFiles/default.glsl @@ -17,13 +17,18 @@ void vmain() { in vec2 vTexture; in vec4 vColor; +uniform bool occlude; + uniform vec4 Tint; uniform bool UseTexture; uniform sampler2D Texture; layout(location = 0) out vec4 color; +layout(location = 1) out vec4 occluder; void fmain() { color = vColor * Tint; if (UseTexture) color *= texture(Texture, vTexture); + + occluder = vec4(occlude,0,0,1); } \ No newline at end of file diff --git a/SM_TEST/Program.cs b/SM_TEST/Program.cs index 6a6c9a2..9829818 100644 --- a/SM_TEST/Program.cs +++ b/SM_TEST/Program.cs @@ -16,6 +16,7 @@ using SM2D; using SM2D.Drawing; using SM2D.Light; using SM2D.Object; +using SM2D.Pipelines; using SM2D.Scene; using Font = SM.Base.Drawing.Text.Font; using Vector2 = OpenTK.Vector2; @@ -38,6 +39,7 @@ namespace SM_TEST window = new GLWindow2D {Scaling = new Vector2(0, 1000)}; //window.GrabCursor(); + window.SetRenderPipeline(Basic2DPipeline.Pipeline); window.SetScene(scene = new Scene()); window.Load += WindowOnLoad; window.RenderFrame += WindowOnUpdateFrame; @@ -59,16 +61,22 @@ namespace SM_TEST scene.ShowAxisHelper = true; DrawObject2D kasten = new DrawObject2D(); + kasten.ShadowCaster = true; kasten.Texture = new Texture(new Bitmap("herosword.png")); kasten.Transform.ApplyTextureSize(kasten.Texture, 500); scene.Objects.Add(kasten); + //scene.Background.Color = Color4.White; + DrawText text = new DrawText(font, "Text"); text.Transform.Position.Set(0, 500); scene.Objects.Add(text); - light = new PointLight(); - light.Color = new Color4(0, 1,0,1); + light = new PointLight + { + Color = new Color4(0, 1, 1, 1), + Power = 100 + }; scene.LightInformations.Lights.Add(light); scene.LightInformations.Ambient = Color4.White;