diff --git a/FModel/Constants.cs b/FModel/Constants.cs index 6deb29c7..0b6d0157 100644 --- a/FModel/Constants.cs +++ b/FModel/Constants.cs @@ -10,6 +10,7 @@ public static class Constants public static readonly FGuid ZERO_GUID = new(0U); public const float SCALE_DOWN_RATIO = 0.01F; + public const uint SAMPLES_COUNT = 4; public const string WHITE = "#DAE5F2"; public const string GRAY = "#BBBBBB"; diff --git a/FModel/Extensions/ImGuiExtensions.cs b/FModel/Extensions/ImGuiExtensions.cs index 0b293077..f317e889 100644 --- a/FModel/Extensions/ImGuiExtensions.cs +++ b/FModel/Extensions/ImGuiExtensions.cs @@ -1,12 +1,30 @@ using System.Numerics; +using FModel.Views.Snooper; using ImGuiNET; +using Silk.NET.Input; +using Silk.NET.Maths; namespace FModel.Extensions; public static class ImGuiExtensions { - public const float PADDING = 5.0f; - public static ImGuiStylePtr STYLE = ImGui.GetStyle(); + public const float PADDING = 2.5f; + + private static bool _viewportFocus; + + public static void DrawDockSpace(Vector2D size) + { + const ImGuiWindowFlags flags = + ImGuiWindowFlags.MenuBar | ImGuiWindowFlags.NoDocking | + ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoResize | + ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoMove | + ImGuiWindowFlags.NoBringToFrontOnFocus | ImGuiWindowFlags.NoNavFocus; + + ImGui.SetNextWindowPos(new Vector2(0, 0)); + ImGui.SetNextWindowSize(new Vector2(size.X, size.Y)); + ImGui.Begin("Snooper", flags); + ImGui.DockSpace(ImGui.GetID("Snooper")); + } public static void DrawNavbar() { @@ -50,58 +68,123 @@ public static class ImGuiExtensions ImGui.End(); } + public static void DrawViewport(FramebufferObject framebuffer, Camera camera, IMouse mouse) + { + const float lookSensitivity = 0.1f; + const ImGuiWindowFlags flags = ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoScrollWithMouse; + + ImGui.Begin("Viewport", flags); + + var largest = ImGui.GetContentRegionAvail(); + largest.X -= ImGui.GetScrollX(); + largest.Y -= ImGui.GetScrollY(); + + var width = largest.X; + var height = width / camera.AspectRatio; + if (height > largest.Y) + { + height = largest.Y; + width = height * camera.AspectRatio; + } + + var pos = new Vector2(largest.X / 2f - width / 2f + ImGui.GetCursorPosX(), largest.Y / 2f - height / 2f + ImGui.GetCursorPosY()); + ImGui.SetCursorPos(pos); + ImGui.ImageButton(framebuffer.GetPointer(), new Vector2(width, height), new Vector2(0, 1), new Vector2(1, 0), 0); + + // it took me 5 hours to make it work, don't change any of the following code + // basically the Raw cursor doesn't actually freeze the mouse position + // so for ImGui, the IsItemHovered will be false if mouse leave, even in Raw mode + var io = ImGui.GetIO(); + if (ImGui.IsItemHovered()) + { + camera.ModifyZoom(io.MouseWheel); + + // if left button down while mouse is hover viewport + if (ImGui.IsMouseDown(ImGuiMouseButton.Left) && !_viewportFocus) + _viewportFocus = true; + } + + // this can't be inside IsItemHovered! read it as + // if left mouse button was pressed while hovering the viewport + // move camera until left mouse button is released + // no matter where mouse position end up + if (ImGui.IsMouseDragging(ImGuiMouseButton.Left, lookSensitivity) && _viewportFocus) + { + var delta = io.MouseDelta * lookSensitivity; + camera.ModifyDirection(delta.X, delta.Y); + mouse.Cursor.CursorMode = CursorMode.Raw; + } + + // if left button up and mouse was in viewport + if (ImGui.IsMouseReleased(ImGuiMouseButton.Left) && _viewportFocus) + { + _viewportFocus = false; + mouse.Cursor.CursorMode = CursorMode.Normal; + } + + ImGui.End(); + } + public static void Theme() { - STYLE.FrameRounding = 4.0f; - STYLE.GrabRounding = 4.0f; + var io = ImGui.GetIO(); + io.ConfigFlags |= ImGuiConfigFlags.DockingEnable; + io.ConfigFlags |= ImGuiConfigFlags.ViewportsEnable; + io.ConfigWindowsMoveFromTitleBarOnly = true; + io.ConfigWindowsResizeFromEdges = false; - STYLE.Colors[(int) ImGuiCol.Text] = new Vector4(0.95f, 0.96f, 0.98f, 1.00f); - STYLE.Colors[(int) ImGuiCol.TextDisabled] = new Vector4(0.36f, 0.42f, 0.47f, 1.00f); - STYLE.Colors[(int) ImGuiCol.WindowBg] = new Vector4(0.11f, 0.15f, 0.17f, 0.35f); - STYLE.Colors[(int) ImGuiCol.ChildBg] = new Vector4(0.15f, 0.18f, 0.22f, 1.00f); - STYLE.Colors[(int) ImGuiCol.PopupBg] = new Vector4(0.08f, 0.08f, 0.08f, 0.94f); - STYLE.Colors[(int) ImGuiCol.Border] = new Vector4(0.08f, 0.10f, 0.12f, 1.00f); - STYLE.Colors[(int) ImGuiCol.BorderShadow] = new Vector4(0.00f, 0.00f, 0.00f, 0.00f); - STYLE.Colors[(int) ImGuiCol.FrameBg] = new Vector4(0.20f, 0.25f, 0.29f, 1.00f); - STYLE.Colors[(int) ImGuiCol.FrameBgHovered] = new Vector4(0.12f, 0.20f, 0.28f, 1.00f); - STYLE.Colors[(int) ImGuiCol.FrameBgActive] = new Vector4(0.09f, 0.12f, 0.14f, 1.00f); - STYLE.Colors[(int) ImGuiCol.TitleBg] = new Vector4(0.09f, 0.12f, 0.14f, 0.65f); - STYLE.Colors[(int) ImGuiCol.TitleBgActive] = new Vector4(0.08f, 0.10f, 0.12f, 1.00f); - STYLE.Colors[(int) ImGuiCol.TitleBgCollapsed] = new Vector4(0.00f, 0.00f, 0.00f, 0.51f); - STYLE.Colors[(int) ImGuiCol.MenuBarBg] = new Vector4(0.15f, 0.18f, 0.22f, 1.00f); - STYLE.Colors[(int) ImGuiCol.ScrollbarBg] = new Vector4(0.02f, 0.02f, 0.02f, 0.39f); - STYLE.Colors[(int) ImGuiCol.ScrollbarGrab] = new Vector4(0.20f, 0.25f, 0.29f, 1.00f); - STYLE.Colors[(int) ImGuiCol.ScrollbarGrabHovered] = new Vector4(0.18f, 0.22f, 0.25f, 1.00f); - STYLE.Colors[(int) ImGuiCol.ScrollbarGrabActive] = new Vector4(0.09f, 0.21f, 0.31f, 1.00f); - STYLE.Colors[(int) ImGuiCol.CheckMark] = new Vector4(0.28f, 0.56f, 1.00f, 1.00f); - STYLE.Colors[(int) ImGuiCol.SliderGrab] = new Vector4(0.28f, 0.56f, 1.00f, 1.00f); - STYLE.Colors[(int) ImGuiCol.SliderGrabActive] = new Vector4(0.37f, 0.61f, 1.00f, 1.00f); - STYLE.Colors[(int) ImGuiCol.Button] = new Vector4(0.20f, 0.25f, 0.29f, 1.00f); - STYLE.Colors[(int) ImGuiCol.ButtonHovered] = new Vector4(0.28f, 0.56f, 1.00f, 1.00f); - STYLE.Colors[(int) ImGuiCol.ButtonActive] = new Vector4(0.06f, 0.53f, 0.98f, 1.00f); - STYLE.Colors[(int) ImGuiCol.Header] = new Vector4(0.20f, 0.25f, 0.29f, 0.55f); - STYLE.Colors[(int) ImGuiCol.HeaderHovered] = new Vector4(0.26f, 0.59f, 0.98f, 0.80f); - STYLE.Colors[(int) ImGuiCol.HeaderActive] = new Vector4(0.26f, 0.59f, 0.98f, 1.00f); - STYLE.Colors[(int) ImGuiCol.Separator] = new Vector4(0.20f, 0.25f, 0.29f, 1.00f); - STYLE.Colors[(int) ImGuiCol.SeparatorHovered] = new Vector4(0.10f, 0.40f, 0.75f, 0.78f); - STYLE.Colors[(int) ImGuiCol.SeparatorActive] = new Vector4(0.10f, 0.40f, 0.75f, 1.00f); - STYLE.Colors[(int) ImGuiCol.ResizeGrip] = new Vector4(0.26f, 0.59f, 0.98f, 0.25f); - STYLE.Colors[(int) ImGuiCol.ResizeGripHovered] = new Vector4(0.26f, 0.59f, 0.98f, 0.67f); - STYLE.Colors[(int) ImGuiCol.ResizeGripActive] = new Vector4(0.26f, 0.59f, 0.98f, 0.95f); - STYLE.Colors[(int) ImGuiCol.Tab] = new Vector4(0.11f, 0.15f, 0.17f, 1.00f); - STYLE.Colors[(int) ImGuiCol.TabHovered] = new Vector4(0.26f, 0.59f, 0.98f, 0.80f); - STYLE.Colors[(int) ImGuiCol.TabActive] = new Vector4(0.20f, 0.25f, 0.29f, 1.00f); - STYLE.Colors[(int) ImGuiCol.TabUnfocused] = new Vector4(0.11f, 0.15f, 0.17f, 1.00f); - STYLE.Colors[(int) ImGuiCol.TabUnfocusedActive] = new Vector4(0.11f, 0.15f, 0.17f, 1.00f); - STYLE.Colors[(int) ImGuiCol.PlotLines] = new Vector4(0.61f, 0.61f, 0.61f, 1.00f); - STYLE.Colors[(int) ImGuiCol.PlotLinesHovered] = new Vector4(1.00f, 0.43f, 0.35f, 1.00f); - STYLE.Colors[(int) ImGuiCol.PlotHistogram] = new Vector4(0.90f, 0.70f, 0.00f, 1.00f); - STYLE.Colors[(int) ImGuiCol.PlotHistogramHovered] = new Vector4(1.00f, 0.60f, 0.00f, 1.00f); - STYLE.Colors[(int) ImGuiCol.TextSelectedBg] = new Vector4(0.26f, 0.59f, 0.98f, 0.35f); - STYLE.Colors[(int) ImGuiCol.DragDropTarget] = new Vector4(1.00f, 1.00f, 0.00f, 0.90f); - STYLE.Colors[(int) ImGuiCol.NavHighlight] = new Vector4(0.26f, 0.59f, 0.98f, 1.00f); - STYLE.Colors[(int) ImGuiCol.NavWindowingHighlight] = new Vector4(1.00f, 1.00f, 1.00f, 0.70f); - STYLE.Colors[(int) ImGuiCol.NavWindowingDimBg] = new Vector4(0.80f, 0.80f, 0.80f, 0.20f); - STYLE.Colors[(int) ImGuiCol.ModalWindowDimBg] = new Vector4(0.80f, 0.80f, 0.80f, 0.35f); + var style = ImGui.GetStyle(); + style.FrameRounding = 2.0f; + style.GrabRounding = 2.0f; + style.WindowPadding = Vector2.Zero; + + // style.Colors[(int) ImGuiCol.Text] = new Vector4(0.95f, 0.96f, 0.98f, 1.00f); + // style.Colors[(int) ImGuiCol.TextDisabled] = new Vector4(0.36f, 0.42f, 0.47f, 1.00f); + // style.Colors[(int) ImGuiCol.WindowBg] = new Vector4(0.149f, 0.149f, 0.188f, 0.35f); + // style.Colors[(int) ImGuiCol.ChildBg] = new Vector4(0.15f, 0.18f, 0.22f, 1.00f); + // style.Colors[(int) ImGuiCol.PopupBg] = new Vector4(0.08f, 0.08f, 0.08f, 0.94f); + // style.Colors[(int) ImGuiCol.Border] = new Vector4(0.08f, 0.10f, 0.12f, 1.00f); + // style.Colors[(int) ImGuiCol.BorderShadow] = new Vector4(0.00f, 0.00f, 0.00f, 0.00f); + // style.Colors[(int) ImGuiCol.FrameBg] = new Vector4(0.20f, 0.25f, 0.29f, 1.00f); + // style.Colors[(int) ImGuiCol.FrameBgHovered] = new Vector4(0.12f, 0.20f, 0.28f, 1.00f); + // style.Colors[(int) ImGuiCol.FrameBgActive] = new Vector4(0.09f, 0.12f, 0.14f, 1.00f); + // style.Colors[(int) ImGuiCol.TitleBg] = new Vector4(0.09f, 0.12f, 0.14f, 0.65f); + // style.Colors[(int) ImGuiCol.TitleBgActive] = new Vector4(0.08f, 0.10f, 0.12f, 1.00f); + // style.Colors[(int) ImGuiCol.TitleBgCollapsed] = new Vector4(0.00f, 0.00f, 0.00f, 0.51f); + // style.Colors[(int) ImGuiCol.MenuBarBg] = new Vector4(0.15f, 0.18f, 0.22f, 1.00f); + // style.Colors[(int) ImGuiCol.ScrollbarBg] = new Vector4(0.02f, 0.02f, 0.02f, 0.39f); + // style.Colors[(int) ImGuiCol.ScrollbarGrab] = new Vector4(0.20f, 0.25f, 0.29f, 1.00f); + // style.Colors[(int) ImGuiCol.ScrollbarGrabHovered] = new Vector4(0.18f, 0.22f, 0.25f, 1.00f); + // style.Colors[(int) ImGuiCol.ScrollbarGrabActive] = new Vector4(0.09f, 0.21f, 0.31f, 1.00f); + // style.Colors[(int) ImGuiCol.CheckMark] = new Vector4(0.28f, 0.56f, 1.00f, 1.00f); + // style.Colors[(int) ImGuiCol.SliderGrab] = new Vector4(0.28f, 0.56f, 1.00f, 1.00f); + // style.Colors[(int) ImGuiCol.SliderGrabActive] = new Vector4(0.37f, 0.61f, 1.00f, 1.00f); + // style.Colors[(int) ImGuiCol.Button] = new Vector4(0.20f, 0.25f, 0.29f, 1.00f); + // style.Colors[(int) ImGuiCol.ButtonHovered] = new Vector4(0.28f, 0.56f, 1.00f, 1.00f); + // style.Colors[(int) ImGuiCol.ButtonActive] = new Vector4(0.06f, 0.53f, 0.98f, 1.00f); + // style.Colors[(int) ImGuiCol.Header] = new Vector4(0.20f, 0.25f, 0.29f, 0.55f); + // style.Colors[(int) ImGuiCol.HeaderHovered] = new Vector4(0.26f, 0.59f, 0.98f, 0.80f); + // style.Colors[(int) ImGuiCol.HeaderActive] = new Vector4(0.26f, 0.59f, 0.98f, 1.00f); + // style.Colors[(int) ImGuiCol.Separator] = new Vector4(0.20f, 0.25f, 0.29f, 1.00f); + // style.Colors[(int) ImGuiCol.SeparatorHovered] = new Vector4(0.10f, 0.40f, 0.75f, 0.78f); + // style.Colors[(int) ImGuiCol.SeparatorActive] = new Vector4(0.10f, 0.40f, 0.75f, 1.00f); + // style.Colors[(int) ImGuiCol.ResizeGrip] = new Vector4(0.26f, 0.59f, 0.98f, 0.25f); + // style.Colors[(int) ImGuiCol.ResizeGripHovered] = new Vector4(0.26f, 0.59f, 0.98f, 0.67f); + // style.Colors[(int) ImGuiCol.ResizeGripActive] = new Vector4(0.26f, 0.59f, 0.98f, 0.95f); + // style.Colors[(int) ImGuiCol.Tab] = new Vector4(0.11f, 0.15f, 0.17f, 1.00f); + // style.Colors[(int) ImGuiCol.TabHovered] = new Vector4(0.26f, 0.59f, 0.98f, 0.80f); + // style.Colors[(int) ImGuiCol.TabActive] = new Vector4(0.20f, 0.25f, 0.29f, 1.00f); + // style.Colors[(int) ImGuiCol.TabUnfocused] = new Vector4(0.11f, 0.15f, 0.17f, 1.00f); + // style.Colors[(int) ImGuiCol.TabUnfocusedActive] = new Vector4(0.11f, 0.15f, 0.17f, 1.00f); + // style.Colors[(int) ImGuiCol.PlotLines] = new Vector4(0.61f, 0.61f, 0.61f, 1.00f); + // style.Colors[(int) ImGuiCol.PlotLinesHovered] = new Vector4(1.00f, 0.43f, 0.35f, 1.00f); + // style.Colors[(int) ImGuiCol.PlotHistogram] = new Vector4(0.90f, 0.70f, 0.00f, 1.00f); + // style.Colors[(int) ImGuiCol.PlotHistogramHovered] = new Vector4(1.00f, 0.60f, 0.00f, 1.00f); + // style.Colors[(int) ImGuiCol.TextSelectedBg] = new Vector4(0.26f, 0.59f, 0.98f, 0.35f); + // style.Colors[(int) ImGuiCol.DragDropTarget] = new Vector4(1.00f, 1.00f, 0.00f, 0.90f); + // style.Colors[(int) ImGuiCol.NavHighlight] = new Vector4(0.26f, 0.59f, 0.98f, 1.00f); + // style.Colors[(int) ImGuiCol.NavWindowingHighlight] = new Vector4(1.00f, 1.00f, 1.00f, 0.70f); + // style.Colors[(int) ImGuiCol.NavWindowingDimBg] = new Vector4(0.80f, 0.80f, 0.80f, 0.20f); + // style.Colors[(int) ImGuiCol.ModalWindowDimBg] = new Vector4(0.80f, 0.80f, 0.80f, 0.35f); } } diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj index c11e65eb..1dcb7ee1 100644 --- a/FModel/FModel.csproj +++ b/FModel/FModel.csproj @@ -99,6 +99,8 @@ + + @@ -114,6 +116,8 @@ + + diff --git a/FModel/Resources/framebuffer.frag b/FModel/Resources/framebuffer.frag new file mode 100644 index 00000000..a039b285 --- /dev/null +++ b/FModel/Resources/framebuffer.frag @@ -0,0 +1,12 @@ +#version 330 core + +in vec2 fTexCoords; + +uniform sampler2D screenTexture; + +out vec4 FragColor; + +void main() +{ + FragColor = texture(screenTexture, fTexCoords); +} diff --git a/FModel/Resources/framebuffer.vert b/FModel/Resources/framebuffer.vert new file mode 100644 index 00000000..3d332f17 --- /dev/null +++ b/FModel/Resources/framebuffer.vert @@ -0,0 +1,12 @@ +#version 330 core + +layout (location = 0) in vec2 vPos; +layout (location = 1) in vec2 vTexCoords; + +out vec2 fTexCoords; + +void main() +{ + gl_Position = vec4(vPos.x, vPos.y, 0.0, 1.0); + fTexCoords = vTexCoords; +} diff --git a/FModel/Views/Snooper/FramebufferObject.cs b/FModel/Views/Snooper/FramebufferObject.cs new file mode 100644 index 00000000..90852810 --- /dev/null +++ b/FModel/Views/Snooper/FramebufferObject.cs @@ -0,0 +1,104 @@ +using System; +using Silk.NET.Maths; +using Silk.NET.OpenGL; + +namespace FModel.Views.Snooper; + +public class FramebufferObject : IDisposable +{ + private uint _handle; + private GL _gl; + + private readonly int _width; + private readonly int _height; + private readonly RenderbufferObject _renderbuffer; + + private BufferObject _ebo; + private BufferObject _vbo; + private VertexArrayObject _vao; + + private Shader _shader; + private Texture _texture; + + public readonly uint[] Indices = { 0, 1, 2, 3, 4, 5 }; + public readonly float[] Vertices = { + // Coords // texCoords + 1.0f, -1.0f, 1.0f, 0.0f, + -1.0f, -1.0f, 0.0f, 0.0f, + -1.0f, 1.0f, 0.0f, 1.0f, + + 1.0f, 1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, 0.0f, + -1.0f, 1.0f, 0.0f, 1.0f + }; + + public FramebufferObject(Vector2D size) + { + _width = size.X; + _height = size.Y; + _renderbuffer = new RenderbufferObject((uint) _width, (uint) _height); + } + + public void Setup(GL gl) + { + _gl = gl; + _handle = _gl.GenFramebuffer(); + Bind(); + + _texture = new Texture(_gl, (uint) _width, (uint) _height); + + _renderbuffer.Setup(gl); + + _shader = new Shader(_gl, "framebuffer.vert", "framebuffer.frag"); + _shader.Use(); + _shader.SetUniform("screenTexture", 0); + + _ebo = new BufferObject(_gl, Indices, BufferTargetARB.ElementArrayBuffer); + _vbo = new BufferObject(_gl, Vertices, BufferTargetARB.ArrayBuffer); + _vao = new VertexArrayObject(_gl, _vbo, _ebo); + + _vao.VertexAttributePointer(0, 2, VertexAttribPointerType.Float, 4, 0); // position + _vao.VertexAttributePointer(1, 2, VertexAttribPointerType.Float, 4, 2); // uv + + var status = _gl.CheckFramebufferStatus(FramebufferTarget.Framebuffer); + if (status != GLEnum.FramebufferComplete) + { + throw new Exception($"Framebuffer failed to bind with error: {_gl.GetProgramInfoLog(_handle)}"); + } + } + + public void Bind() + { + _gl.BindFramebuffer(FramebufferTarget.DrawFramebuffer, _handle); + } + + public void UnBind() + { + _gl.BindFramebuffer(FramebufferTarget.DrawFramebuffer, 0); + } + + public void BindStuff() + { + _gl.DepthMask(false); + + _shader.Use(); + _vao.Bind(); + + _texture.Bind(TextureUnit.Texture0); + + _gl.DrawArrays(PrimitiveType.Triangles, 0, (uint) Indices.Length); + + _gl.DepthMask(true); + } + + public IntPtr GetPointer() => _texture.GetPointer(); + + public void Dispose() + { + _vao.Dispose(); + _shader.Dispose(); + _texture.Dispose(); + _renderbuffer.Dispose(); + _gl.DeleteFramebuffer(_handle); + } +} diff --git a/FModel/Views/Snooper/Model.cs b/FModel/Views/Snooper/Model.cs index c6befbc6..b63f329a 100644 --- a/FModel/Views/Snooper/Model.cs +++ b/FModel/Views/Snooper/Model.cs @@ -99,25 +99,15 @@ public class Model : IDisposable public void Bind(Shader shader) { - ImGui.Text($"Entity: {Name}"); - if (HasVertexColors) - ImGui.Checkbox("Display Vertex Colors", ref _display_vertex_colors); - _vao.Bind(); shader.SetUniform("display_vertex_colors", _display_vertex_colors); - ImGui.BeginTable("Sections", 2, ImGuiTableFlags.RowBg); - ImGui.TableSetupColumn("Index", ImGuiTableColumnFlags.WidthFixed); - ImGui.TableSetupColumn("Material", ImGuiTableColumnFlags.WidthFixed); - ImGui.TableHeadersRow(); + DrawImGui(); for (int section = 0; section < Sections.Length; section++) { Sections[section].Bind(shader, Indices.Length); - // if (!Sections[section].Show) continue; - _gl.DrawArrays(PrimitiveType.Triangles, Sections[section].FirstFaceIndex, Sections[section].FacesCount); } - ImGui.EndTable(); ImGui.Separator(); } @@ -133,4 +123,11 @@ public class Model : IDisposable } _gl.DeleteProgram(_handle); } + + private void DrawImGui() + { + ImGui.Text($"Entity: {Name}"); + if (HasVertexColors) + ImGui.Checkbox("Display Vertex Colors", ref _display_vertex_colors); + } } diff --git a/FModel/Views/Snooper/RenderbufferObject.cs b/FModel/Views/Snooper/RenderbufferObject.cs new file mode 100644 index 00000000..bf1fee56 --- /dev/null +++ b/FModel/Views/Snooper/RenderbufferObject.cs @@ -0,0 +1,34 @@ +using System; +using Silk.NET.OpenGL; + +namespace FModel.Views.Snooper; + +public class RenderbufferObject : IDisposable +{ + private uint _handle; + private GL _gl; + + private readonly uint _width; + private readonly uint _height; + + public RenderbufferObject(uint width, uint height) + { + _width = width; + _height = height; + } + + public void Setup(GL gl) + { + _gl = gl; + _handle = _gl.GenRenderbuffer(); + + _gl.BindRenderbuffer(RenderbufferTarget.Renderbuffer, _handle); + _gl.RenderbufferStorage(RenderbufferTarget.Renderbuffer, InternalFormat.Depth24Stencil8, _width, _height); + _gl.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthStencilAttachment, RenderbufferTarget.Renderbuffer, _handle); + } + + public void Dispose() + { + _gl.DeleteRenderbuffer(_handle); + } +} diff --git a/FModel/Views/Snooper/Section.cs b/FModel/Views/Snooper/Section.cs index 995ccf52..760d38de 100644 --- a/FModel/Views/Snooper/Section.cs +++ b/FModel/Views/Snooper/Section.cs @@ -39,11 +39,7 @@ public class Section : IDisposable public readonly CMaterialParams Parameters; private bool _show = true; - public bool Show - { - get => _show; - set => _show = value; - } + private bool _wireframe; public Section(string name, int index, uint facesCount, int firstFaceIndex, CMeshSection section) { @@ -225,33 +221,35 @@ public class Section : IDisposable public void Bind(Shader shader, float indices) { - ImGui.TableNextRow(); + // ImGui.TableNextRow(); + // + // ImGui.TableSetColumnIndex(0); + // ImGui.Text(Index.ToString()); + // ImGui.TableSetColumnIndex(1); + // ImGui.Text(Name); + // if (ImGui.IsItemHovered()) + // { + // ImGui.BeginTooltip(); + // ImGui.Text($"Faces: {FacesCount} ({Math.Round(FacesCount / indices * 100f, 2)}%%)"); + // ImGui.Text($"First Face: {FirstFaceIndex}"); + // ImGui.Separator(); + // if (_hasDiffuseColor) + // { + // ImGui.ColorEdit4("Diffuse Color", ref _diffuseColor, ImGuiColorEditFlags.NoInputs); + // } + // else + // { + // ImGui.Text($"Diffuse: ({Parameters.Diffuse?.ExportType}) {Parameters.Diffuse?.Name}"); + // ImGui.Text($"Normal: ({Parameters.Normal?.ExportType}) {Parameters.Normal?.Name}"); + // ImGui.Text($"Specular: ({Parameters.Specular?.ExportType}) {Parameters.Specular?.Name}"); + // if (Parameters.HasTopEmissiveTexture) + // ImGui.Text($"Emissive: ({Parameters.Emissive?.ExportType}) {Parameters.Emissive?.Name}"); + // ImGui.Separator(); + // } + // ImGui.EndTooltip(); + // } - ImGui.TableSetColumnIndex(0); - ImGui.Text(Index.ToString()); - ImGui.TableSetColumnIndex(1); - ImGui.Text(Name); - if (ImGui.IsItemHovered()) - { - ImGui.BeginTooltip(); - ImGui.Text($"Faces: {FacesCount} ({Math.Round(FacesCount / indices * 100f, 2)}%%)"); - ImGui.Text($"First Face: {FirstFaceIndex}"); - ImGui.Separator(); - if (_hasDiffuseColor) - { - ImGui.ColorEdit4("Diffuse Color", ref _diffuseColor, ImGuiColorEditFlags.NoInputs); - } - else - { - ImGui.Text($"Diffuse: ({Parameters.Diffuse?.ExportType}) {Parameters.Diffuse?.Name}"); - ImGui.Text($"Normal: ({Parameters.Normal?.ExportType}) {Parameters.Normal?.Name}"); - ImGui.Text($"Specular: ({Parameters.Specular?.ExportType}) {Parameters.Specular?.Name}"); - if (Parameters.HasTopEmissiveTexture) - ImGui.Text($"Emissive: ({Parameters.Emissive?.ExportType}) {Parameters.Emissive?.Name}"); - ImGui.Separator(); - } - ImGui.EndTooltip(); - } + // DrawImGui(); _diffuseMap?.Bind(TextureUnit.Texture0); _normalMap?.Bind(TextureUnit.Texture1); @@ -270,6 +268,9 @@ public class Section : IDisposable shader.SetUniform("light.ambient", _ambientLight); shader.SetUniform("light.diffuse", _diffuseLight); shader.SetUniform("light.specular", _specularLight); + + _gl.PolygonMode(MaterialFace.Front, _wireframe ? PolygonMode.Line : PolygonMode.Fill); + if (_show) _gl.DrawArrays(PrimitiveType.Triangles, FirstFaceIndex, FacesCount); } public void Dispose() @@ -280,4 +281,11 @@ public class Section : IDisposable _emissionMap?.Dispose(); _gl.DeleteProgram(_handle); } + + private void DrawImGui() + { + ImGui.Checkbox($"Show {Name}", ref _show); + ImGui.Checkbox($"Wireframe {Name}", ref _wireframe); + ImGui.Separator(); + } } diff --git a/FModel/Views/Snooper/Snooper.cs b/FModel/Views/Snooper/Snooper.cs index e32960a8..6c0ccd08 100644 --- a/FModel/Views/Snooper/Snooper.cs +++ b/FModel/Views/Snooper/Snooper.cs @@ -30,31 +30,28 @@ public class Snooper private Camera _camera; private IKeyboard _keyboard; private IMouse _mouse; - private Vector2 _previousMousePosition; private RawImage _icon; + private readonly FramebufferObject _framebuffer; private readonly Skybox _skybox; private readonly Grid _grid; private readonly List _models; private Shader _shader; - private readonly int _width; - private readonly int _height; + private Vector2D _size; public Snooper() { const double ratio = .7; var x = SystemParameters.MaximizedPrimaryScreenWidth; var y = SystemParameters.MaximizedPrimaryScreenHeight; - _width = Convert.ToInt32(x * ratio); - _height = Convert.ToInt32(y * ratio); var options = WindowOptions.Default; - options.Size = new Vector2D(_width, _height); + options.Size = _size = new Vector2D(Convert.ToInt32(x * ratio), Convert.ToInt32(y * ratio)); options.WindowBorder = WindowBorder.Hidden; options.Title = "Snooper"; - options.Samples = 4; + options.Samples = (int) Constants.SAMPLES_COUNT; _window = Silk.NET.Windowing.Window.Create(options); unsafe @@ -76,8 +73,13 @@ public class Snooper _window.Update += OnUpdate; _window.Render += OnRender; _window.Closing += OnClose; - _window.FramebufferResize += OnFramebufferResize; + _window.FramebufferResize += delegate(Vector2D vector2D) + { + _gl.Viewport(vector2D); + _size = vector2D; + }; + _framebuffer = new FramebufferObject(_size); _skybox = new Skybox(); _grid = new Grid(); _models = new List(); @@ -123,21 +125,15 @@ public class Snooper _keyboard = input.Keyboards[0]; _keyboard.KeyDown += KeyDown; _mouse = input.Mice[0]; - _mouse.MouseDown += OnMouseDown; - _mouse.MouseUp += OnMouseUp; - _mouse.MouseMove += OnMouseMove; - _mouse.Scroll += OnMouseWheel; _gl = GL.GetApi(_window); - _gl.Enable(EnableCap.Blend); - _gl.Enable(EnableCap.DepthTest); _gl.Enable(EnableCap.Multisample); - _gl.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); _controller = new ImGuiController(_gl, _window, input); - // ImGuiExtensions.Theme(); + ImGuiExtensions.Theme(); + _framebuffer.Setup(_gl); _skybox.Setup(_gl); _grid.Setup(_gl); @@ -148,18 +144,24 @@ public class Snooper } } - private void OnFramebufferResize(Vector2D size) - { - _gl.Viewport(size); - } - + /// + /// friendly reminder this is called each frame + /// don't do crazy things inside + /// private void OnRender(double deltaTime) { _controller.Update((float) deltaTime); - _gl.ClearColor(0.102f, 0.102f, 0.129f, 1.0f); - _gl.Clear((uint) ClearBufferMask.ColorBufferBit | (uint) ClearBufferMask.DepthBufferBit); + ClearWhatHasBeenDrawn(); // in main window + _framebuffer.Bind(); // switch to dedicated window + ClearWhatHasBeenDrawn(); // in dedicated window + + ImGuiExtensions.DrawDockSpace(_size); + ImGuiExtensions.DrawNavbar(); + ImGui.ShowDemoWindow(); + + _framebuffer.BindStuff(); _skybox.Bind(_camera); _grid.Bind(_camera); @@ -175,18 +177,30 @@ public class Snooper _shader.SetUniform("material.specularMap", 2); _shader.SetUniform("material.emissionMap", 3); - ImGuiExtensions.DrawNavbar(); - ImGui.Begin("ImGui.NET", ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoBringToFrontOnFocus | ImGuiWindowFlags.NoSavedSettings); + _shader.SetUniform("light.position", _camera.Position); + + ImGui.Begin("ImGui.NET"); foreach (var model in _models) { model.Bind(_shader); } ImGui.End(); + + ImGuiExtensions.DrawViewport(_framebuffer, _camera, _mouse); ImGuiExtensions.DrawFPS(); - _shader.SetUniform("light.position", _camera.Position); + _framebuffer.UnBind(); // switch back to main window + _controller.Render(); // render ImGui in main window + } - _controller.Render(); + private void ClearWhatHasBeenDrawn() + { + _gl.Enable(EnableCap.Blend); + _gl.Enable(EnableCap.DepthTest); + _gl.ClearColor(1.0f, 0.102f, 0.129f, 1.0f); + _gl.Clear((uint) ClearBufferMask.ColorBufferBit | (uint) ClearBufferMask.DepthBufferBit); + _gl.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); + _gl.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); } private void OnUpdate(double deltaTime) @@ -219,43 +233,9 @@ public class Snooper } } - private void OnMouseDown(IMouse mouse, MouseButton button) - { - if (button != MouseButton.Left) return; - mouse.Cursor.CursorMode = CursorMode.Raw; - } - - private void OnMouseUp(IMouse mouse, MouseButton button) - { - if (button != MouseButton.Left) return; - mouse.Cursor.CursorMode = CursorMode.Normal; - } - - private void OnMouseMove(IMouse mouse, Vector2 position) - { - if (_previousMousePosition == default) { _previousMousePosition = position; } - else - { - if (mouse.Cursor.CursorMode == CursorMode.Raw) - { - const float lookSensitivity = 0.1f; - var xOffset = (position.X - _previousMousePosition.X) * lookSensitivity; - var yOffset = (position.Y - _previousMousePosition.Y) * lookSensitivity; - - _camera.ModifyDirection(xOffset, yOffset); - } - - _previousMousePosition = position; - } - } - - private void OnMouseWheel(IMouse mouse, ScrollWheel scrollWheel) - { - _camera.ModifyZoom(scrollWheel.Y); - } - private void OnClose() { + _framebuffer.Dispose(); _grid.Dispose(); _skybox.Dispose(); _shader.Dispose(); diff --git a/FModel/Views/Snooper/Texture.cs b/FModel/Views/Snooper/Texture.cs index 8a1e60d4..8e00e124 100644 --- a/FModel/Views/Snooper/Texture.cs +++ b/FModel/Views/Snooper/Texture.cs @@ -22,11 +22,20 @@ public class Texture : IDisposable Bind(TextureUnit.Texture0); } + // public Texture(GL gl, uint width, uint height) : this(gl, TextureType.MsaaFramebuffer) + // { + // _gl.TexImage2DMultisample(TextureTarget.Texture2DMultisample, Constants.SAMPLES_COUNT, InternalFormat.Rgb, width, height, Silk.NET.OpenGL.Boolean.True); + // + // _gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int) GLEnum.Nearest); + // _gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int) GLEnum.Nearest); + // _gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int) GLEnum.ClampToEdge); + // _gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int) GLEnum.ClampToEdge); + // + // _gl.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2DMultisample, _handle, 0); + // } + public unsafe Texture(GL gl, uint width, uint height) : this(gl, TextureType.Framebuffer) { - _gl = gl; - _handle = _gl.GenTexture(); - _gl.TexImage2D(TextureTarget.Texture2D, 0, (int) InternalFormat.Rgb, width, height, 0, PixelFormat.Rgb, PixelType.UnsignedByte, null); _gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int) GLEnum.Nearest); @@ -102,5 +111,6 @@ public enum TextureType { Normal, Cubemap, - Framebuffer + Framebuffer, + MsaaFramebuffer }