diff --git a/.gitignore b/.gitignore index cd42ee3..03c9b93 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ bin/ obj/ +.vs/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..d51e2a4 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/MoonWorks"] + path = lib/MoonWorks + url = https://gitea.moonside.games/MoonsideGames/MoonWorks.git diff --git a/Content/hexagon_grid.spv b/Content/hexagon_grid.spv new file mode 100644 index 0000000..b05224c Binary files /dev/null and b/Content/hexagon_grid.spv differ diff --git a/Content/noise.png b/Content/noise.png new file mode 100644 index 0000000..ba38afd Binary files /dev/null and b/Content/noise.png differ diff --git a/Content/passthrough_vert.spv b/Content/passthrough_vert.spv new file mode 100644 index 0000000..daa8a18 Binary files /dev/null and b/Content/passthrough_vert.spv differ diff --git a/Content/woodgrain.png b/Content/woodgrain.png new file mode 100644 index 0000000..8f2aa11 Binary files /dev/null and b/Content/woodgrain.png differ diff --git a/CopyMoonlibs.targets b/CopyMoonlibs.targets new file mode 100644 index 0000000..209c222 --- /dev/null +++ b/CopyMoonlibs.targets @@ -0,0 +1,19 @@ + + + + + + %(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + osx\%(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + lib64\%(RecursiveDir)%(Filename)%(Extension) + PreserveNewest + + + + diff --git a/MoonWorksTest.csproj b/MoonWorksTest.csproj index 3787680..90fcbee 100644 --- a/MoonWorksTest.csproj +++ b/MoonWorksTest.csproj @@ -17,4 +17,10 @@ Always + + + + + + diff --git a/MoonWorksTest.sln b/MoonWorksTest.sln index 9244a7d..a897f36 100644 --- a/MoonWorksTest.sln +++ b/MoonWorksTest.sln @@ -1,34 +1,49 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26124.0 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30717.126 MinimumVisualStudioVersion = 15.0.26124.0 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MoonWorksTest", "MoonWorksTest.csproj", "{D03DE2E4-7731-4E13-B3DC-DB94F4156681}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MoonWorksTest", "MoonWorksTest.csproj", "{D03DE2E4-7731-4E13-B3DC-DB94F4156681}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MoonWorks", "lib\MoonWorks\MoonWorks.csproj", "{38EE757C-50C0-4ABF-851D-45586C1077A1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FAudio-CS.Core", "lib\MoonWorks\lib\FAudio\csharp\FAudio-CS.Core.csproj", "{3C123688-D3E5-48D7-8003-DDA4E93BFE6E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RefreshCS", "lib\MoonWorks\lib\RefreshCS\RefreshCS.csproj", "{1EF0BDFD-5583-41DE-9BF4-9E7112651D12}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SDL2-CS.Core", "lib\MoonWorks\lib\SDL2-CS\SDL2-CS.Core.csproj", "{C0759474-25B1-4F51-AE5E-1E1F424BAC89}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 - Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D03DE2E4-7731-4E13-B3DC-DB94F4156681}.Debug|x64.ActiveCfg = Debug|x64 + {D03DE2E4-7731-4E13-B3DC-DB94F4156681}.Debug|x64.Build.0 = Debug|x64 + {D03DE2E4-7731-4E13-B3DC-DB94F4156681}.Release|x64.ActiveCfg = Release|x64 + {D03DE2E4-7731-4E13-B3DC-DB94F4156681}.Release|x64.Build.0 = Release|x64 + {38EE757C-50C0-4ABF-851D-45586C1077A1}.Debug|x64.ActiveCfg = Debug|x64 + {38EE757C-50C0-4ABF-851D-45586C1077A1}.Debug|x64.Build.0 = Debug|x64 + {38EE757C-50C0-4ABF-851D-45586C1077A1}.Release|x64.ActiveCfg = Release|x64 + {38EE757C-50C0-4ABF-851D-45586C1077A1}.Release|x64.Build.0 = Release|x64 + {3C123688-D3E5-48D7-8003-DDA4E93BFE6E}.Debug|x64.ActiveCfg = Debug|x64 + {3C123688-D3E5-48D7-8003-DDA4E93BFE6E}.Debug|x64.Build.0 = Debug|x64 + {3C123688-D3E5-48D7-8003-DDA4E93BFE6E}.Release|x64.ActiveCfg = Release|x64 + {3C123688-D3E5-48D7-8003-DDA4E93BFE6E}.Release|x64.Build.0 = Release|x64 + {1EF0BDFD-5583-41DE-9BF4-9E7112651D12}.Debug|x64.ActiveCfg = Debug|x64 + {1EF0BDFD-5583-41DE-9BF4-9E7112651D12}.Debug|x64.Build.0 = Debug|x64 + {1EF0BDFD-5583-41DE-9BF4-9E7112651D12}.Release|x64.ActiveCfg = Release|x64 + {1EF0BDFD-5583-41DE-9BF4-9E7112651D12}.Release|x64.Build.0 = Release|x64 + {C0759474-25B1-4F51-AE5E-1E1F424BAC89}.Debug|x64.ActiveCfg = Debug|x64 + {C0759474-25B1-4F51-AE5E-1E1F424BAC89}.Debug|x64.Build.0 = Debug|x64 + {C0759474-25B1-4F51-AE5E-1E1F424BAC89}.Release|x64.ActiveCfg = Release|x64 + {C0759474-25B1-4F51-AE5E-1E1F424BAC89}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D03DE2E4-7731-4E13-B3DC-DB94F4156681}.Debug|Any CPU.ActiveCfg = Debug|x64 - {D03DE2E4-7731-4E13-B3DC-DB94F4156681}.Debug|Any CPU.Build.0 = Debug|x64 - {D03DE2E4-7731-4E13-B3DC-DB94F4156681}.Debug|x64.ActiveCfg = Debug|x64 - {D03DE2E4-7731-4E13-B3DC-DB94F4156681}.Debug|x64.Build.0 = Debug|x64 - {D03DE2E4-7731-4E13-B3DC-DB94F4156681}.Debug|x86.ActiveCfg = Debug|x64 - {D03DE2E4-7731-4E13-B3DC-DB94F4156681}.Debug|x86.Build.0 = Debug|x64 - {D03DE2E4-7731-4E13-B3DC-DB94F4156681}.Release|Any CPU.ActiveCfg = Release|x64 - {D03DE2E4-7731-4E13-B3DC-DB94F4156681}.Release|Any CPU.Build.0 = Release|x64 - {D03DE2E4-7731-4E13-B3DC-DB94F4156681}.Release|x64.ActiveCfg = Release|x64 - {D03DE2E4-7731-4E13-B3DC-DB94F4156681}.Release|x64.Build.0 = Release|x64 - {D03DE2E4-7731-4E13-B3DC-DB94F4156681}.Release|x86.ActiveCfg = Release|x64 - {D03DE2E4-7731-4E13-B3DC-DB94F4156681}.Release|x86.Build.0 = Release|x64 + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {7DA782A1-7B3E-42D2-B4EF-EDB951E06A13} EndGlobalSection EndGlobal diff --git a/lib/MoonWorks b/lib/MoonWorks new file mode 160000 index 0000000..408e438 --- /dev/null +++ b/lib/MoonWorks @@ -0,0 +1 @@ +Subproject commit 408e438efcf8a19992c3b0ecd74bfd11b65441e6 diff --git a/moonlibs/windows/FAudio.dll b/moonlibs/windows/FAudio.dll new file mode 100644 index 0000000..b9c6d40 Binary files /dev/null and b/moonlibs/windows/FAudio.dll differ diff --git a/moonlibs/windows/Refresh.dll b/moonlibs/windows/Refresh.dll new file mode 100644 index 0000000..a7a3c38 Binary files /dev/null and b/moonlibs/windows/Refresh.dll differ diff --git a/moonlibs/windows/SDL2.dll b/moonlibs/windows/SDL2.dll new file mode 100644 index 0000000..ddba03c Binary files /dev/null and b/moonlibs/windows/SDL2.dll differ diff --git a/src/Program.cs b/src/Program.cs new file mode 100644 index 0000000..ab4464e --- /dev/null +++ b/src/Program.cs @@ -0,0 +1,20 @@ +using MoonWorks; + +namespace MoonWorksTest +{ + class Program + { + static void Main(string[] args) + { + WindowCreateInfo windowCreateInfo = new WindowCreateInfo + { + WindowWidth = 1280, + WindowHeight = 720, + ScreenMode = ScreenMode.Windowed + }; + + TestGame game = new TestGame(windowCreateInfo, PresentMode.FIFO, 60, true); + game.Run(); + } + } +} diff --git a/src/RaymarchUniforms.cs b/src/RaymarchUniforms.cs new file mode 100644 index 0000000..f57b50a --- /dev/null +++ b/src/RaymarchUniforms.cs @@ -0,0 +1,11 @@ +using System.Runtime.InteropServices; + +namespace MoonWorksTest +{ + [StructLayout(LayoutKind.Sequential)] + struct RaymarchUniforms + { + public float time, padding; + public float resolutionX, resolutionY; + } +} diff --git a/src/TestGame.cs b/src/TestGame.cs new file mode 100644 index 0000000..a2ebfaf --- /dev/null +++ b/src/TestGame.cs @@ -0,0 +1,303 @@ +using MoonWorks; +using MoonWorks.Graphics; +using RefreshCS; +using System.Threading; + +namespace MoonWorksTest +{ + public class TestGame : Game + { + ShaderModule passthroughVertexShaderModule; + ShaderModule raymarchFragmentShaderModule; + RaymarchUniforms raymarchUniforms; + + Texture woodTexture; + Texture noiseTexture; + Sampler sampler; + + Buffer vertexBuffer; + + RefreshCS.Refresh.Rect renderArea; + RefreshCS.Refresh.Rect flip; + RefreshCS.Refresh.Color clearColor; + + Texture mainColorTargetTexture; + TextureSlice mainColorTargetTextureSlice; + ColorTarget mainColorTarget; + + RenderPass mainRenderPass; + Framebuffer mainFramebuffer; + GraphicsPipeline mainGraphicsPipeline; + + byte[] screenshotPixels; + Buffer screenshotBuffer; + uint screenShotBufferSize; + Thread screenshotThread; + + public TestGame(WindowCreateInfo windowCreateInfo, PresentMode presentMode, int targetTimestep = 60, bool debugMode = false) : base(windowCreateInfo, presentMode, targetTimestep, debugMode) + { + var windowWidth = windowCreateInfo.WindowWidth; + var windowHeight = windowCreateInfo.WindowHeight; + + passthroughVertexShaderModule = new ShaderModule(GraphicsDevice, new System.IO.FileInfo("Content/passthrough_vert.spv")); + raymarchFragmentShaderModule = new ShaderModule(GraphicsDevice, new System.IO.FileInfo("Content/hexagon_grid.spv")); + + raymarchUniforms.time = 0; + raymarchUniforms.padding = 0; + raymarchUniforms.resolutionX = windowWidth; + raymarchUniforms.resolutionY = windowHeight; + + woodTexture = Texture.LoadPNG(GraphicsDevice, new System.IO.FileInfo("Content/woodgrain.png")); + noiseTexture = Texture.LoadPNG(GraphicsDevice, new System.IO.FileInfo("Content/noise.png")); + + SamplerState samplerState = SamplerState.LinearWrap; + sampler = new Sampler(GraphicsDevice, ref samplerState); + + /* Load Vertex Data */ + + var vertices = new Vertex[3]; + vertices[0].x = -1; + vertices[0].y = -1; + vertices[0].z = 0; + vertices[0].u = 0; + vertices[0].v = 1; + + vertices[1].x = 3; + vertices[1].y = -1; + vertices[1].z = 0; + vertices[1].u = 1; + vertices[1].v = 1; + + vertices[2].x = -1; + vertices[2].y = 3; + vertices[2].z = 0; + vertices[2].u = 0; + vertices[2].v = 0; + + vertexBuffer = new Buffer(GraphicsDevice, Refresh.BufferUsageFlags.Vertex, 4 * 5 * 3); + vertexBuffer.SetData(0, vertices, 4 * 5 * 3); + + /* Render Pass */ + + renderArea.x = 0; + renderArea.y = 0; + renderArea.w = (int) windowWidth; + renderArea.h = (int) windowHeight; + + flip.x = 0; + flip.y = (int) windowHeight; + flip.w = (int) windowWidth; + flip.h = -(int) windowHeight; + + clearColor.r = 237; + clearColor.g = 41; + clearColor.b = 57; + clearColor.a = byte.MaxValue; + + Refresh.ColorTargetDescription colorTargetDescription = new Refresh.ColorTargetDescription + { + format = Refresh.ColorFormat.R8G8B8A8, + multisampleCount = Refresh.SampleCount.One, + loadOp = Refresh.LoadOp.Clear, + storeOp = Refresh.StoreOp.Store + }; + + mainRenderPass = new RenderPass(GraphicsDevice, colorTargetDescription); + + mainColorTargetTexture = Texture.CreateTexture2D( + GraphicsDevice, + windowWidth, + windowHeight, + Refresh.ColorFormat.R8G8B8A8, + Refresh.TextureUsageFlags.ColorTargetBit + ); + + mainColorTargetTextureSlice = new TextureSlice(mainColorTargetTexture); + + mainColorTarget = new ColorTarget(GraphicsDevice, Refresh.SampleCount.One, ref mainColorTargetTextureSlice); + + mainFramebuffer = new Framebuffer( + GraphicsDevice, + windowWidth, + windowHeight, + mainRenderPass, + null, + mainColorTarget + ); + + /* Pipeline */ + + ColorTargetBlendState[] colorTargetBlendStates = new ColorTargetBlendState[1] + { + ColorTargetBlendState.None + }; + + ColorBlendState colorBlendState = new ColorBlendState + { + LogicOpEnable = false, + LogicOp = Refresh.LogicOp.NoOp, + BlendConstants = new BlendConstants(), + ColorTargetBlendStates = colorTargetBlendStates + }; + + DepthStencilState depthStencilState = DepthStencilState.Disable; + + ShaderStageState vertexShaderState = new ShaderStageState + { + ShaderModule = passthroughVertexShaderModule, + EntryPointName = "main", + UniformBufferSize = 0 + }; + + ShaderStageState fragmentShaderState = new ShaderStageState + { + ShaderModule = raymarchFragmentShaderModule, + EntryPointName = "main", + UniformBufferSize = 4 + }; + + MultisampleState multisampleState = MultisampleState.None; + + GraphicsPipelineLayoutCreateInfo pipelineLayoutCreateInfo = new GraphicsPipelineLayoutCreateInfo + { + VertexSamplerBindingCount = 0, + FragmentSamplerBindingCount = 2 + }; + + RasterizerState rasterizerState = RasterizerState.CullCounterClockwise; + + var vertexBindings = new Refresh.VertexBinding[1] + { + new Refresh.VertexBinding + { + binding = 0, + inputRate = Refresh.VertexInputRate.Vertex, + stride = 4 * 5 + } + }; + + var vertexAttributes = new Refresh.VertexAttribute[2] + { + new Refresh.VertexAttribute + { + binding = 0, + location = 0, + format = Refresh.VertexElementFormat.Vector3, + offset = 0 + }, + new Refresh.VertexAttribute + { + binding = 0, + location = 1, + format = Refresh.VertexElementFormat.Vector2, + offset = 4 * 3 + } + }; + + VertexInputState vertexInputState = new VertexInputState + { + VertexBindings = vertexBindings, + VertexAttributes = vertexAttributes + }; + + var viewports = new Refresh.Viewport[1] + { + new Refresh.Viewport + { + x = 0, + y = 0, + w = windowWidth, + h = windowHeight, + minDepth = 0, + maxDepth = 1 + } + }; + + var scissors = new Refresh.Rect[1] + { + new Refresh.Rect + { + x = 0, + y = 0, + w = (int) windowWidth, + h = (int) windowHeight + } + }; + + ViewportState viewportState = new ViewportState + { + Viewports = viewports, + Scissors = scissors + }; + + mainGraphicsPipeline = new GraphicsPipeline( + GraphicsDevice, + colorBlendState, + depthStencilState, + vertexShaderState, + fragmentShaderState, + multisampleState, + pipelineLayoutCreateInfo, + rasterizerState, + Refresh.PrimitiveType.TriangleList, + vertexInputState, + viewportState, + mainRenderPass + ); + + screenShotBufferSize = windowWidth * windowHeight * 4; + screenshotPixels = new byte[screenShotBufferSize]; + screenshotBuffer = new Buffer(GraphicsDevice, 0, screenShotBufferSize); + screenshotThread = new Thread(new ThreadStart(SaveScreenshot)); + } + + protected override void Update(double dt) + { + raymarchUniforms.time += (float) dt; + } + + protected override void Draw() + { + var screenshotPressed = Input.Keyboard.IsPressed(Keycode.S); + + var commandBuffer = GraphicsDevice.AcquireCommandBuffer(); + + commandBuffer.BeginRenderPass( + mainRenderPass, + mainFramebuffer, + ref renderArea, + clearColor + ); + + commandBuffer.BindGraphicsPipeline(mainGraphicsPipeline); + var fragmentParamOffset = commandBuffer.PushFragmentShaderParams(raymarchUniforms); + commandBuffer.BindVertexBuffers(0, new BufferBinding(vertexBuffer, 0)); + commandBuffer.BindFragmentSamplers( + new TextureSamplerBinding(woodTexture, sampler), + new TextureSamplerBinding(noiseTexture, sampler) + ); + commandBuffer.DrawPrimitives(0, 1, 0, fragmentParamOffset); + commandBuffer.EndRenderPass(); + + if (screenshotPressed) + { + commandBuffer.CopyTextureToBuffer(ref mainColorTargetTextureSlice, screenshotBuffer); + } + + commandBuffer.QueuePresent(ref mainColorTargetTextureSlice, ref flip, Refresh.Filter.Nearest); + GraphicsDevice.Submit(commandBuffer); + + if (screenshotPressed) + { + screenshotThread.Start(); + } + } + + private void SaveScreenshot() + { + GraphicsDevice.Wait(); + screenshotBuffer.GetData(screenshotPixels, screenShotBufferSize); + Texture.SavePNG("screenshot.png", 1280, 720, screenshotPixels); + } + } +} diff --git a/src/Vertex.cs b/src/Vertex.cs new file mode 100644 index 0000000..ea9731c --- /dev/null +++ b/src/Vertex.cs @@ -0,0 +1,11 @@ +using System.Runtime.InteropServices; + +namespace MoonWorksTest +{ + [StructLayout(LayoutKind.Sequential)] + struct Vertex + { + public float x, y, z; + public float u, v; + } +}