diff --git a/MoonWorks.Test.Common/Content/Textures/mip0.png b/MoonWorks.Test.Common/Content/Textures/mip0.png new file mode 100644 index 0000000..88c2d81 Binary files /dev/null and b/MoonWorks.Test.Common/Content/Textures/mip0.png differ diff --git a/MoonWorks.Test.Common/Content/Textures/mip1.png b/MoonWorks.Test.Common/Content/Textures/mip1.png new file mode 100644 index 0000000..58c0fd3 Binary files /dev/null and b/MoonWorks.Test.Common/Content/Textures/mip1.png differ diff --git a/MoonWorks.Test.Common/Content/Textures/mip2.png b/MoonWorks.Test.Common/Content/Textures/mip2.png new file mode 100644 index 0000000..a84993b Binary files /dev/null and b/MoonWorks.Test.Common/Content/Textures/mip2.png differ diff --git a/MoonWorks.Test.Common/Content/Textures/mip3.png b/MoonWorks.Test.Common/Content/Textures/mip3.png new file mode 100644 index 0000000..d6df85a Binary files /dev/null and b/MoonWorks.Test.Common/Content/Textures/mip3.png differ diff --git a/MoonWorksGraphicsTests.sln b/MoonWorksGraphicsTests.sln index 1f61e44..d2b285c 100644 --- a/MoonWorksGraphicsTests.sln +++ b/MoonWorksGraphicsTests.sln @@ -51,6 +51,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RenderTextureCube", "Render EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RenderTextureMipmaps", "RenderTextureMipmaps\RenderTextureMipmaps.csproj", "{2219C628-5593-4C23-86CB-0E1E96EBD6C5}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TextureMipmaps", "TextureMipmaps\TextureMipmaps.csproj", "{5A1AC35B-EF18-426D-A633-D4899E84EAA7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -131,28 +133,32 @@ Global {FCD63849-9D3C-4D48-A8BD-39671096F03A}.Release|x64.Build.0 = Release|x64 {9D0F0573-7FD4-4480-8F9B-CDD52120A170}.Debug|x64.ActiveCfg = Debug|x64 {9D0F0573-7FD4-4480-8F9B-CDD52120A170}.Debug|x64.Build.0 = Debug|x64 - {9D0F0573-7FD4-4480-8F9B-CDD52120A170}.Release|x64.ActiveCfg = Release|Any CPU - {9D0F0573-7FD4-4480-8F9B-CDD52120A170}.Release|x64.Build.0 = Release|Any CPU + {9D0F0573-7FD4-4480-8F9B-CDD52120A170}.Release|x64.ActiveCfg = Release|x64 + {9D0F0573-7FD4-4480-8F9B-CDD52120A170}.Release|x64.Build.0 = Release|x64 {5CDA8D41-F96C-4DE7-AD53-5A76C4C0CC31}.Debug|x64.ActiveCfg = Debug|x64 {5CDA8D41-F96C-4DE7-AD53-5A76C4C0CC31}.Debug|x64.Build.0 = Debug|x64 {5CDA8D41-F96C-4DE7-AD53-5A76C4C0CC31}.Release|x64.ActiveCfg = Release|x64 {5CDA8D41-F96C-4DE7-AD53-5A76C4C0CC31}.Release|x64.Build.0 = Release|x64 {C525B6DE-3003-45D5-BB83-89679B108C08}.Debug|x64.ActiveCfg = Debug|x64 {C525B6DE-3003-45D5-BB83-89679B108C08}.Debug|x64.Build.0 = Debug|x64 - {C525B6DE-3003-45D5-BB83-89679B108C08}.Release|x64.ActiveCfg = Release|Any CPU - {C525B6DE-3003-45D5-BB83-89679B108C08}.Release|x64.Build.0 = Release|Any CPU + {C525B6DE-3003-45D5-BB83-89679B108C08}.Release|x64.ActiveCfg = Release|x64 + {C525B6DE-3003-45D5-BB83-89679B108C08}.Release|x64.Build.0 = Release|x64 {6D625A4C-8618-4DFC-A6AD-AA3BE3488D70}.Debug|x64.ActiveCfg = Debug|x64 {6D625A4C-8618-4DFC-A6AD-AA3BE3488D70}.Debug|x64.Build.0 = Debug|x64 - {6D625A4C-8618-4DFC-A6AD-AA3BE3488D70}.Release|x64.ActiveCfg = Release|Any CPU - {6D625A4C-8618-4DFC-A6AD-AA3BE3488D70}.Release|x64.Build.0 = Release|Any CPU + {6D625A4C-8618-4DFC-A6AD-AA3BE3488D70}.Release|x64.ActiveCfg = Release|x64 + {6D625A4C-8618-4DFC-A6AD-AA3BE3488D70}.Release|x64.Build.0 = Release|x64 {D7A8452F-123F-4965-8716-9E39F677A831}.Debug|x64.ActiveCfg = Debug|x64 {D7A8452F-123F-4965-8716-9E39F677A831}.Debug|x64.Build.0 = Debug|x64 - {D7A8452F-123F-4965-8716-9E39F677A831}.Release|x64.ActiveCfg = Release|Any CPU - {D7A8452F-123F-4965-8716-9E39F677A831}.Release|x64.Build.0 = Release|Any CPU + {D7A8452F-123F-4965-8716-9E39F677A831}.Release|x64.ActiveCfg = Release|x64 + {D7A8452F-123F-4965-8716-9E39F677A831}.Release|x64.Build.0 = Release|x64 {2219C628-5593-4C23-86CB-0E1E96EBD6C5}.Debug|x64.ActiveCfg = Debug|x64 {2219C628-5593-4C23-86CB-0E1E96EBD6C5}.Debug|x64.Build.0 = Debug|x64 {2219C628-5593-4C23-86CB-0E1E96EBD6C5}.Release|x64.ActiveCfg = Release|x64 {2219C628-5593-4C23-86CB-0E1E96EBD6C5}.Release|x64.Build.0 = Release|x64 + {5A1AC35B-EF18-426D-A633-D4899E84EAA7}.Debug|x64.ActiveCfg = Debug|x64 + {5A1AC35B-EF18-426D-A633-D4899E84EAA7}.Debug|x64.Build.0 = Debug|x64 + {5A1AC35B-EF18-426D-A633-D4899E84EAA7}.Release|x64.ActiveCfg = Release|x64 + {5A1AC35B-EF18-426D-A633-D4899E84EAA7}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/README.md b/README.md index 3cc1d34..7b56fe7 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,10 @@ Plays a sample Ogg Theora video file. Tests YUV textures and video rendering. Displays 2D slices of a 3D texture. Tests creating and drawing 3D textures. +**TextureMipmaps** + +Displays a quad that can be scaled to reveal various mip levels. The mips are generated from PNGs. Tests SetTextureData for mip levels and rendering mipmaps. + **VertexSampler** Displays a triangle whose colors are driven by sampling a texture in the vertex shader. @@ -86,4 +90,4 @@ Displays a cubemap generated by rendering to a cube render target. Tests binding **RenderTextureMipmaps** -Displays a quad that can be scaled to reveal various mip levels. The mips are solid colors, generated by clearing various levels of the texture in a render pass. Tests rendering to mipmap levels of a render texture and rendering mipmaps. +Displays a quad that can be scaled to reveal various mip levels. The mips are solid colors, generated by clearing various levels of the texture in a render pass. Tests rendering to mipmap levels of a render texture, mip LOD bias, min/max LODs, and mip filter modes. diff --git a/TextureMipmaps/TextureMipmaps.csproj b/TextureMipmaps/TextureMipmaps.csproj new file mode 100644 index 0000000..2868e63 --- /dev/null +++ b/TextureMipmaps/TextureMipmaps.csproj @@ -0,0 +1,17 @@ + + + + + + + + + Exe + net7.0 + enable + x64 + + + + + diff --git a/TextureMipmaps/TextureMipmapsGame.cs b/TextureMipmaps/TextureMipmapsGame.cs new file mode 100644 index 0000000..389c377 --- /dev/null +++ b/TextureMipmaps/TextureMipmapsGame.cs @@ -0,0 +1,148 @@ +using MoonWorks; +using MoonWorks.Graphics; +using MoonWorks.Math.Float; +using RefreshCS; + +namespace MoonWorks.Test +{ + class TextureMipmapsGame : Game + { + private GraphicsPipeline pipeline; + private Buffer vertexBuffer; + private Buffer indexBuffer; + private Texture texture; + private Sampler sampler; + + private float scale = 0.5f; + + private struct VertexUniforms + { + public Matrix4x4 TransformMatrix; + + public VertexUniforms(Matrix4x4 transformMatrix) + { + TransformMatrix = transformMatrix; + } + } + + public TextureMipmapsGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true) + { + Logger.LogInfo("Press Left and Right to shrink/expand the scale of the quad"); + + // Load the shaders + ShaderModule vertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuadVertWithMatrix")); + ShaderModule fragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuadFrag")); + + // Create the graphics pipeline + GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo( + MainWindow.SwapchainFormat, + vertShaderModule, + fragShaderModule + ); + pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding(); + pipelineCreateInfo.VertexShaderInfo = GraphicsShaderInfo.Create(vertShaderModule, "main", 0); + pipelineCreateInfo.FragmentShaderInfo.SamplerBindingCount = 1; + pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo); + + // Create and populate the GPU resources + sampler = new Sampler(GraphicsDevice, SamplerCreateInfo.PointClamp); + vertexBuffer = Buffer.Create(GraphicsDevice, BufferUsageFlags.Vertex, 4); + indexBuffer = Buffer.Create(GraphicsDevice, BufferUsageFlags.Index, 6); + texture = Texture.CreateTexture2D( + GraphicsDevice, + 256, + 256, + TextureFormat.R8G8B8A8, + TextureUsageFlags.Sampler, + 4 + ); + + CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer(); + cmdbuf.SetBufferData( + vertexBuffer, + 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, 1)), + } + ); + cmdbuf.SetBufferData( + indexBuffer, + new ushort[] + { + 0, 1, 2, + 0, 2, 3, + } + ); + + // Set the various mip levels + for (int i = 0; i < texture.LevelCount; i += 1) + { + int w = (int) texture.Width >> i; + int h = (int) texture.Height >> i; + TextureSlice slice = new TextureSlice( + texture, + new Rect(0, 0, w, h), + 0, + 0, + (uint) i + ); + + var pixels = Refresh.Refresh_Image_Load( + TestUtils.GetTexturePath($"mip{i}.png"), + out var width, + out var height, + out var channels + ); + + var byteCount = (uint)(width * height * channels); + cmdbuf.SetTextureData(slice, pixels, byteCount); + + Refresh.Refresh_Image_Free(pixels); + } + + GraphicsDevice.Submit(cmdbuf); + } + + protected override void Update(System.TimeSpan delta) + { + if (TestUtils.CheckButtonDown(Inputs, TestUtils.ButtonType.Left)) + { + scale = System.MathF.Max(0.01f, scale - 0.01f); + } + + if (TestUtils.CheckButtonDown(Inputs, TestUtils.ButtonType.Right)) + { + scale = System.MathF.Min(1f, scale + 0.01f); + } + } + + protected override void Draw(double alpha) + { + VertexUniforms vertUniforms = new VertexUniforms(Matrix4x4.CreateScale(scale, scale, 1)); + + CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer(); + Texture? backbuffer = cmdbuf.AcquireSwapchainTexture(MainWindow); + if (backbuffer != null) + { + cmdbuf.BeginRenderPass(new ColorAttachmentInfo(backbuffer, Color.Black)); + cmdbuf.BindGraphicsPipeline(pipeline); + cmdbuf.BindVertexBuffers(vertexBuffer); + cmdbuf.BindIndexBuffer(indexBuffer, IndexElementSize.Sixteen); + cmdbuf.BindFragmentSamplers(new TextureSamplerBinding(texture, sampler)); + uint vertParamOffset = cmdbuf.PushVertexShaderUniforms(vertUniforms); + cmdbuf.DrawIndexedPrimitives(0, 0, 2, vertParamOffset, 0); + cmdbuf.EndRenderPass(); + } + GraphicsDevice.Submit(cmdbuf); + } + + public static void Main(string[] args) + { + TextureMipmapsGame game = new TextureMipmapsGame(); + game.Run(); + } + } +}