From a9f53af62c40986e5116daf77cd4c94dfcbe55c0 Mon Sep 17 00:00:00 2001 From: Caleb Cornett Date: Sat, 12 Nov 2022 14:27:10 -0500 Subject: [PATCH] added a depth-only visualization mode to the Cube test --- Cube/CubeGame.cs | 202 +++++++++++++----- .../Compiled/TexturedDepthQuadFrag.spv | Bin 0 -> 1648 bytes .../Shaders/Source/TexturedDepthQuadFrag.frag | 26 +++ README.md | 2 +- 4 files changed, 179 insertions(+), 51 deletions(-) create mode 100644 MoonWorks.Test.Common/Content/Shaders/Compiled/TexturedDepthQuadFrag.spv create mode 100644 MoonWorks.Test.Common/Content/Shaders/Source/TexturedDepthQuadFrag.frag diff --git a/Cube/CubeGame.cs b/Cube/CubeGame.cs index e1ac5b5..15767c4 100644 --- a/Cube/CubeGame.cs +++ b/Cube/CubeGame.cs @@ -9,29 +9,51 @@ namespace MoonWorks.Test class CubeGame : Game { private GraphicsPipeline cubePipeline; + private GraphicsPipeline cubePipelineDepthOnly; private GraphicsPipeline skyboxPipeline; + private GraphicsPipeline skyboxPipelineDepthOnly; + private GraphicsPipeline blitPipeline; + private Texture depthTexture; + private Sampler depthSampler; + private DepthUniforms depthUniforms; + private Buffer cubeVertexBuffer; private Buffer skyboxVertexBuffer; + private Buffer blitVertexBuffer; private Buffer indexBuffer; + private Texture skyboxTexture; private Sampler skyboxSampler; - private bool finishedLoading; + private bool finishedLoading = false; private float cubeTimer = 0f; private Quaternion cubeRotation = Quaternion.Identity; private Quaternion previousCubeRotation = Quaternion.Identity; + private bool depthOnlyEnabled = false; - struct Uniforms + struct ViewProjectionUniforms { public Matrix4x4 ViewProjection; - public Uniforms(Matrix4x4 viewProjection) + public ViewProjectionUniforms(Matrix4x4 viewProjection) { ViewProjection = viewProjection; } } + struct DepthUniforms + { + public float ZNear; + public float ZFar; + + public DepthUniforms(float zNear, float zFar) + { + ZNear = zNear; + ZFar = zFar; + } + } + void LoadCubemap(CommandBuffer cmdbuf, string[] imagePaths) { System.IntPtr textureData; @@ -79,13 +101,24 @@ namespace MoonWorks.Test TestUtils.GetShaderPath("SkyboxFrag.spv") ); + ShaderModule blitVertShaderModule = new ShaderModule( + GraphicsDevice, + TestUtils.GetShaderPath("TexturedQuadVert.spv") + ); + ShaderModule blitFragShaderModule = new ShaderModule( + GraphicsDevice, + TestUtils.GetShaderPath("TexturedDepthQuadFrag.spv") + ); + depthTexture = Texture.CreateTexture2D( GraphicsDevice, MainWindow.Width, MainWindow.Height, TextureFormat.D16, - TextureUsageFlags.DepthStencilTarget + TextureUsageFlags.DepthStencilTarget | TextureUsageFlags.Sampler ); + depthSampler = new Sampler(GraphicsDevice, new SamplerCreateInfo()); + depthUniforms = new DepthUniforms(0.01f, 100f); skyboxTexture = Texture.CreateTextureCube( GraphicsDevice, @@ -111,56 +144,82 @@ namespace MoonWorks.Test 36 ); // Using uint here just to test IndexElementSize=32 + blitVertexBuffer = Buffer.Create( + GraphicsDevice, + BufferUsageFlags.Vertex, + 6 + ); + Task loadingTask = Task.Run(() => UploadGPUAssets()); - cubePipeline = new GraphicsPipeline( - GraphicsDevice, - new GraphicsPipelineCreateInfo - { - AttachmentInfo = new GraphicsPipelineAttachmentInfo( + // Create the cube pipelines + + GraphicsPipelineCreateInfo cubePipelineCreateInfo = new GraphicsPipelineCreateInfo + { + AttachmentInfo = new GraphicsPipelineAttachmentInfo( TextureFormat.D16, new ColorAttachmentDescription( MainWindow.SwapchainFormat, ColorAttachmentBlendState.Opaque ) ), - DepthStencilState = DepthStencilState.DepthReadWrite, - VertexShaderInfo = GraphicsShaderInfo.Create(cubeVertShaderModule, "main", 0), - VertexInputState = new VertexInputState( + DepthStencilState = DepthStencilState.DepthReadWrite, + VertexShaderInfo = GraphicsShaderInfo.Create(cubeVertShaderModule, "main", 0), + VertexInputState = new VertexInputState( VertexBinding.Create(), VertexAttribute.Create("Position", 0), VertexAttribute.Create("Color", 1) ), - PrimitiveType = PrimitiveType.TriangleList, - FragmentShaderInfo = GraphicsShaderInfo.Create(cubeFragShaderModule, "main", 0), - RasterizerState = RasterizerState.CW_CullBack, - MultisampleState = MultisampleState.None - } - ); + PrimitiveType = PrimitiveType.TriangleList, + FragmentShaderInfo = GraphicsShaderInfo.Create(cubeFragShaderModule, "main", 0), + RasterizerState = RasterizerState.CW_CullBack, + MultisampleState = MultisampleState.None + }; + cubePipeline = new GraphicsPipeline(GraphicsDevice, cubePipelineCreateInfo); - skyboxPipeline = new GraphicsPipeline( - GraphicsDevice, - new GraphicsPipelineCreateInfo - { - AttachmentInfo = new GraphicsPipelineAttachmentInfo( - TextureFormat.D16, - new ColorAttachmentDescription( - MainWindow.SwapchainFormat, - ColorAttachmentBlendState.Opaque - ) - ), - DepthStencilState = DepthStencilState.DepthReadWrite, - VertexShaderInfo = GraphicsShaderInfo.Create(skyboxVertShaderModule, "main", 0), - VertexInputState = new VertexInputState( - VertexBinding.Create(), - VertexAttribute.Create("Position", 0) - ), - PrimitiveType = PrimitiveType.TriangleList, - FragmentShaderInfo = GraphicsShaderInfo.Create(skyboxFragShaderModule, "main", 1), - RasterizerState = RasterizerState.CW_CullNone, - MultisampleState = MultisampleState.None, - } + cubePipelineCreateInfo.AttachmentInfo = new GraphicsPipelineAttachmentInfo(TextureFormat.D16); + cubePipelineDepthOnly = new GraphicsPipeline(GraphicsDevice, cubePipelineCreateInfo); + + // Create the skybox pipelines + + GraphicsPipelineCreateInfo skyboxPipelineCreateInfo = new GraphicsPipelineCreateInfo + { + AttachmentInfo = new GraphicsPipelineAttachmentInfo( + TextureFormat.D16, + new ColorAttachmentDescription( + MainWindow.SwapchainFormat, + ColorAttachmentBlendState.Opaque + ) + ), + DepthStencilState = DepthStencilState.DepthReadWrite, + VertexShaderInfo = GraphicsShaderInfo.Create(skyboxVertShaderModule, "main", 0), + VertexInputState = new VertexInputState( + VertexBinding.Create(), + VertexAttribute.Create("Position", 0) + ), + PrimitiveType = PrimitiveType.TriangleList, + FragmentShaderInfo = GraphicsShaderInfo.Create(skyboxFragShaderModule, "main", 1), + RasterizerState = RasterizerState.CW_CullNone, + MultisampleState = MultisampleState.None, + }; + skyboxPipeline = new GraphicsPipeline(GraphicsDevice, skyboxPipelineCreateInfo); + + skyboxPipelineCreateInfo.AttachmentInfo = new GraphicsPipelineAttachmentInfo(TextureFormat.D16); + skyboxPipelineDepthOnly = new GraphicsPipeline(GraphicsDevice, skyboxPipelineCreateInfo); + + // Create the blit pipeline + + GraphicsPipelineCreateInfo blitPipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo( + blitVertShaderModule, + blitFragShaderModule ); + blitPipelineCreateInfo.VertexInputState = new VertexInputState( + VertexBinding.Create(), + VertexAttribute.Create("Position", 0), + VertexAttribute.Create("TexCoord", 1) + ); + blitPipelineCreateInfo.FragmentShaderInfo = GraphicsShaderInfo.Create(blitFragShaderModule, "main", 1); + blitPipeline = new GraphicsPipeline(GraphicsDevice, blitPipelineCreateInfo); } private void UploadGPUAssets() @@ -254,6 +313,19 @@ namespace MoonWorks.Test } ); + cmdbuf.SetBufferData( + blitVertexBuffer, + new PositionTextureVertex[] + { + new PositionTextureVertex(new Vector3(-1, -1, 0), new Vector2(0, 0)), + new PositionTextureVertex(new Vector3(1, -1, 0), new Vector2(1, 0)), + new PositionTextureVertex(new Vector3(1, 1, 0), new Vector2(1, 1)), + new PositionTextureVertex(new Vector3(-1, -1, 0), new Vector2(0, 0)), + new PositionTextureVertex(new Vector3(1, 1, 0), new Vector2(1, 1)), + new PositionTextureVertex(new Vector3(-1, 1, 0), new Vector2(0, 1)), + } + ); + LoadCubemap(cmdbuf, new string[] { TestUtils.GetTexturePath("right.png"), @@ -268,6 +340,7 @@ namespace MoonWorks.Test finishedLoading = true; Logger.LogInfo("Finished loading!"); + Logger.LogInfo("Press A to toggle Depth-Only Mode"); } protected override void Update(System.TimeSpan delta) @@ -281,6 +354,12 @@ namespace MoonWorks.Test 0, cubeTimer * 2f ); + + if (Inputs.Keyboard.IsPressed(Input.KeyCode.A)) + { + depthOnlyEnabled = !depthOnlyEnabled; + Logger.LogInfo("Depth-Only Mode enabled: " + depthOnlyEnabled); + } } protected override void Draw(double alpha) @@ -288,15 +367,15 @@ namespace MoonWorks.Test Matrix4x4 proj = Matrix4x4.CreatePerspectiveFieldOfView( MathHelper.ToRadians(75f), (float) MainWindow.Width / MainWindow.Height, - 0.01f, - 100f + depthUniforms.ZNear, + depthUniforms.ZFar ); Matrix4x4 view = Matrix4x4.CreateLookAt( new Vector3(0, 1.5f, 4f), Vector3.Zero, Vector3.Up ); - Uniforms skyboxUniforms = new Uniforms(view * proj); + ViewProjectionUniforms skyboxUniforms = new ViewProjectionUniforms(view * proj); Matrix4x4 model = Matrix4x4.CreateFromQuaternion( Quaternion.Slerp( @@ -305,7 +384,7 @@ namespace MoonWorks.Test (float) alpha ) ); - Uniforms cubeUniforms = new Uniforms(model * view * proj); + ViewProjectionUniforms cubeUniforms = new ViewProjectionUniforms(model * view * proj); CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer(); Texture? swapchainTexture = cmdbuf.AcquireSwapchainTexture(MainWindow); @@ -322,20 +401,29 @@ namespace MoonWorks.Test } else { - cmdbuf.BeginRenderPass( - new DepthStencilAttachmentInfo(depthTexture, new DepthStencilValue(1f, 0)), - new ColorAttachmentInfo(swapchainTexture, Color.CornflowerBlue) - ); + if (!depthOnlyEnabled) + { + cmdbuf.BeginRenderPass( + new DepthStencilAttachmentInfo(depthTexture, new DepthStencilValue(1f, 0)), + new ColorAttachmentInfo(swapchainTexture, LoadOp.DontCare) + ); + } + else + { + cmdbuf.BeginRenderPass( + new DepthStencilAttachmentInfo(depthTexture, new DepthStencilValue(1f, 0)) + ); + } // Draw cube - cmdbuf.BindGraphicsPipeline(cubePipeline); + cmdbuf.BindGraphicsPipeline(depthOnlyEnabled ? cubePipelineDepthOnly : cubePipeline); cmdbuf.BindVertexBuffers(cubeVertexBuffer); cmdbuf.BindIndexBuffer(indexBuffer, IndexElementSize.ThirtyTwo); uint vertexParamOffset = cmdbuf.PushVertexShaderUniforms(cubeUniforms); cmdbuf.DrawIndexedPrimitives(0, 0, 12, vertexParamOffset, 0); // Draw skybox - cmdbuf.BindGraphicsPipeline(skyboxPipeline); + cmdbuf.BindGraphicsPipeline(depthOnlyEnabled ? skyboxPipelineDepthOnly : skyboxPipeline); cmdbuf.BindVertexBuffers(skyboxVertexBuffer); cmdbuf.BindIndexBuffer(indexBuffer, IndexElementSize.ThirtyTwo); cmdbuf.BindFragmentSamplers(new TextureSamplerBinding(skyboxTexture, skyboxSampler)); @@ -343,6 +431,20 @@ namespace MoonWorks.Test cmdbuf.DrawIndexedPrimitives(0, 0, 12, vertexParamOffset, 0); cmdbuf.EndRenderPass(); + + if (depthOnlyEnabled) + { + // Draw the depth buffer as a grayscale image + cmdbuf.BeginRenderPass(new ColorAttachmentInfo(swapchainTexture, LoadOp.DontCare)); + + cmdbuf.BindGraphicsPipeline(blitPipeline); + cmdbuf.BindFragmentSamplers(new TextureSamplerBinding(depthTexture, depthSampler)); + cmdbuf.BindVertexBuffers(blitVertexBuffer); + uint fragParamOffset = cmdbuf.PushFragmentShaderUniforms(depthUniforms); + cmdbuf.DrawPrimitives(0, 2, vertexParamOffset, fragParamOffset); + + cmdbuf.EndRenderPass(); + } } } diff --git a/MoonWorks.Test.Common/Content/Shaders/Compiled/TexturedDepthQuadFrag.spv b/MoonWorks.Test.Common/Content/Shaders/Compiled/TexturedDepthQuadFrag.spv new file mode 100644 index 0000000000000000000000000000000000000000..882034baf2943aaf82ae57e939ccfaaa12c032ed GIT binary patch literal 1648 zcmZ9MTTc^F6orqp0|=s21Vj{DY9fkOQLZ8vMX3*sXwdlBOxgh_PCLy|jrK`nO#EH` zDql3N?{totaFU(9*V@;!=d`(j@{loS%!nB?yQY5%W<<#j4KXa4P@n1)tFyO%Bx$oR<9l$RBO-cjZUY2()|(z z^(bry^=6m^jc)iUAZ|Dl7q%PG$7VLbQ$)6}r%og4K^;E{d%?4y(|x~iw6tlAr@Ne$ zFHXYauUx@aYDzd7F> zuB80o)P`FWhCe6K*_{(+cDR0xyxv&9F8rqaVD3b(N#SwnqJ;UW2QElBMd6Fm#8S`s zr(_d9qnEId`oP)a@T~50OAg|wcRLM&V;(R&u71Kc*Wt&f@K%an=@!hlBO!-4eC&q0>Rgr0tgg;A*{6H)+l6;A*VCBnJ&NMszo)%QvdJq-+}-A7(+{7EE6Zjsd_U9N8?xC0 LzQ5Wbn0@~PaqeyZ literal 0 HcmV?d00001 diff --git a/MoonWorks.Test.Common/Content/Shaders/Source/TexturedDepthQuadFrag.frag b/MoonWorks.Test.Common/Content/Shaders/Source/TexturedDepthQuadFrag.frag new file mode 100644 index 0000000..07feffe --- /dev/null +++ b/MoonWorks.Test.Common/Content/Shaders/Source/TexturedDepthQuadFrag.frag @@ -0,0 +1,26 @@ +#version 450 + +layout (location = 0) in vec2 TexCoord; + +layout (location = 0) out vec4 FragColor; + +layout(binding = 0, set = 1) uniform sampler2D Sampler; + +layout (binding = 0, set = 3) uniform UniformBlock +{ + float zNear; + float zFar; +}; + +// Calculation taken from http://www.geeks3d.com/20091216/geexlab-how-to-visualize-the-depth-buffer-in-glsl/ +float linearizeDepth(float originalDepth) +{ + return (2.0 * zNear) / (zFar + zNear - originalDepth * (zFar - zNear)); +} + +void main() +{ + float d = texture(Sampler, TexCoord).r; + d = linearizeDepth(d); + FragColor = vec4(d, d, d, 1.0); +} diff --git a/README.md b/README.md index ee763b2..3f0706b 100644 --- a/README.md +++ b/README.md @@ -38,4 +38,4 @@ Sets buffer data, gets the data back from the GPU, and prints the results to the **Cube** -Renders a cubemap skybox and a spinning cube. Tests depth texture, cube texture, and 32-bit index buffers. +Renders a cubemap skybox and a spinning cube. Tests depth textures, sampling from depth textures, depth-only render passes, cube textures, and 32-bit index buffers.