Last active
September 26, 2023 21:50
-
-
Save thatcosmonaut/0d4e549f6774277bb16c17561f6568fc to your computer and use it in GitHub Desktop.
MoonWorks + Dear Imgui
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if DEBUG | |
using MoonWorks; | |
using MoonWorks.Graphics; | |
using MoonWorks.Math.Float; | |
using ImGuiNET; | |
using Buffer = MoonWorks.Graphics.Buffer; | |
namespace SamuraiGunn2 | |
{ | |
public class DebugRenderer | |
{ | |
private GraphicsDevice GraphicsDevice; | |
private Window Window; | |
private Data.DebugTextureStorage TextureStorage; | |
private Texture FontTexture; | |
private uint VertexCount = 0; | |
private uint IndexCount = 0; | |
private Buffer ImGuiVertexBuffer = null; | |
private Buffer ImGuiIndexBuffer = null; | |
private GraphicsPipeline ImGuiPipeline; | |
private Sampler ImGuiSampler; | |
public DebugRenderer(GraphicsDevice graphicsDevice, Window window, ShaderModules shaderModules, Data.DebugTextureStorage debugTextureStorage) | |
{ | |
GraphicsDevice = graphicsDevice; | |
Window = window; | |
TextureStorage = debugTextureStorage; | |
ImGuiSampler = new Sampler(GraphicsDevice, SamplerCreateInfo.PointClamp); | |
ImGuiPipeline = new GraphicsPipeline( | |
GraphicsDevice, | |
new GraphicsPipelineCreateInfo | |
{ | |
AttachmentInfo = new GraphicsPipelineAttachmentInfo( | |
new ColorAttachmentDescription( | |
window.SwapchainFormat, | |
ColorAttachmentBlendState.NonPremultiplied | |
) | |
), | |
DepthStencilState = DepthStencilState.Disable, | |
VertexShaderInfo = GraphicsShaderInfo.Create<Matrix4x4>(shaderModules.ImguiVertexShader, "main", 0), | |
FragmentShaderInfo = GraphicsShaderInfo.Create(shaderModules.ImguiFragmentShader, "main", 1), | |
VertexInputState = VertexInputState.CreateSingleBinding<Position2DTextureColorVertex>(), | |
PrimitiveType = PrimitiveType.TriangleList, | |
RasterizerState = RasterizerState.CW_CullNone, | |
MultisampleState = MultisampleState.None | |
} | |
); | |
var io = ImGui.GetIO(); | |
io.DisplaySize = new System.Numerics.Vector2(window.Width, window.Height); io.DisplayFramebufferScale = System.Numerics.Vector2.One; | |
BuildFontAtlas(); | |
} | |
public void Resize() | |
{ | |
ImGui.GetIO().DisplaySize = new System.Numerics.Vector2(Window.Width, Window.Height); | |
} | |
public void Draw(CommandBuffer commandBuffer, Texture renderTexture) | |
{ | |
ImGui.Render(); | |
var io = ImGui.GetIO(); | |
var drawDataPtr = ImGui.GetDrawData(); | |
UpdateImGuiBuffers(drawDataPtr); | |
RenderCommandLists(commandBuffer, renderTexture, drawDataPtr, io); | |
} | |
private void BuildFontAtlas() | |
{ | |
var commandBuffer = GraphicsDevice.AcquireCommandBuffer(); | |
var io = ImGui.GetIO(); | |
io.Fonts.GetTexDataAsRGBA32( | |
out System.IntPtr pixelData, | |
out int width, | |
out int height, | |
out int bytesPerPixel | |
); | |
FontTexture = Texture.CreateTexture2D( | |
GraphicsDevice, | |
(uint) width, | |
(uint) height, | |
TextureFormat.R8G8B8A8, | |
TextureUsageFlags.Sampler | |
); | |
commandBuffer.SetTextureData(FontTexture, pixelData, (uint) (width * height * bytesPerPixel)); | |
GraphicsDevice.Submit(commandBuffer); | |
io.Fonts.SetTexID(FontTexture.Handle); | |
io.Fonts.ClearTexData(); | |
TextureStorage.Add(FontTexture); | |
} | |
private unsafe void UpdateImGuiBuffers(ImDrawDataPtr drawDataPtr) | |
{ | |
if (drawDataPtr.TotalVtxCount == 0) { return; } | |
var commandBuffer = GraphicsDevice.AcquireCommandBuffer(); | |
if (drawDataPtr.TotalVtxCount > VertexCount) | |
{ | |
ImGuiVertexBuffer?.Dispose(); | |
VertexCount = (uint) (drawDataPtr.TotalVtxCount * 1.5f); | |
ImGuiVertexBuffer = Buffer.Create<Position2DTextureColorVertex>( | |
GraphicsDevice, | |
BufferUsageFlags.Vertex, | |
VertexCount | |
); | |
} | |
if (drawDataPtr.TotalIdxCount > IndexCount) | |
{ | |
ImGuiIndexBuffer?.Dispose(); | |
IndexCount = (uint) (drawDataPtr.TotalIdxCount * 1.5f); | |
ImGuiIndexBuffer = Buffer.Create<ushort>( | |
GraphicsDevice, | |
BufferUsageFlags.Index, | |
IndexCount | |
); | |
} | |
uint vertexOffset = 0; | |
uint indexOffset = 0; | |
for (var n = 0; n < drawDataPtr.CmdListsCount; n += 1) | |
{ | |
var cmdList = drawDataPtr.CmdListsRange[n]; | |
commandBuffer.SetBufferData<Position2DTextureColorVertex>( | |
ImGuiVertexBuffer, | |
cmdList.VtxBuffer.Data, | |
vertexOffset, | |
(uint) cmdList.VtxBuffer.Size | |
); | |
commandBuffer.SetBufferData<ushort>( | |
ImGuiIndexBuffer, | |
cmdList.IdxBuffer.Data, | |
indexOffset, | |
(uint) cmdList.IdxBuffer.Size | |
); | |
vertexOffset += (uint) cmdList.VtxBuffer.Size; | |
indexOffset += (uint) cmdList.IdxBuffer.Size; | |
} | |
GraphicsDevice.Submit(commandBuffer); | |
} | |
private void RenderCommandLists(CommandBuffer commandBuffer, Texture renderTexture, ImDrawDataPtr drawDataPtr, ImGuiIOPtr ioPtr) | |
{ | |
if (ImGuiVertexBuffer == null) { return; } | |
commandBuffer.BeginRenderPass( | |
new ColorAttachmentInfo(renderTexture, LoadOp.Load) | |
); | |
commandBuffer.BindGraphicsPipeline(ImGuiPipeline); | |
var vertexUniformOffset = commandBuffer.PushVertexShaderUniforms( | |
Matrix4x4.CreateOrthographicOffCenter(0, ioPtr.DisplaySize.X, ioPtr.DisplaySize.Y, 0, -1, 1) | |
); | |
commandBuffer.BindVertexBuffers(ImGuiVertexBuffer); | |
commandBuffer.BindIndexBuffer(ImGuiIndexBuffer, IndexElementSize.Sixteen); | |
uint vertexOffset = 0; | |
uint indexOffset = 0; | |
for (int n = 0; n < drawDataPtr.CmdListsCount; n += 1) | |
{ | |
var cmdList = drawDataPtr.CmdListsRange[n]; | |
for (int cmdIndex = 0; cmdIndex < cmdList.CmdBuffer.Size; cmdIndex += 1) | |
{ | |
var drawCmd = cmdList.CmdBuffer[cmdIndex]; | |
commandBuffer.BindFragmentSamplers( | |
new TextureSamplerBinding(TextureStorage.GetTexture(drawCmd.TextureId), ImGuiSampler) | |
); | |
var width = drawCmd.ClipRect.Z - (int) drawCmd.ClipRect.X; | |
var height = drawCmd.ClipRect.W - (int) drawCmd.ClipRect.Y; | |
if (width <= 0 || height <= 0) | |
{ | |
continue; | |
} | |
commandBuffer.SetScissor( | |
new Rect( | |
(int) drawCmd.ClipRect.X, | |
(int) drawCmd.ClipRect.Y, | |
(int) width, | |
(int) height | |
) | |
); | |
commandBuffer.DrawIndexedPrimitives( | |
vertexOffset, | |
indexOffset, | |
drawCmd.ElemCount / 3, | |
vertexUniformOffset, | |
0 | |
); | |
indexOffset += drawCmd.ElemCount; | |
} | |
vertexOffset += (uint) cmdList.VtxBuffer.Size; | |
} | |
commandBuffer.EndRenderPass(); | |
} | |
} | |
} | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if DEBUG | |
using System; | |
using System.Collections.Generic; | |
using MoonWorks.Graphics; | |
namespace SamuraiGunn2.Data | |
{ | |
public class DebugTextureStorage | |
{ | |
Dictionary<IntPtr, WeakReference<Texture>> PointerToTexture = new Dictionary<IntPtr, WeakReference<Texture>>(); | |
public IntPtr Add(Texture texture) | |
{ | |
if (!PointerToTexture.ContainsKey(texture.Handle)) | |
{ | |
PointerToTexture.Add(texture.Handle, new WeakReference<Texture>(texture)); | |
} | |
return texture.Handle; | |
} | |
public Texture GetTexture(IntPtr pointer) | |
{ | |
if (!PointerToTexture.ContainsKey(pointer)) | |
{ | |
return null; | |
} | |
var result = PointerToTexture[pointer]; | |
if (!result.TryGetTarget(out var texture)) | |
{ | |
PointerToTexture.Remove(pointer); | |
return null; | |
} | |
return texture; | |
} | |
} | |
} | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#version 450 | |
layout(set = 1, binding = 0) uniform sampler2D tex; | |
layout(location = 0) in vec2 inTexCoord; | |
layout(location = 1) in vec4 inColor; | |
layout(location = 0) out vec4 outColor; | |
void main() | |
{ | |
outColor = texture(tex, inTexCoord) * inColor; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#version 450 | |
layout(location = 0) in vec2 inPosition; | |
layout(location = 1) in vec2 inTexCoord; | |
layout(location = 2) in vec4 inColor; | |
layout (set = 2, binding = 0) uniform UniformBlock | |
{ | |
mat4 projectionMatrix; | |
} Uniforms; | |
layout(location = 0) out vec2 outTexCoord; | |
layout(location = 1) out vec4 outColor; | |
void main() { | |
gl_Position = Uniforms.projectionMatrix * vec4(inPosition, 0.0, 1.0); | |
outTexCoord = inTexCoord; | |
outColor = inColor; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment