diff --git a/SMCode/SM.Base/Drawing/DrawingBasis.cs b/SMCode/SM.Base/Drawing/DrawingBasis.cs index 1cd76ce..7aa9180 100644 --- a/SMCode/SM.Base/Drawing/DrawingBasis.cs +++ b/SMCode/SM.Base/Drawing/DrawingBasis.cs @@ -15,6 +15,11 @@ namespace SM.Base.Drawing /// public abstract class DrawingBasis : IShowItem, IModelItem { + /// + /// The camera, that was used last time the object was rendered. + /// + public GenericCamera LastDrawingCamera; + /// /// The material it should use. /// @@ -86,6 +91,8 @@ namespace SM.Base.Drawing context.ForcedType = ForcedMeshType; context.TextureMatrix *= TextureTransform.GetMatrix(); context.LastObject = this; + + LastDrawingCamera = context.UseCamera; } } diff --git a/SMCode/SM.Base/PostEffects/BloomEffect.cs b/SMCode/SM.Base/PostEffects/BloomEffect.cs index f5926ca..095fdb7 100644 --- a/SMCode/SM.Base/PostEffects/BloomEffect.cs +++ b/SMCode/SM.Base/PostEffects/BloomEffect.cs @@ -77,6 +77,12 @@ namespace SM.Base.PostEffects /// public float Power = 1; + /// + /// Radius of the effect + /// Default: 2 + /// + public float Radius = 1; + /// /// This can disable the bloom calculation. /// Default: true @@ -127,7 +133,7 @@ namespace SM.Base.PostEffects /// protected override void InitProcess() { - _source = Pipeline.MainFramebuffer; + _source ??= Pipeline.MainFramebuffer; _source.ColorAttachments["color"].PixelInformation = PixelInformation.RGBA_HDR; @@ -175,6 +181,8 @@ namespace SM.Base.PostEffects collection["Weights"].SetUniform1(_weights); collection["WeightCount"].SetUniform1(WeightCurvePickAmount); collection["Power"].SetUniform1(Power); + + collection["Radius"].SetUniform1(_textureScale * Radius); }); hoz = !hoz; diff --git a/SMCode/SM.Base/PostEffects/PostProcessUtility.cs b/SMCode/SM.Base/PostEffects/PostProcessUtility.cs index e8c7b31..55bef36 100644 --- a/SMCode/SM.Base/PostEffects/PostProcessUtility.cs +++ b/SMCode/SM.Base/PostEffects/PostProcessUtility.cs @@ -28,6 +28,7 @@ namespace SM.Base.PostEffects /// /// This resolves a multisampled framebuffer to a non-multisampled renderbuffer. + /// This removes the depth buffer. /// /// /// @@ -36,7 +37,7 @@ namespace SM.Base.PostEffects multisampledBuffers.Activate(FramebufferTarget.ReadFramebuffer); target.Activate(FramebufferTarget.DrawFramebuffer); GL.BlitFramebuffer(0, 0, (int) multisampledBuffers.Size.X, (int) multisampledBuffers.Size.Y, 0, 0, - (int) target.Size.X, (int) target.Size.Y, ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit, + (int) target.Size.X, (int) target.Size.Y, ClearBufferMask.ColorBufferBit, BlitFramebufferFilter.Nearest); target.Activate(); diff --git a/SMCode/SM.Base/PostEffects/Shaders/bloom_blur.glsl b/SMCode/SM.Base/PostEffects/Shaders/bloom_blur.glsl index 0393f55..834ad23 100644 --- a/SMCode/SM.Base/PostEffects/Shaders/bloom_blur.glsl +++ b/SMCode/SM.Base/PostEffects/Shaders/bloom_blur.glsl @@ -13,6 +13,8 @@ uniform float[32] Weights; uniform int WeightCount; uniform float Power; +uniform float Radius; + layout(location = 0) out vec4 color; vec4 GetRenderColorOffset(vec2 offset); @@ -33,12 +35,13 @@ void main() { vec2 tex_offset = 1.0 / textureSize(renderedTexture, 0) * vec2(Horizontal ? 1 : 0, Horizontal ? 0 : 1); - vec3 result = max(GetRenderColorOffset(vec2(0)).rgb - thres, 0) * (First ? Power : 1); - result *= GetWeight(0); + vec3 result = max(GetRenderColorOffset(vec2(0)).rgb - thres, 0) * (First ? Power : 1) * GetWeight(0); + + float radi = Radius + (length(result)); for(int i = 1; i < WeightCount; i++) { - result += max(GetRenderColorOffset(tex_offset * i).rgb - thres, 0) * (First ? Power : 1) * GetWeight(i); - result += max(GetRenderColorOffset(-tex_offset * i).rgb - thres, 0) * (First ? Power : 1) * GetWeight(i); + result += max(GetRenderColorOffset(tex_offset * i * radi).rgb - thres, 0) * (First ? Power : 1) * GetWeight(i); + result += max(GetRenderColorOffset(-tex_offset * i * radi).rgb - thres, 0) * (First ? Power : 1) * GetWeight(i); } color = vec4(result, 1); diff --git a/SMCode/SM.Base/SM.Base.csproj b/SMCode/SM.Base/SM.Base.csproj index ee29747..c2abcad 100644 --- a/SMCode/SM.Base/SM.Base.csproj +++ b/SMCode/SM.Base/SM.Base.csproj @@ -121,7 +121,6 @@ SM.OGL - diff --git a/SMCode/SM.Base/Window/RenderPipeline.cs b/SMCode/SM.Base/Window/RenderPipeline.cs index 649d11a..a02ab36 100644 --- a/SMCode/SM.Base/Window/RenderPipeline.cs +++ b/SMCode/SM.Base/Window/RenderPipeline.cs @@ -75,29 +75,57 @@ namespace SM.Base.Window /// public virtual void Resize() { - if (Framebuffers == null) return; - foreach (var framebuffer in Framebuffers) - framebuffer.Dispose(); + Recompile(); + } - Thread.Sleep(50); + /// + /// Compiles the framebuffers. + /// + public void Compile() + { foreach (var framebuffer in Framebuffers) framebuffer.Compile(); } + /// + /// Recompiles the pipeline. + /// + public void Recompile() + { + if (Framebuffers == null) return; + Dispose(); + + Thread.Sleep(100); + + Compile(); + } + + /// + /// Disposes unmanaged resources like Framebuffers. + /// + public void Dispose() + { + foreach (var framebuffer in Framebuffers) + framebuffer.Dispose(); + } + /// /// This creates a finished setup for a framebuffer. /// /// /// - public Framebuffer CreateWindowFramebuffer(int multisamples = 0) + public Framebuffer CreateWindowFramebuffer(int multisamples = 0, PixelInformation? pixelInformation = null, bool depth = true) { Framebuffer framebuffer = new Framebuffer(ConnectedWindow); - framebuffer.Append("color", new ColorAttachment(0, PixelInformation.RGBA_LDR, multisamples)); - - RenderbufferAttachment depthAttach = RenderbufferAttachment.Depth; - depthAttach.Multisample = multisamples; - framebuffer.AppendRenderbuffer(depthAttach); + framebuffer.Append("color", new ColorAttachment(0, pixelInformation.GetValueOrDefault(PixelInformation.RGBA_LDR), multisamples)); + + if (depth) + { + RenderbufferAttachment depthAttach = RenderbufferAttachment.Depth; + depthAttach.Multisample = multisamples; + framebuffer.AppendRenderbuffer(depthAttach); + } return framebuffer; } diff --git a/SMCode/SM.Base/Window/WindowCode.cs b/SMCode/SM.Base/Window/WindowCode.cs index 8f35b89..6270a52 100644 --- a/SMCode/SM.Base/Window/WindowCode.cs +++ b/SMCode/SM.Base/Window/WindowCode.cs @@ -13,6 +13,7 @@ using SM.Base.Shaders.Extensions; using SM.Base.Time; using SM.Base.Utility; using SM.OGL; +using SM.OGL.Framebuffer; using Keyboard = SM.Base.Controls.Keyboard; using Mouse = SM.Base.Controls.Mouse; @@ -26,6 +27,7 @@ namespace SM.Base.Window { GLSystem.INIT_SYSTEM(); GLSettings.ShaderPreProcessing = true; + Framebuffer.ScreenWindow = window; var args = Environment.GetCommandLineArgs(); if (args.Contains("--advDebugging")) diff --git a/SMCode/SM.OGL/Framebuffer/Framebuffer.cs b/SMCode/SM.OGL/Framebuffer/Framebuffer.cs index b92718b..8ffc5f1 100644 --- a/SMCode/SM.OGL/Framebuffer/Framebuffer.cs +++ b/SMCode/SM.OGL/Framebuffer/Framebuffer.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Linq; using OpenTK; using OpenTK.Graphics.OpenGL4; @@ -17,6 +18,11 @@ namespace SM.OGL.Framebuffer /// protected override bool AutoCompile { get; set; } = true; + /// + /// The window for the screen + /// + public static IFramebufferWindow ScreenWindow; + /// /// Represents the screen buffer. /// @@ -24,10 +30,12 @@ namespace SM.OGL.Framebuffer { _id = 0, CanCompile = false, + _window = ScreenWindow, + _windowScale = 1, }; - private readonly IFramebufferWindow _window; - private readonly float _windowScale; + private IFramebufferWindow _window; + private float _windowScale; /// public override ObjectLabelIdentifier TypeIdentifier { get; } = ObjectLabelIdentifier.Framebuffer; @@ -42,11 +50,12 @@ namespace SM.OGL.Framebuffer /// public Dictionary ColorAttachments { get; private set; } = new Dictionary(); - /// /// Contains the current renderbuffer attachments of the framebuffer. /// - public List RenderbufferAttachments { get; } = new List(); + public Dictionary RenderbufferAttachments { get; } = new Dictionary(); + + public ColorAttachment this[string colorName] => ColorAttachments[colorName]; /// /// Creates a buffer without any options. @@ -79,6 +88,7 @@ namespace SM.OGL.Framebuffer /// public override void Compile() { + if (_id == 0) _window = ScreenWindow; if (_window != null) Size = new Vector2(_window.Width * _windowScale, _window.Height * _windowScale); base.Compile(); @@ -99,10 +109,11 @@ namespace SM.OGL.Framebuffer GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, pair.Value.FramebufferAttachment, pair.Value.Target, pair.Value.ID, 0); - foreach (RenderbufferAttachment attachment in RenderbufferAttachments) + foreach (RenderbufferAttachment attachment in RenderbufferAttachments.Keys.ToArray()) { int att = attachment.Generate(this); GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, attachment.FramebufferAttachment, RenderbufferTarget.Renderbuffer, att); + RenderbufferAttachments[attachment] = att; } var err = GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer); @@ -118,6 +129,11 @@ namespace SM.OGL.Framebuffer { foreach (var attachment in ColorAttachments.Values) attachment.Dispose(); + foreach (KeyValuePair pair in RenderbufferAttachments.ToArray()) + { + GL.DeleteRenderbuffer(pair.Value); + RenderbufferAttachments[pair.Key] = -1; + } GL.DeleteFramebuffer(this); base.Dispose(); @@ -141,7 +157,7 @@ namespace SM.OGL.Framebuffer /// public void AppendRenderbuffer(RenderbufferAttachment attachment) { - RenderbufferAttachments.Add(attachment); + RenderbufferAttachments.Add(attachment, -1); } /// diff --git a/SMCode/SM.OGL/Mesh/GenericMesh.cs b/SMCode/SM.OGL/Mesh/GenericMesh.cs index cadd423..96e4b76 100644 --- a/SMCode/SM.OGL/Mesh/GenericMesh.cs +++ b/SMCode/SM.OGL/Mesh/GenericMesh.cs @@ -103,6 +103,29 @@ namespace SM.OGL.Mesh GL.BindVertexArray(0); } + /// + /// This updates the parts of the mesh, that needs updating. + /// + public void Update() + { + if (!WasCompiled) + { + Compile(); + return; + } + + GL.BindVertexArray(_id); + + UpdateBoundingBox(); + + foreach(var attrib in Attributes) + { + if (attrib.ConnectedVBO == null || !attrib.ConnectedVBO.Active || !attrib.ConnectedVBO.CanBeUpdated) continue; + attrib.ConnectedVBO.Update(); + } + + } + /// public override void Dispose() { diff --git a/SMCode/SM.OGL/Mesh/VBO.cs b/SMCode/SM.OGL/Mesh/VBO.cs index 738bb60..1fee8cc 100644 --- a/SMCode/SM.OGL/Mesh/VBO.cs +++ b/SMCode/SM.OGL/Mesh/VBO.cs @@ -1,5 +1,6 @@ #region usings +using System; using System.Collections.Generic; using OpenTK; using OpenTK.Graphics; @@ -14,6 +15,11 @@ namespace SM.OGL.Mesh /// public class VBO : List { + /// + /// The ID for the buffer. + /// + public int BufferID { get; private set; } + /// /// Specifies the expected usage pattern of the data store. /// @@ -51,6 +57,11 @@ namespace SM.OGL.Mesh /// public VertexAttribPointerType PointerType; + /// + /// If true it can be updated, otherwise it will get ignored, when the mesh gets updated. + /// + public bool CanBeUpdated = false; + /// /// Generates a VBO for inserting mesh data. /// @@ -91,12 +102,18 @@ namespace SM.OGL.Mesh Normalised = normalised; } + public void Add(float x) + { + CanBeUpdated = true; + } + /// /// Adds two values to the VBO. /// public void Add(float x, float y) { AddRange(new[] {x, y}); + CanBeUpdated = true; } /// @@ -105,6 +122,7 @@ namespace SM.OGL.Mesh public void Add(float x, float y, float z) { AddRange(new[] {x, y, z}); + CanBeUpdated = true; } /// @@ -113,6 +131,7 @@ namespace SM.OGL.Mesh public void Add(float x, float y, float z, float w) { AddRange(new[] {x, y, z, w}); + CanBeUpdated = true; } /// @@ -205,13 +224,23 @@ namespace SM.OGL.Mesh var data = ToArray(); - var buffer = GL.GenBuffer(); - GL.BindBuffer(BufferTarget.ArrayBuffer, buffer); + BufferID = GL.GenBuffer(); + GL.BindBuffer(BufferTarget.ArrayBuffer, BufferID); GL.BufferData(BufferTarget.ArrayBuffer, data.Length * sizeof(float), data, BufferUsageHint); GL.VertexAttribPointer(attribID, PointerSize, PointerType, Normalised, PointerStride, PointerOffset); GL.EnableVertexAttribArray(attribID); GL.BindBuffer(BufferTarget.ArrayBuffer, 0); + + CanBeUpdated = false; + } + + internal void Update() + { + var data = ToArray(); + + GL.BindBuffer(BufferTarget.ArrayBuffer, BufferID); + GL.BufferSubData(BufferTarget.ArrayBuffer, IntPtr.Zero, data.Length * sizeof(float), data); } } } \ No newline at end of file diff --git a/SMCode/SM2D/SM2D.csproj b/SMCode/SM2D/SM2D.csproj index f4b25f5..d58b4f3 100644 --- a/SMCode/SM2D/SM2D.csproj +++ b/SMCode/SM2D/SM2D.csproj @@ -53,6 +53,14 @@ + + + 3.3.1 + + + + + {8e733844-4204-43e7-b3dc-3913cddabb0d} @@ -63,14 +71,5 @@ SM.OGL - - - 3.3.1 - - - - - - \ No newline at end of file diff --git a/SM_TEST/Program.cs b/SM_TEST/Program.cs index 6fc29b1..63afed2 100644 --- a/SM_TEST/Program.cs +++ b/SM_TEST/Program.cs @@ -4,9 +4,12 @@ using OpenTK; using OpenTK.Graphics; using OpenTK.Input; using SM.Base; +using SM.Base.Time; using SM.Base.Window; using SM2D; +using SM2D.Controls; using SM2D.Drawing; +using SM2D.Object; using SM2D.Pipelines; using SM2D.Scene; using Font = SM.Base.Drawing.Text.Font; @@ -19,27 +22,42 @@ namespace SM_TEST static Scene scene; private static Font font; private static GLWindow window; + private static PolyLine line; static void Main(string[] args) { - window = new GLWindow(); + window = new GLWindow(1280, 720, "0ms", WindowFlags.Window, VSyncMode.Off); window.ApplySetup(new Window2DSetup()); + window.SetRenderPipeline(new TestRenderPipeline()); + window.SetScene(scene = new Scene()); - scene.Objects.Add(new DrawObject2D()); + + line = new PolyLine(new Vector2[] { Vector2.Zero, Vector2.One }, PolyLineType.Connected); + var display = new DrawObject2D() + { + Mesh = line + }; + display.Transform.Size.Set(1); + scene.Objects.Add(display); + window.UpdateFrame += WindowOnUpdateFrame; + window.RenderFrame += Window_RenderFrame; window.Run(); Debug.WriteLine("Window Closed"); } + private static void Window_RenderFrame(object sender, FrameEventArgs e) + { + window.Title = Math.Floor(e.Time * 1000) + "ms"; + } + private static void WindowOnUpdateFrame(object sender, FrameEventArgs e) { - if (SM.Base.Controls.Keyboard.IsDown(Key.F, true)) - { - window.WindowFlags = WindowFlags.ExclusiveFullscreen; - window.ChangeFullscreenResolution(DisplayDevice.Default.SelectResolution(1280,720, DisplayDevice.Default.BitsPerPixel, DisplayDevice.Default.RefreshRate)); - } - if (SM.Base.Controls.Keyboard.IsDown(Key.W, true)) window.WindowFlags = WindowFlags.Window; - if (SM.Base.Controls.Keyboard.IsDown(Key.B, true)) window.WindowFlags = WindowFlags.BorderlessWindow; + + line.Vertex.RemoveRange(3, 3); + line.Vertex.Add(Mouse2D.InWorld(window.ViewportCamera as Camera), 0); + line.Update(); + } diff --git a/SM_TEST/SM_TEST.csproj b/SM_TEST/SM_TEST.csproj index b84ebe5..5cd19ac 100644 --- a/SM_TEST/SM_TEST.csproj +++ b/SM_TEST/SM_TEST.csproj @@ -5,7 +5,7 @@ Debug AnyCPU {6D4FB8E6-4D0B-4928-8F9E-EF5C2FBF44E8} - Exe + WinExe SM_TEST SM_TEST v4.5.2 @@ -32,6 +32,9 @@ prompt 4 + + + ..\packages\OpenTK.3.3.1\lib\net20\OpenTK.dll diff --git a/SM_TEST/TestRenderPipeline.cs b/SM_TEST/TestRenderPipeline.cs index 652abd6..7191e71 100644 --- a/SM_TEST/TestRenderPipeline.cs +++ b/SM_TEST/TestRenderPipeline.cs @@ -2,6 +2,7 @@ using SM.Base.PostEffects; using SM.Base.Window; using SM.OGL.Framebuffer; +using SM.OGL.Texture; namespace SM_TEST { @@ -13,11 +14,11 @@ namespace SM_TEST public override void Initialization() { - MainFramebuffer = CreateWindowFramebuffer(0); + MainFramebuffer = CreateWindowFramebuffer(16, PixelInformation.RGBA_HDR); - _postBuffer = CreateWindowFramebuffer(); + _postBuffer = CreateWindowFramebuffer(0, PixelInformation.RGBA_HDR, depth: false); Framebuffers.Add(_postBuffer); - _bloom = new BloomEffect(MainFramebuffer, hdr: true, .75f) + _bloom = new BloomEffect(_postBuffer, hdr: true, .5f) { Threshold = .5f, }; @@ -33,9 +34,13 @@ namespace SM_TEST context.Scene.DrawBackground(context); context.Scene.DrawMainObjects(context); context.Scene.DrawHUD(context); - + + PostProcessUtility.ResolveMultisampledBuffers(MainFramebuffer, _postBuffer); + + //_bloom.Draw(context); Framebuffer.Screen.Activate(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); - _bloom.Draw(context); + + PostProcessUtility.FinalizeHDR(_postBuffer["color"], .5f); context.Scene.DrawDebug(context); }