Compare commits

...

74 Commits

Author SHA1 Message Date
cosmonaut 041b52ed44 compute sprite batch 2024-06-11 17:20:47 -07:00
cosmonaut f17e9851f3 update with MoonWorks changes 2024-06-11 10:08:37 -07:00
cosmonaut 512ef598d2 examples now use new shader creation system 2024-06-10 16:54:27 -07:00
cosmonaut ea7c1245bc WindowResizingExample 2024-06-06 16:24:12 -07:00
cosmonaut 486b55527f VideoPlayerExample 2024-06-06 16:19:35 -07:00
cosmonaut 2cfc8fa512 VertexSamplerExample 2024-06-06 16:05:36 -07:00
cosmonaut 31d659020e TriangleVertexBufferExample 2024-06-06 16:01:11 -07:00
cosmonaut 6dbcd65fbe TextureMipmapsExample 2024-06-06 15:56:42 -07:00
cosmonaut 002bcc7913 TexturedQuadExample 2024-06-06 15:51:29 -07:00
cosmonaut 7fe6fba2d7 TexturedAnimatedQuadExample 2024-06-06 15:43:24 -07:00
cosmonaut dd8a416052 Texture3DExample 2024-06-06 15:34:15 -07:00
cosmonaut 071ff5788c Texture3DCopyExample 2024-06-06 15:28:16 -07:00
cosmonaut 2efb502cd4 StoreLoadExample 2024-06-06 15:20:20 -07:00
cosmonaut b826ff6a89 RenderTextureMipmapsExample 2024-06-06 15:11:11 -07:00
cosmonaut 6d0add6230 RenderTextureCubeExample 2024-06-06 15:03:43 -07:00
cosmonaut d538c2c935 RenderTexture2DExample 2024-06-06 14:58:30 -07:00
cosmonaut 1568924f55 RenderTexture2DArrayExample 2024-06-06 14:47:06 -07:00
cosmonaut 42f66e8a87 MSAAExample 2024-06-06 14:38:53 -07:00
cosmonaut 4b2a9385d9 MSAACubeExample 2024-06-06 14:19:46 -07:00
cosmonaut ab796356b9 InstancingAndOffsetsExample 2024-06-06 14:11:14 -07:00
cosmonaut e85220318f GetBufferDataExample 2024-06-06 13:24:11 -07:00
cosmonaut 83bdf69e64 DrawIndirectExample 2024-06-06 13:09:45 -07:00
cosmonaut 17aac39403 DepthMSAAExample 2024-06-06 13:00:14 -07:00
cosmonaut 7b58a1ac06 CullFaceExample 2024-06-06 12:13:01 -07:00
cosmonaut 877b533d7b CubeExample 2024-06-06 12:06:37 -07:00
cosmonaut 8258bb07a4 CopyTextureExample 2024-06-06 11:14:24 -07:00
cosmonaut 2387a03e1d Refresh API update 2024-06-06 10:52:12 -07:00
cosmonaut d582bfe473 fix up some window behavior 2024-06-05 22:56:09 -07:00
cosmonaut 69ffbbf03a shader fixup and new example structure 2024-06-05 22:47:06 -07:00
cosmonaut da90d28c33 restructure graphics tests 2024-06-05 14:19:43 -07:00
cosmonaut 75c13c3c6b Cube test debug names 2024-03-11 16:11:27 -07:00
cosmonaut 5782970ad8 go back to vulkan default 2024-03-11 10:22:59 -07:00
cosmonaut 39daf3cad4 update WriteOptions 2024-03-11 10:20:54 -07:00
cosmonaut b66dc20768 change default back to vulkan 2024-03-07 14:25:51 -08:00
cosmonaut b283df5d6b rename Discard to Cycle 2024-03-07 14:24:54 -08:00
cosmonaut 43cd8f0182 change backend selection behavior 2024-03-07 10:35:12 -08:00
cosmonaut f3eacbf776 comment on DepthMSAA 2024-03-07 00:03:42 -08:00
cosmonaut 17a321dcf7 change success message from error to info 2024-03-06 23:59:34 -08:00
cosmonaut 2435b4d226 rename TestUtils.DefaultBackend to just TestUtils.Backend 2024-03-06 14:31:22 -08:00
cosmonaut e4f4e53f2c more tests on D3D11 2024-03-06 14:23:06 -08:00
cosmonaut 5159442540 start converting tests to be D3D11-compatibility 2024-03-06 00:15:44 -08:00
cosmonaut beacd05925 fix BasicStencil 2024-03-02 23:10:52 -08:00
cosmonaut 0855bf6e26 update bindings and WriteOptions API 2024-03-01 15:03:29 -08:00
cosmonaut 52f4e361ae use element-wise buffer upload in GetBufferData 2024-02-23 15:40:18 -08:00
cosmonaut b8bbbe2327 update VideoPlayer 2024-02-23 15:29:03 -08:00
cosmonaut 844e330a48 update WindowResizing 2024-02-23 14:54:46 -08:00
cosmonaut 89dea810cc update examples that load from compressed image files 2024-02-23 14:54:01 -08:00
cosmonaut 347290bae2 update TextureMipmaps 2024-02-23 14:42:47 -08:00
cosmonaut b462f5d140 update TexturedAnimatedQuad 2024-02-23 14:37:45 -08:00
cosmonaut cd235b9172 rename ResourceInitializer to ResourceUploader 2024-02-23 14:32:56 -08:00
cosmonaut 795331c133 convert Cube test to use UploadAndWait 2024-02-23 14:30:53 -08:00
cosmonaut 1876258114 update Texture3DGame 2024-02-23 14:05:05 -08:00
cosmonaut 6b0f80119a update StoreLoad 2024-02-23 13:34:03 -08:00
cosmonaut 6c54808407 update RenderTextureMipmaps 2024-02-23 13:32:49 -08:00
cosmonaut 59d25a0ee7 update RenderTextureCube 2024-02-23 13:30:29 -08:00
cosmonaut ffd7f76843 update RenderTexture3D 2024-02-23 13:27:36 -08:00
cosmonaut d3ae483074 update RenderTexture2D 2024-02-23 13:25:21 -08:00
cosmonaut c2a029ce85 update MSAA 2024-02-23 13:09:23 -08:00
cosmonaut 683fffad16 update InstancingAndOffsets 2024-02-23 13:06:53 -08:00
cosmonaut c2f1a02ba3 update GetBufferData 2024-02-23 13:04:59 -08:00
cosmonaut c878a26b74 update DrawIndirect 2024-02-23 12:51:42 -08:00
cosmonaut f71917310d update DepthMSAA 2024-02-23 12:49:17 -08:00
cosmonaut 5534edb8fe update CullFace 2024-02-23 12:42:01 -08:00
cosmonaut 3299ff578f update CopyTexture 2024-02-23 12:40:12 -08:00
cosmonaut b9337fdbe6 update ComputeUniforms 2024-02-23 12:03:46 -08:00
cosmonaut 165af544de update CompressedTexture 2024-02-23 12:00:15 -08:00
cosmonaut 329f3c68f4 update ClearScreen_MultiWindow 2024-02-23 11:08:15 -08:00
cosmonaut b50df03dd7 update BasicTriangle 2024-02-23 11:03:04 -08:00
cosmonaut 94438c8991 update BasicStencil 2024-02-23 10:59:38 -08:00
cosmonaut d6ec93525e update BasicCompute 2024-02-23 10:57:54 -08:00
cosmonaut d8f402646a update CubeGame to use resourceInitializer 2024-02-23 10:12:47 -08:00
cosmonaut 91aecfd13c update TexturedQuad 2024-02-23 00:07:51 -08:00
cosmonaut 59c99daa9c re-add Cube screenshot feature 2024-02-22 22:51:01 -08:00
cosmonaut 110151ad56 update Cube for new API 2024-02-21 23:30:15 -08:00
182 changed files with 5828 additions and 4966 deletions

7
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,7 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": []
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,142 +0,0 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Math.Float;
namespace MoonWorks.Test
{
class BasicComputeGame : Game
{
private GraphicsPipeline drawPipeline;
private Texture texture;
private Sampler sampler;
private Buffer vertexBuffer;
public BasicComputeGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{
// Create the compute pipeline that writes texture data
ShaderModule fillTextureComputeShaderModule = new ShaderModule(
GraphicsDevice,
TestUtils.GetShaderPath("FillTexture.comp")
);
ComputePipeline fillTextureComputePipeline = new ComputePipeline(
GraphicsDevice,
ComputeShaderInfo.Create(fillTextureComputeShaderModule, "main", 0, 1)
);
// Create the compute pipeline that calculates squares of numbers
ShaderModule calculateSquaresComputeShaderModule = new ShaderModule(
GraphicsDevice,
TestUtils.GetShaderPath("CalculateSquares.comp")
);
ComputePipeline calculateSquaresComputePipeline = new ComputePipeline(
GraphicsDevice,
ComputeShaderInfo.Create(calculateSquaresComputeShaderModule, "main", 1, 0)
);
// Create the graphics pipeline
ShaderModule vertShaderModule = new ShaderModule(
GraphicsDevice,
TestUtils.GetShaderPath("TexturedQuad.vert")
);
ShaderModule fragShaderModule = new ShaderModule(
GraphicsDevice,
TestUtils.GetShaderPath("TexturedQuad.frag")
);
GraphicsPipelineCreateInfo drawPipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
MainWindow.SwapchainFormat,
vertShaderModule,
fragShaderModule
);
drawPipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureVertex>();
drawPipelineCreateInfo.FragmentShaderInfo.SamplerBindingCount = 1;
drawPipeline = new GraphicsPipeline(
GraphicsDevice,
drawPipelineCreateInfo
);
// Create buffers and textures
uint[] squares = new uint[64];
Buffer squaresBuffer = Buffer.Create<uint>(
GraphicsDevice,
BufferUsageFlags.Compute,
(uint) squares.Length
);
vertexBuffer = Buffer.Create<PositionTextureVertex>(
GraphicsDevice,
BufferUsageFlags.Vertex,
6
);
texture = Texture.CreateTexture2D(
GraphicsDevice,
MainWindow.Width,
MainWindow.Height,
TextureFormat.R8G8B8A8,
TextureUsageFlags.Compute | TextureUsageFlags.Sampler
);
sampler = new Sampler(GraphicsDevice, new SamplerCreateInfo());
// Upload GPU resources and dispatch compute work
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, 0)),
new PositionTextureVertex(new Vector3(1, 1, 0), new Vector2(1, 1)),
new PositionTextureVertex(new Vector3(-1, 1, 0), new Vector2(0, 1)),
});
// This should result in a bright yellow texture!
cmdbuf.BindComputePipeline(fillTextureComputePipeline);
cmdbuf.BindComputeTextures(texture);
cmdbuf.DispatchCompute(texture.Width / 8, texture.Height / 8, 1, 0);
// This calculates the squares of the first N integers!
cmdbuf.BindComputePipeline(calculateSquaresComputePipeline);
cmdbuf.BindComputeBuffers(squaresBuffer);
cmdbuf.DispatchCompute((uint) squares.Length / 8, 1, 1, 0);
var fence = GraphicsDevice.SubmitAndAcquireFence(cmdbuf);
GraphicsDevice.WaitForFences(fence);
GraphicsDevice.ReleaseFence(fence);
// Print the squares!
squaresBuffer.GetData(squares);
Logger.LogInfo("Squares of the first " + squares.Length + " integers: " + string.Join(", ", squares));
}
protected override void Update(System.TimeSpan delta) { }
protected override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture? backbuffer = cmdbuf.AcquireSwapchainTexture(MainWindow);
if (backbuffer != null)
{
cmdbuf.BeginRenderPass(new ColorAttachmentInfo(backbuffer, Color.CornflowerBlue));
cmdbuf.BindGraphicsPipeline(drawPipeline);
cmdbuf.BindFragmentSamplers(new TextureSamplerBinding(texture, sampler));
cmdbuf.BindVertexBuffers(vertexBuffer);
cmdbuf.DrawPrimitives(0, 2, 0, 0);
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
BasicComputeGame game = new BasicComputeGame();
game.Run();
}
}
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,110 +0,0 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Math.Float;
namespace MoonWorks.Test
{
class BasicStencilGame : Game
{
private GraphicsPipeline maskerPipeline;
private GraphicsPipeline maskeePipeline;
private Buffer vertexBuffer;
private Texture depthStencilTexture;
public BasicStencilGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{
// Load the shaders
ShaderModule vertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("PositionColor.vert"));
ShaderModule fragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("SolidColor.frag"));
// Create the graphics pipelines
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
MainWindow.SwapchainFormat,
vertShaderModule,
fragShaderModule
);
pipelineCreateInfo.AttachmentInfo.HasDepthStencilAttachment = true;
pipelineCreateInfo.AttachmentInfo.DepthStencilFormat = TextureFormat.D16S8;
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionColorVertex>();
pipelineCreateInfo.DepthStencilState = new DepthStencilState
{
StencilTestEnable = true,
FrontStencilState = new StencilOpState
{
Reference = 1,
WriteMask = 0xFF,
CompareOp = CompareOp.Never,
FailOp = StencilOp.Replace,
}
};
maskerPipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
pipelineCreateInfo.DepthStencilState = new DepthStencilState
{
StencilTestEnable = true,
FrontStencilState = new StencilOpState
{
Reference = 0,
CompareMask = 0xFF,
WriteMask = 0,
CompareOp = CompareOp.Equal,
}
};
maskeePipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create and populate the GPU resources
depthStencilTexture = Texture.CreateTexture2D(
GraphicsDevice,
MainWindow.Width,
MainWindow.Height,
TextureFormat.D16S8,
TextureUsageFlags.DepthStencilTarget
);
vertexBuffer = Buffer.Create<PositionColorVertex>(GraphicsDevice, BufferUsageFlags.Vertex, 6);
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
cmdbuf.SetBufferData(
vertexBuffer,
new PositionColorVertex[]
{
new PositionColorVertex(new Vector3(-0.5f, 0.5f, 0), Color.Yellow),
new PositionColorVertex(new Vector3(0.5f, 0.5f, 0), Color.Yellow),
new PositionColorVertex(new Vector3(0, -0.5f, 0), Color.Yellow),
new PositionColorVertex(new Vector3(-1, 1, 0), Color.Red),
new PositionColorVertex(new Vector3(1, 1, 0), Color.Lime),
new PositionColorVertex(new Vector3(0, -1, 0), Color.Blue),
}
);
GraphicsDevice.Submit(cmdbuf);
}
protected override void Update(System.TimeSpan delta) { }
protected override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture? backbuffer = cmdbuf.AcquireSwapchainTexture(MainWindow);
if (backbuffer != null)
{
cmdbuf.BeginRenderPass(
new DepthStencilAttachmentInfo(depthStencilTexture, new DepthStencilValue(0, 0), StoreOp.DontCare, StoreOp.DontCare),
new ColorAttachmentInfo(backbuffer, Color.Black)
);
cmdbuf.BindGraphicsPipeline(maskerPipeline);
cmdbuf.BindVertexBuffers(vertexBuffer);
cmdbuf.DrawPrimitives(0, 1, 0, 0);
cmdbuf.BindGraphicsPipeline(maskeePipeline);
cmdbuf.DrawPrimitives(3, 1, 0, 0);
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
BasicStencilGame p = new BasicStencilGame();
p.Run();
}
}
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,87 +0,0 @@
using MoonWorks;
using MoonWorks.Graphics;
namespace MoonWorks.Test
{
class BasicTriangleGame : Game
{
private GraphicsPipeline fillPipeline;
private GraphicsPipeline linePipeline;
private Viewport smallViewport = new Viewport(160, 120, 320, 240);
private Rect scissorRect = new Rect(320, 240, 320, 240);
private bool useWireframeMode;
private bool useSmallViewport;
private bool useScissorRect;
public BasicTriangleGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{
Logger.LogInfo("Press Left to toggle wireframe mode\nPress Down to toggle small viewport\nPress Right to toggle scissor rect");
ShaderModule vertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("RawTriangle.vert"));
ShaderModule fragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("SolidColor.frag"));
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
MainWindow.SwapchainFormat,
vertShaderModule,
fragShaderModule
);
fillPipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
pipelineCreateInfo.RasterizerState.FillMode = FillMode.Line;
linePipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
}
protected override void Update(System.TimeSpan delta)
{
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Left))
{
useWireframeMode = !useWireframeMode;
Logger.LogInfo("Using wireframe mode: " + useWireframeMode);
}
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Bottom))
{
useSmallViewport = !useSmallViewport;
Logger.LogInfo("Using small viewport: " + useSmallViewport);
}
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Right))
{
useScissorRect = !useScissorRect;
Logger.LogInfo("Using scissor rect: " + useScissorRect);
}
}
protected override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture? backbuffer = cmdbuf.AcquireSwapchainTexture(MainWindow);
if (backbuffer != null)
{
cmdbuf.BeginRenderPass(new ColorAttachmentInfo(backbuffer, Color.Black));
cmdbuf.BindGraphicsPipeline(useWireframeMode ? linePipeline : fillPipeline);
if (useSmallViewport)
{
cmdbuf.SetViewport(smallViewport);
}
if (useScissorRect)
{
cmdbuf.SetScissor(scissorRect);
}
cmdbuf.DrawPrimitives(0, 1, 0, 0);
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
BasicTriangleGame game = new BasicTriangleGame();
game.Run();
}
}
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,30 +0,0 @@
using MoonWorks;
using MoonWorks.Graphics;
namespace MoonWorks.Test
{
class ClearScreenGame : Game
{
public ClearScreenGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true) { }
protected override void Update(System.TimeSpan delta) { }
protected override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture? backbuffer = cmdbuf.AcquireSwapchainTexture(MainWindow);
if (backbuffer != null)
{
cmdbuf.BeginRenderPass(new ColorAttachmentInfo(backbuffer, Color.CornflowerBlue));
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
ClearScreenGame game = new ClearScreenGame();
game.Run();
}
}
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,51 +0,0 @@
using MoonWorks;
using MoonWorks.Graphics;
namespace MoonWorks.Test
{
class ClearScreen_MultiWindowGame : Game
{
private Window secondaryWindow;
public ClearScreen_MultiWindowGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{
secondaryWindow = new Window(
new WindowCreateInfo("Secondary Window", 640, 480, ScreenMode.Windowed, PresentMode.FIFO, false, false),
GraphicsDevice.WindowFlags
);
GraphicsDevice.ClaimWindow(secondaryWindow, PresentMode.FIFO);
}
protected override void Update(System.TimeSpan delta) { }
protected override void Draw(double alpha)
{
CommandBuffer cmdbuf;
Texture? backbuffer;
cmdbuf = GraphicsDevice.AcquireCommandBuffer();
backbuffer = cmdbuf.AcquireSwapchainTexture(MainWindow);
if (backbuffer != null)
{
cmdbuf.BeginRenderPass(new ColorAttachmentInfo(backbuffer, Color.CornflowerBlue));
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
cmdbuf = GraphicsDevice.AcquireCommandBuffer();
backbuffer = cmdbuf.AcquireSwapchainTexture(secondaryWindow);
if (backbuffer != null)
{
cmdbuf.BeginRenderPass(new ColorAttachmentInfo(backbuffer, Color.Aquamarine));
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
ClearScreen_MultiWindowGame game = new ClearScreen_MultiWindowGame();
game.Run();
}
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,7 +1,7 @@
#version 450
layout (local_size_x = 8) in;
layout (set = 0, binding = 0) buffer outBuffer
layout (set = 1, binding = 0) writeonly buffer outBuffer
{
uint squares[];
};

View File

@ -0,0 +1,19 @@
#version 450
layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
layout (set = 1, binding = 0, rgba8) uniform writeonly image2D outImage;
layout (set = 2, binding = 0) uniform UBO
{
float time;
} ubo;
void main()
{
vec2 size = imageSize(outImage);
vec2 coord = gl_GlobalInvocationID.xy;
vec2 uv = coord / size;
vec3 col = 0.5 + 0.5*cos(ubo.time + uv.xyx + vec3(0, 2, 4));
imageStore(outImage, ivec2(coord), vec4(col, 1.0));
}

View File

@ -5,7 +5,7 @@ layout (location = 1) in vec4 Color;
layout (location = 0) out vec4 outColor;
layout (binding = 0, set = 2) uniform UniformBlock
layout (set = 1, binding = 0) uniform UniformBlock
{
mat4x4 MatrixTransform;
};

View File

@ -5,7 +5,7 @@ layout (location = 1) in vec2 TexCoord;
layout (location = 0) out vec4 outColor;
layout(binding = 0, set = 0) uniform sampler2D Sampler;
layout(set = 0, binding = 0) uniform sampler2D Sampler;
void main()
{

View File

@ -8,17 +8,17 @@ void main()
if (gl_VertexIndex == 0)
{
pos = vec2(-1, 1);
pos = vec2(-1, -1);
outColor = vec4(1, 0, 0, 1);
}
else if (gl_VertexIndex == 1)
{
pos = vec2(1, 1);
pos = vec2(1, -1);
outColor = vec4(0, 1, 0, 1);
}
else if (gl_VertexIndex == 2)
{
pos = vec2(0, -1);
pos = vec2(0, 1);
outColor = vec4(0, 0, 1, 1);
}

View File

@ -3,7 +3,7 @@
layout(location = 0) in vec3 TexCoord;
layout(location = 0) out vec4 FragColor;
layout(binding = 0, set = 1) uniform samplerCube SkyboxSampler;
layout(set = 2, binding = 0) uniform samplerCube SkyboxSampler;
void main()
{

View File

@ -3,7 +3,7 @@
layout(location = 0) in vec3 inPos;
layout(location = 0) out vec3 vPos;
layout(set = 2, binding = 0) uniform UBO
layout(set = 1, binding = 0) uniform UBO
{
mat4 ViewProjection;
} ubo;

View File

@ -0,0 +1,79 @@
#version 450
struct SpriteComputeData
{
vec3 position;
float rotation;
vec2 scale;
vec4 color;
};
struct SpriteVertex
{
vec4 position;
vec2 texcoord;
vec4 color;
};
layout (local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
layout (std430, set = 0, binding = 0) readonly buffer inBuffer
{
SpriteComputeData computeData[];
};
layout (std430, set = 1, binding = 0) writeonly buffer outBuffer
{
SpriteVertex vertexData[];
};
void main()
{
uint n = gl_GlobalInvocationID.x;
SpriteComputeData currentSpriteData = computeData[n];
mat4 Scale = mat4(
currentSpriteData.scale.x, 0, 0, 0,
0, currentSpriteData.scale.y, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
);
float c = cos(currentSpriteData.rotation);
float s = sin(currentSpriteData.rotation);
mat4 Rotation = mat4(
c, s, 0, 0,
-s, c, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
);
mat4 Translation = mat4(
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
currentSpriteData.position.x, currentSpriteData.position.y, currentSpriteData.position.z, 1
);
mat4 Model = Translation * Rotation * Scale;
vec4 topLeft = vec4(0, 0, 0, 1);
vec4 topRight = vec4(1, 0, 0, 1);
vec4 bottomLeft = vec4(0, 1, 0, 1);
vec4 bottomRight = vec4(1, 1, 0, 1);
vertexData[n*4] .position = Model * topLeft;
vertexData[n*4+1].position = Model * topRight;
vertexData[n*4+2].position = Model * bottomLeft;
vertexData[n*4+3].position = Model * bottomRight;
vertexData[n*4] .texcoord = vec2(0, 0);
vertexData[n*4+1].texcoord = vec2(1, 0);
vertexData[n*4+2].texcoord = vec2(0, 1);
vertexData[n*4+3].texcoord = vec2(1, 1);
vertexData[n*4] .color = currentSpriteData.color;
vertexData[n*4+1].color = currentSpriteData.color;
vertexData[n*4+2].color = currentSpriteData.color;
vertexData[n*4+3].color = currentSpriteData.color;
}

View File

@ -1,12 +1,11 @@
#version 450
layout (location = 0) in vec2 TexCoord;
layout (location = 0) out vec4 FragColor;
layout(binding = 0, set = 1) uniform sampler2D Sampler;
layout(set = 2, binding = 0) uniform sampler2D Sampler;
layout (binding = 0, set = 3) uniform UniformBlock
layout (set = 3, binding = 0) uniform UniformBlock
{
float zNear;
float zFar;

View File

@ -4,7 +4,7 @@ layout (location = 0) in vec2 TexCoord;
layout (location = 0) out vec4 FragColor;
layout(binding = 0, set = 1) uniform sampler2D Sampler;
layout(set = 2, binding = 0) uniform sampler2D Sampler;
void main()
{

View File

@ -0,0 +1,17 @@
#version 450
layout (location = 0) in vec2 TexCoord;
layout (location = 0) out vec4 FragColor;
layout(set = 2, binding = 0) uniform sampler2DArray Sampler;
layout (set = 3, binding = 0) uniform UniformBlock
{
float depth;
};
void main()
{
FragColor = texture(Sampler, vec3(TexCoord, depth));
}

View File

@ -4,9 +4,9 @@ layout (location = 0) in vec2 TexCoord;
layout (location = 0) out vec4 FragColor;
layout(binding = 0, set = 1) uniform sampler3D Sampler;
layout(set = 2, binding = 0) uniform sampler3D Sampler;
layout (binding = 0, set = 3) uniform UniformBlock
layout (set = 3, binding = 0) uniform UniformBlock
{
float depth;
};

View File

@ -0,0 +1,13 @@
#version 450
layout (location = 0) in vec2 TexCoord;
layout (location = 1) in vec4 Color;
layout (location = 0) out vec4 FragColor;
layout(set = 2, binding = 0) uniform sampler2D Sampler;
void main()
{
FragColor = Color * texture(Sampler, TexCoord);
}

View File

@ -0,0 +1,20 @@
#version 450
layout (location = 0) in vec4 Position;
layout (location = 1) in vec2 TexCoord;
layout (location = 2) in vec4 Color;
layout (location = 0) out vec2 outTexCoord;
layout (location = 1) out vec4 outColor;
layout (set = 1, binding = 0) uniform UniformBlock
{
mat4x4 MatrixTransform;
};
void main()
{
outTexCoord = TexCoord;
outColor = Color;
gl_Position = MatrixTransform * Position;
}

View File

@ -5,7 +5,7 @@ layout (location = 1) in vec2 TexCoord;
layout (location = 0) out vec2 outTexCoord;
layout (binding = 0, set = 2) uniform UniformBlock
layout (set = 1, binding = 0) uniform UniformBlock
{
mat4x4 MatrixTransform;
};

View File

@ -4,9 +4,9 @@ layout (location = 0) in vec2 TexCoord;
layout (location = 0) out vec4 FragColor;
layout(binding = 0, set = 1) uniform sampler2D Sampler;
layout(set = 2, binding = 0) uniform sampler2D Sampler;
layout (binding = 0, set = 3) uniform UniformBlock
layout (set = 3, binding = 0) uniform UniformBlock
{
vec4 MultiplyColor;
};

View File

Before

Width:  |  Height:  |  Size: 3.0 MiB

After

Width:  |  Height:  |  Size: 3.0 MiB

View File

Before

Width:  |  Height:  |  Size: 954 KiB

After

Width:  |  Height:  |  Size: 954 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 MiB

After

Width:  |  Height:  |  Size: 1.7 MiB

View File

Before

Width:  |  Height:  |  Size: 2.4 MiB

After

Width:  |  Height:  |  Size: 2.4 MiB

View File

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

Before

Width:  |  Height:  |  Size: 802 B

After

Width:  |  Height:  |  Size: 802 B

View File

Before

Width:  |  Height:  |  Size: 874 B

After

Width:  |  Height:  |  Size: 874 B

View File

Before

Width:  |  Height:  |  Size: 678 B

After

Width:  |  Height:  |  Size: 678 B

View File

Before

Width:  |  Height:  |  Size: 201 B

After

Width:  |  Height:  |  Size: 201 B

View File

Before

Width:  |  Height:  |  Size: 2.1 MiB

After

Width:  |  Height:  |  Size: 2.1 MiB

View File

Before

Width:  |  Height:  |  Size: 94 B

After

Width:  |  Height:  |  Size: 94 B

View File

Before

Width:  |  Height:  |  Size: 94 B

After

Width:  |  Height:  |  Size: 94 B

View File

Before

Width:  |  Height:  |  Size: 94 B

After

Width:  |  Height:  |  Size: 94 B

View File

Before

Width:  |  Height:  |  Size: 92 B

After

Width:  |  Height:  |  Size: 92 B

View File

Before

Width:  |  Height:  |  Size: 94 B

After

Width:  |  Height:  |  Size: 94 B

View File

Before

Width:  |  Height:  |  Size: 94 B

After

Width:  |  Height:  |  Size: 94 B

View File

Before

Width:  |  Height:  |  Size: 94 B

After

Width:  |  Height:  |  Size: 94 B

View File

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

116
Common/TestUtils.cs Normal file
View File

@ -0,0 +1,116 @@
using MoonWorks;
using MoonWorks.Graphics;
namespace MoonWorksGraphicsTests;
public static class TestUtils
{
public static GraphicsPipelineCreateInfo GetStandardGraphicsPipelineCreateInfo(
TextureFormat swapchainFormat,
Shader vertShader,
Shader fragShader
) {
return new GraphicsPipelineCreateInfo
{
AttachmentInfo = new GraphicsPipelineAttachmentInfo(
new ColorAttachmentDescription(
swapchainFormat,
ColorAttachmentBlendState.Opaque
)
),
DepthStencilState = DepthStencilState.Disable,
MultisampleState = MultisampleState.None,
PrimitiveType = PrimitiveType.TriangleList,
RasterizerState = RasterizerState.CCW_CullNone,
VertexInputState = VertexInputState.Empty,
VertexShader = vertShader,
FragmentShader = fragShader
};
}
public static string GetShaderPath(string shaderName)
{
return SDL2.SDL.SDL_GetBasePath() + "Content/Shaders/Compiled/" + shaderName + ".spv";
}
public static string GetTexturePath(string textureName)
{
return SDL2.SDL.SDL_GetBasePath() + "Content/Textures/" + textureName;
}
public static string GetVideoPath(string videoName)
{
return SDL2.SDL.SDL_GetBasePath() + "Content/Videos/" + videoName;
}
public enum ButtonType
{
Left, // A/left arrow on keyboard, left face button on gamepad
Bottom, // S/down arrow on keyboard, bottom face button on gamepad
Right // D/right arrow on keyboard, right face button on gamepad
}
public static bool CheckButtonPressed(MoonWorks.Input.Inputs inputs, ButtonType buttonType)
{
bool pressed = false;
if (buttonType == ButtonType.Left)
{
pressed = (
(inputs.GamepadExists(0) && inputs.GetGamepad(0).DpadLeft.IsPressed) ||
inputs.Keyboard.IsPressed(MoonWorks.Input.KeyCode.Left) ||
inputs.Keyboard.IsPressed(MoonWorks.Input.KeyCode.A)
);
}
else if (buttonType == ButtonType.Bottom)
{
pressed = (
(inputs.GamepadExists(0) && inputs.GetGamepad(0).DpadDown.IsPressed) ||
inputs.Keyboard.IsPressed(MoonWorks.Input.KeyCode.Down) ||
inputs.Keyboard.IsPressed(MoonWorks.Input.KeyCode.S)
);
}
else if (buttonType == ButtonType.Right)
{
pressed = (
(inputs.GamepadExists(0) && inputs.GetGamepad(0).DpadRight.IsPressed) ||
inputs.Keyboard.IsPressed(MoonWorks.Input.KeyCode.Right) ||
inputs.Keyboard.IsPressed(MoonWorks.Input.KeyCode.D)
);
}
return pressed;
}
public static bool CheckButtonDown(MoonWorks.Input.Inputs inputs, ButtonType buttonType)
{
bool down = false;
if (buttonType == ButtonType.Left)
{
down = (
(inputs.GamepadExists(0) && inputs.GetGamepad(0).DpadLeft.IsDown) ||
inputs.Keyboard.IsDown(MoonWorks.Input.KeyCode.Left) ||
inputs.Keyboard.IsDown(MoonWorks.Input.KeyCode.A)
);
}
else if (buttonType == ButtonType.Bottom)
{
down = (
(inputs.GamepadExists(0) && inputs.GetGamepad(0).DpadDown.IsDown) ||
inputs.Keyboard.IsDown(MoonWorks.Input.KeyCode.Down) ||
inputs.Keyboard.IsDown(MoonWorks.Input.KeyCode.S)
);
}
else if (buttonType == ButtonType.Right)
{
down = (
(inputs.GamepadExists(0) && inputs.GetGamepad(0).DpadRight.IsDown) ||
inputs.Keyboard.IsDown(MoonWorks.Input.KeyCode.Right) ||
inputs.Keyboard.IsDown(MoonWorks.Input.KeyCode.D)
);
}
return down;
}
}

13
Common/UniformTypes.cs Normal file
View File

@ -0,0 +1,13 @@
using MoonWorks.Math.Float;
namespace MoonWorksGraphicsTests;
public struct TransformVertexUniform
{
public Matrix4x4 ViewProjection;
public TransformVertexUniform(Matrix4x4 viewProjection)
{
ViewProjection = viewProjection;
}
}

115
Common/VertexTypes.cs Normal file
View File

@ -0,0 +1,115 @@
using System.Runtime.InteropServices;
using MoonWorks.Graphics;
using MoonWorks.Math.Float;
namespace MoonWorksGraphicsTests;
[StructLayout(LayoutKind.Sequential)]
public struct PositionVertex : IVertexType
{
public Vector3 Position;
public PositionVertex(Vector3 position)
{
Position = position;
}
public static VertexElementFormat[] Formats { get; } =
[
VertexElementFormat.Vector3
];
public static uint[] Offsets { get; } = [ 0 ];
public override string ToString()
{
return Position.ToString();
}
}
[StructLayout(LayoutKind.Sequential)]
public struct PositionColorVertex : IVertexType
{
public Vector3 Position;
public Color Color;
public PositionColorVertex(Vector3 position, Color color)
{
Position = position;
Color = color;
}
public static VertexElementFormat[] Formats { get; } =
[
VertexElementFormat.Vector3,
VertexElementFormat.Color
];
public static uint[] Offsets { get; } =
[
0,
12
];
public override string ToString()
{
return Position + " | " + Color;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct PositionTextureVertex : IVertexType
{
public Vector3 Position;
public Vector2 TexCoord;
public PositionTextureVertex(Vector3 position, Vector2 texCoord)
{
Position = position;
TexCoord = texCoord;
}
public static VertexElementFormat[] Formats { get; } = new VertexElementFormat[2]
{
VertexElementFormat.Vector3,
VertexElementFormat.Vector2
};
public static uint[] Offsets { get; } =
[
0,
12
];
public override string ToString()
{
return Position + " | " + TexCoord;
}
}
[StructLayout(LayoutKind.Explicit, Size = 48)]
struct PositionTextureColorVertex : IVertexType
{
[FieldOffset(0)]
public Vector4 Position;
[FieldOffset(16)]
public Vector2 TexCoord;
[FieldOffset(32)]
public Vector4 Color;
public static VertexElementFormat[] Formats { get; } =
[
VertexElementFormat.Vector4,
VertexElementFormat.Vector2,
VertexElementFormat.Vector4
];
public static uint[] Offsets { get; } =
[
0,
16,
32
];
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,133 +0,0 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Math.Float;
using System.IO;
namespace MoonWorks.Test
{
class CompressedTexturesGame : Game
{
private GraphicsPipeline pipeline;
private Buffer vertexBuffer;
private Buffer indexBuffer;
private Sampler sampler;
private Texture[] textures;
private string[] textureNames = new string[]
{
"BC1",
"BC2",
"BC3",
"BC7"
};
private int currentTextureIndex;
public CompressedTexturesGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{
Logger.LogInfo("Press Left and Right to cycle between textures");
Logger.LogInfo("Setting texture to: " + textureNames[0]);
// Load the shaders
ShaderModule vertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuad.vert"));
ShaderModule fragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuad.frag"));
// Create the graphics pipeline
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
MainWindow.SwapchainFormat,
vertShaderModule,
fragShaderModule
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureVertex>();
pipelineCreateInfo.FragmentShaderInfo.SamplerBindingCount = 1;
pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create sampler
sampler = new Sampler(GraphicsDevice, SamplerCreateInfo.LinearWrap);
// Create texture array
textures = new Texture[textureNames.Length];
// Create and populate the GPU resources
vertexBuffer = Buffer.Create<PositionTextureVertex>(GraphicsDevice, BufferUsageFlags.Vertex, 4);
indexBuffer = Buffer.Create<ushort>(GraphicsDevice, BufferUsageFlags.Index, 6);
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,
}
);
for (int i = 0; i < textureNames.Length; i += 1)
{
Logger.LogInfo(textureNames[i]);
using (FileStream fs = new FileStream(TestUtils.GetTexturePath(textureNames[i] + ".dds"), FileMode.Open, FileAccess.Read))
textures[i] = Texture.LoadDDS(GraphicsDevice, cmdbuf, fs);
}
GraphicsDevice.Submit(cmdbuf);
}
protected override void Update(System.TimeSpan delta)
{
int prevSamplerIndex = currentTextureIndex;
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Left))
{
currentTextureIndex -= 1;
if (currentTextureIndex < 0)
{
currentTextureIndex = textureNames.Length - 1;
}
}
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Right))
{
currentTextureIndex += 1;
if (currentTextureIndex >= textureNames.Length)
{
currentTextureIndex = 0;
}
}
if (prevSamplerIndex != currentTextureIndex)
{
Logger.LogInfo("Setting texture to: " + textureNames[currentTextureIndex]);
}
}
protected override void Draw(double alpha)
{
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(textures[currentTextureIndex], sampler));
cmdbuf.DrawIndexedPrimitives(0, 0, 2, 0, 0);
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
CompressedTexturesGame game = new CompressedTexturesGame();
game.Run();
}
}
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,129 +0,0 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Math.Float;
namespace MoonWorks.Test
{
class ComputeUniformsGame : Game
{
private GraphicsPipeline drawPipeline;
private Texture texture;
private Sampler sampler;
private Buffer vertexBuffer;
struct GradientTextureComputeUniforms
{
public uint groupCountX;
public uint groupCountY;
public GradientTextureComputeUniforms(uint w, uint h)
{
groupCountX = w;
groupCountY = h;
}
}
public ComputeUniformsGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{
// Create the compute pipeline that writes texture data
ShaderModule gradientTextureComputeShaderModule = new ShaderModule(
GraphicsDevice,
TestUtils.GetShaderPath("GradientTexture.comp")
);
ComputePipeline gradientTextureComputePipeline = new ComputePipeline(
GraphicsDevice,
ComputeShaderInfo.Create<GradientTextureComputeUniforms>(gradientTextureComputeShaderModule, "main", 0, 1)
);
// Create the graphics pipeline
ShaderModule vertShaderModule = new ShaderModule(
GraphicsDevice,
TestUtils.GetShaderPath("TexturedQuad.vert")
);
ShaderModule fragShaderModule = new ShaderModule(
GraphicsDevice,
TestUtils.GetShaderPath("TexturedQuad.frag")
);
GraphicsPipelineCreateInfo drawPipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
MainWindow.SwapchainFormat,
vertShaderModule,
fragShaderModule
);
drawPipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureVertex>();
drawPipelineCreateInfo.FragmentShaderInfo.SamplerBindingCount = 1;
drawPipeline = new GraphicsPipeline(
GraphicsDevice,
drawPipelineCreateInfo
);
// Create buffers and textures
vertexBuffer = Buffer.Create<PositionTextureVertex>(
GraphicsDevice,
BufferUsageFlags.Vertex,
6
);
texture = Texture.CreateTexture2D(
GraphicsDevice,
MainWindow.Width,
MainWindow.Height,
TextureFormat.R8G8B8A8,
TextureUsageFlags.Compute | TextureUsageFlags.Sampler
);
sampler = new Sampler(GraphicsDevice, new SamplerCreateInfo());
// Upload GPU resources and dispatch compute work
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, 0)),
new PositionTextureVertex(new Vector3(1, 1, 0), new Vector2(1, 1)),
new PositionTextureVertex(new Vector3(-1, 1, 0), new Vector2(0, 1)),
});
GradientTextureComputeUniforms gradientUniforms = new GradientTextureComputeUniforms(
texture.Width / 8,
texture.Height / 8
);
cmdbuf.BindComputePipeline(gradientTextureComputePipeline);
cmdbuf.BindComputeTextures(texture);
uint offset = cmdbuf.PushComputeShaderUniforms(gradientUniforms);
cmdbuf.DispatchCompute(gradientUniforms.groupCountX, gradientUniforms.groupCountY, 1, offset);
GraphicsDevice.Submit(cmdbuf);
}
protected override void Update(System.TimeSpan delta) { }
protected override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture? backbuffer = cmdbuf.AcquireSwapchainTexture(MainWindow);
if (backbuffer != null)
{
cmdbuf.BeginRenderPass(new ColorAttachmentInfo(backbuffer, Color.CornflowerBlue));
cmdbuf.BindGraphicsPipeline(drawPipeline);
cmdbuf.BindFragmentSamplers(new TextureSamplerBinding(texture, sampler));
cmdbuf.BindVertexBuffers(vertexBuffer);
cmdbuf.DrawPrimitives(0, 2, 0, 0);
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
ComputeUniformsGame game = new ComputeUniformsGame();
game.Run();
}
}
}

View File

@ -6,45 +6,45 @@
</Target>
<ItemGroup Condition="$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))">
<Content Include="..\..\moonlibs\x64\FAudio.dll">
<Content Include="..\moonlibs\x64\FAudio.dll">
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="..\..\moonlibs\x64\Refresh.dll">
<Content Include="..\moonlibs\x64\Refresh.dll">
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="..\..\moonlibs\x64\SDL2.dll">
<Content Include="..\moonlibs\x64\SDL2.dll">
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="..\..\moonlibs\x64\dav1dfile.dll">
<Content Include="..\moonlibs\x64\dav1dfile.dll">
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup Condition="$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))">
<Content Include="..\..\moonlibs\lib64\libFAudio.*">
<Content Include="..\moonlibs\lib64\libFAudio.*">
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="..\..\moonlibs\lib64\libRefresh.*">
<Content Include="..\moonlibs\lib64\libRefresh.*">
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="..\..\moonlibs\lib64\libSDL2-2.0.*">
<Content Include="..\moonlibs\lib64\libSDL2-2.0.*">
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="..\..\moonlibs\windows\libdav1dfile.*">
<Content Include="..\moonlibs\lib64\libdav1dfile.*">
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup Condition="$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))">
<Content Include="..\..\moonlibs\osx\**\*.*" >
<Content Include="..\moonlibs\osx\**\*.*" >
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>

View File

@ -1,17 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,183 +0,0 @@
using System.Runtime.InteropServices;
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Math.Float;
namespace MoonWorks.Test
{
class CopyTextureGame : Game
{
private GraphicsPipeline pipeline;
private Buffer vertexBuffer;
private Buffer indexBuffer;
private Texture originalTexture;
private Texture textureCopy;
private Texture textureSmallCopy;
private Sampler sampler;
public unsafe CopyTextureGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{
// Load the shaders
ShaderModule vertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuad.vert"));
ShaderModule fragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuad.frag"));
// Create the graphics pipeline
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
MainWindow.SwapchainFormat,
vertShaderModule,
fragShaderModule
);
pipelineCreateInfo.AttachmentInfo.ColorAttachmentDescriptions[0].BlendState = ColorAttachmentBlendState.AlphaBlend;
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureVertex>();
pipelineCreateInfo.FragmentShaderInfo.SamplerBindingCount = 1;
pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create sampler
sampler = new Sampler(GraphicsDevice, SamplerCreateInfo.PointClamp);
// Create and populate the GPU resources
vertexBuffer = Buffer.Create<PositionTextureVertex>(GraphicsDevice, BufferUsageFlags.Vertex, 12);
indexBuffer = Buffer.Create<ushort>(GraphicsDevice, BufferUsageFlags.Index, 12);
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
cmdbuf.SetBufferData(
vertexBuffer,
new PositionTextureVertex[]
{
new PositionTextureVertex(new Vector3(-1f, 0f, 0), new Vector2(0, 0)),
new PositionTextureVertex(new Vector3( 0f, 0f, 0), new Vector2(1, 0)),
new PositionTextureVertex(new Vector3( 0f, 1f, 0), new Vector2(1, 1)),
new PositionTextureVertex(new Vector3(-1f, 1f, 0), new Vector2(0, 1)),
new PositionTextureVertex(new Vector3(0f, 0f, 0), new Vector2(0, 0)),
new PositionTextureVertex(new Vector3(1f, 0f, 0), new Vector2(1, 0)),
new PositionTextureVertex(new Vector3(1f, 1f, 0), new Vector2(1, 1)),
new PositionTextureVertex(new Vector3(0f, 1f, 0), new Vector2(0, 1)),
new PositionTextureVertex(new Vector3(-0.5f, -1f, 0), new Vector2(0, 0)),
new PositionTextureVertex(new Vector3( 0.5f, -1f, 0), new Vector2(1, 0)),
new PositionTextureVertex(new Vector3( 0.5f, 0f, 0), new Vector2(1, 1)),
new PositionTextureVertex(new Vector3(-0.5f, 0f, 0), new Vector2(0, 1))
}
);
cmdbuf.SetBufferData(
indexBuffer,
new ushort[]
{
0, 1, 2,
0, 2, 3,
}
);
// Load the texture. Storing the texture bytes so we can compare them.
var fileStream = new System.IO.FileStream(TestUtils.GetTexturePath("ravioli.png"), System.IO.FileMode.Open, System.IO.FileAccess.Read);
var fileLength = fileStream.Length;
var fileBuffer = NativeMemory.Alloc((nuint) fileLength);
var fileSpan = new System.Span<byte>(fileBuffer, (int) fileLength);
fileStream.ReadExactly(fileSpan);
var pixels = RefreshCS.Refresh.Refresh_Image_Load(
(nint) fileBuffer,
(int) fileLength,
out var width,
out var height,
out var byteCount
);
NativeMemory.Free(fileBuffer);
TextureCreateInfo textureCreateInfo = new TextureCreateInfo();
textureCreateInfo.Width = (uint) width;
textureCreateInfo.Height = (uint) height;
textureCreateInfo.Depth = 1;
textureCreateInfo.Format = TextureFormat.R8G8B8A8;
textureCreateInfo.IsCube = false;
textureCreateInfo.LevelCount = 1;
textureCreateInfo.UsageFlags = TextureUsageFlags.Sampler;
originalTexture = new Texture(GraphicsDevice, textureCreateInfo);
cmdbuf.SetTextureData(originalTexture, pixels, (uint) byteCount);
// Create a 1:1 copy of the texture
textureCopy = new Texture(GraphicsDevice, textureCreateInfo);
cmdbuf.CopyTextureToTexture(
new TextureSlice(originalTexture),
new TextureSlice(textureCopy),
Filter.Linear
);
// Create a half-sized copy of this texture
textureCreateInfo.Width /= 2;
textureCreateInfo.Height /= 2;
textureSmallCopy = new Texture(GraphicsDevice, textureCreateInfo);
cmdbuf.CopyTextureToTexture(
new TextureSlice(originalTexture),
new TextureSlice(
textureSmallCopy,
new Rect(
(int) textureCreateInfo.Width,
(int) textureCreateInfo.Height
)
),
Filter.Linear
);
// Copy the texture to a buffer
Buffer compareBuffer = Buffer.Create<byte>(GraphicsDevice, 0, (uint) byteCount);
cmdbuf.CopyTextureToBuffer(new TextureSlice(originalTexture), compareBuffer);
var fence = GraphicsDevice.SubmitAndAcquireFence(cmdbuf);
GraphicsDevice.WaitForFences(fence);
GraphicsDevice.ReleaseFence(fence);
// Compare the original bytes to the copied bytes.
var copiedBytes = NativeMemory.Alloc((nuint) byteCount);
var copiedSpan = new System.Span<byte>(copiedBytes, byteCount);
compareBuffer.GetData(copiedSpan);
var originalSpan = new System.Span<byte>((void*) pixels, byteCount);
if (System.MemoryExtensions.SequenceEqual(originalSpan, copiedSpan))
{
Logger.LogError("SUCCESS! Original texture bytes and the bytes from CopyTextureToBuffer match!");
}
else
{
Logger.LogError("FAIL! Original texture bytes do not match bytes from CopyTextureToBuffer!");
}
RefreshCS.Refresh.Refresh_Image_Free(pixels);
}
protected override void Update(System.TimeSpan delta) { }
protected override void Draw(double alpha)
{
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(originalTexture, sampler));
cmdbuf.DrawIndexedPrimitives(0, 0, 2, 0, 0);
cmdbuf.BindFragmentSamplers(new TextureSamplerBinding(textureCopy, sampler));
cmdbuf.DrawIndexedPrimitives(4, 0, 2, 0, 0);
cmdbuf.BindFragmentSamplers(new TextureSamplerBinding(textureSmallCopy, sampler));
cmdbuf.DrawIndexedPrimitives(8, 0, 2, 0, 0);
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
CopyTextureGame game = new CopyTextureGame();
game.Run();
}
}
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,467 +0,0 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Math;
using MoonWorks.Math.Float;
using System.Threading.Tasks;
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 = false;
private float cubeTimer = 0f;
private Quaternion cubeRotation = Quaternion.Identity;
private Quaternion previousCubeRotation = Quaternion.Identity;
private bool depthOnlyEnabled = false;
private Vector3 camPos = new Vector3(0, 1.5f, 4f);
private TaskFactory taskFactory = new TaskFactory();
private bool takeScreenshot;
struct DepthUniforms
{
public float ZNear;
public float ZFar;
public DepthUniforms(float zNear, float zFar)
{
ZNear = zNear;
ZFar = zFar;
}
}
void LoadCubemap(CommandBuffer cmdbuf, string[] imagePaths)
{
for (uint i = 0; i < imagePaths.Length; i++)
{
var textureSlice = new TextureSlice(
skyboxTexture,
new Rect(0, 0, (int) skyboxTexture.Width, (int) skyboxTexture.Height),
0,
i,
0
);
Texture.SetDataFromImageFile(cmdbuf, textureSlice, imagePaths[i]);
}
}
public CubeGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{
ShaderModule cubeVertShaderModule = new ShaderModule(
GraphicsDevice,
TestUtils.GetShaderPath("PositionColorWithMatrix.vert")
);
ShaderModule cubeFragShaderModule = new ShaderModule(
GraphicsDevice,
TestUtils.GetShaderPath("SolidColor.frag")
);
ShaderModule skyboxVertShaderModule = new ShaderModule(
GraphicsDevice,
TestUtils.GetShaderPath("Skybox.vert")
);
ShaderModule skyboxFragShaderModule = new ShaderModule(
GraphicsDevice,
TestUtils.GetShaderPath("Skybox.frag")
);
ShaderModule blitVertShaderModule = new ShaderModule(
GraphicsDevice,
TestUtils.GetShaderPath("TexturedQuad.vert")
);
ShaderModule blitFragShaderModule = new ShaderModule(
GraphicsDevice,
TestUtils.GetShaderPath("TexturedDepthQuad.frag")
);
depthTexture = Texture.CreateTexture2D(
GraphicsDevice,
MainWindow.Width,
MainWindow.Height,
TextureFormat.D16,
TextureUsageFlags.DepthStencilTarget | TextureUsageFlags.Sampler
);
depthSampler = new Sampler(GraphicsDevice, new SamplerCreateInfo());
depthUniforms = new DepthUniforms(0.01f, 100f);
skyboxTexture = Texture.CreateTextureCube(
GraphicsDevice,
2048,
TextureFormat.R8G8B8A8,
TextureUsageFlags.Sampler
);
skyboxSampler = new Sampler(GraphicsDevice, new SamplerCreateInfo());
cubeVertexBuffer = Buffer.Create<PositionColorVertex>(
GraphicsDevice,
BufferUsageFlags.Vertex,
24
);
skyboxVertexBuffer = Buffer.Create<PositionVertex>(
GraphicsDevice,
BufferUsageFlags.Vertex,
24
);
indexBuffer = Buffer.Create<uint>(
GraphicsDevice,
BufferUsageFlags.Index,
36
); // Using uint here just to test IndexElementSize=32
blitVertexBuffer = Buffer.Create<PositionTextureVertex>(
GraphicsDevice,
BufferUsageFlags.Vertex,
6
);
Task loadingTask = Task.Run(() => UploadGPUAssets());
// 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<TransformVertexUniform>(cubeVertShaderModule, "main", 0),
VertexInputState = VertexInputState.CreateSingleBinding<PositionColorVertex>(),
PrimitiveType = PrimitiveType.TriangleList,
FragmentShaderInfo = GraphicsShaderInfo.Create(cubeFragShaderModule, "main", 0),
RasterizerState = RasterizerState.CW_CullBack,
MultisampleState = MultisampleState.None
};
cubePipeline = new GraphicsPipeline(GraphicsDevice, cubePipelineCreateInfo);
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<TransformVertexUniform>(skyboxVertShaderModule, "main", 0),
VertexInputState = VertexInputState.CreateSingleBinding<PositionVertex>(),
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(
MainWindow.SwapchainFormat,
blitVertShaderModule,
blitFragShaderModule
);
blitPipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureVertex>();
blitPipelineCreateInfo.FragmentShaderInfo = GraphicsShaderInfo.Create<DepthUniforms>(blitFragShaderModule, "main", 1);
blitPipeline = new GraphicsPipeline(GraphicsDevice, blitPipelineCreateInfo);
}
private void UploadGPUAssets()
{
Logger.LogInfo("Loading...");
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
cmdbuf.SetBufferData(
cubeVertexBuffer,
new PositionColorVertex[]
{
new PositionColorVertex(new Vector3(-1, -1, -1), new Color(1f, 0f, 0f)),
new PositionColorVertex(new Vector3(1, -1, -1), new Color(1f, 0f, 0f)),
new PositionColorVertex(new Vector3(1, 1, -1), new Color(1f, 0f, 0f)),
new PositionColorVertex(new Vector3(-1, 1, -1), new Color(1f, 0f, 0f)),
new PositionColorVertex(new Vector3(-1, -1, 1), new Color(0f, 1f, 0f)),
new PositionColorVertex(new Vector3(1, -1, 1), new Color(0f, 1f, 0f)),
new PositionColorVertex(new Vector3(1, 1, 1), new Color(0f, 1f, 0f)),
new PositionColorVertex(new Vector3(-1, 1, 1), new Color(0f, 1f, 0f)),
new PositionColorVertex(new Vector3(-1, -1, -1), new Color(0f, 0f, 1f)),
new PositionColorVertex(new Vector3(-1, 1, -1), new Color(0f, 0f, 1f)),
new PositionColorVertex(new Vector3(-1, 1, 1), new Color(0f, 0f, 1f)),
new PositionColorVertex(new Vector3(-1, -1, 1), new Color(0f, 0f, 1f)),
new PositionColorVertex(new Vector3(1, -1, -1), new Color(1f, 0.5f, 0f)),
new PositionColorVertex(new Vector3(1, 1, -1), new Color(1f, 0.5f, 0f)),
new PositionColorVertex(new Vector3(1, 1, 1), new Color(1f, 0.5f, 0f)),
new PositionColorVertex(new Vector3(1, -1, 1), new Color(1f, 0.5f, 0f)),
new PositionColorVertex(new Vector3(-1, -1, -1), new Color(1f, 0f, 0.5f)),
new PositionColorVertex(new Vector3(-1, -1, 1), new Color(1f, 0f, 0.5f)),
new PositionColorVertex(new Vector3(1, -1, 1), new Color(1f, 0f, 0.5f)),
new PositionColorVertex(new Vector3(1, -1, -1), new Color(1f, 0f, 0.5f)),
new PositionColorVertex(new Vector3(-1, 1, -1), new Color(0f, 0.5f, 0f)),
new PositionColorVertex(new Vector3(-1, 1, 1), new Color(0f, 0.5f, 0f)),
new PositionColorVertex(new Vector3(1, 1, 1), new Color(0f, 0.5f, 0f)),
new PositionColorVertex(new Vector3(1, 1, -1), new Color(0f, 0.5f, 0f))
}
);
cmdbuf.SetBufferData(
skyboxVertexBuffer,
new PositionVertex[]
{
new PositionVertex(new Vector3(-10, -10, -10)),
new PositionVertex(new Vector3(10, -10, -10)),
new PositionVertex(new Vector3(10, 10, -10)),
new PositionVertex(new Vector3(-10, 10, -10)),
new PositionVertex(new Vector3(-10, -10, 10)),
new PositionVertex(new Vector3(10, -10, 10)),
new PositionVertex(new Vector3(10, 10, 10)),
new PositionVertex(new Vector3(-10, 10, 10)),
new PositionVertex(new Vector3(-10, -10, -10)),
new PositionVertex(new Vector3(-10, 10, -10)),
new PositionVertex(new Vector3(-10, 10, 10)),
new PositionVertex(new Vector3(-10, -10, 10)),
new PositionVertex(new Vector3(10, -10, -10)),
new PositionVertex(new Vector3(10, 10, -10)),
new PositionVertex(new Vector3(10, 10, 10)),
new PositionVertex(new Vector3(10, -10, 10)),
new PositionVertex(new Vector3(-10, -10, -10)),
new PositionVertex(new Vector3(-10, -10, 10)),
new PositionVertex(new Vector3(10, -10, 10)),
new PositionVertex(new Vector3(10, -10, -10)),
new PositionVertex(new Vector3(-10, 10, -10)),
new PositionVertex(new Vector3(-10, 10, 10)),
new PositionVertex(new Vector3(10, 10, 10)),
new PositionVertex(new Vector3(10, 10, -10))
}
);
cmdbuf.SetBufferData(
indexBuffer,
new uint[]
{
0, 1, 2, 0, 2, 3,
6, 5, 4, 7, 6, 4,
8, 9, 10, 8, 10, 11,
14, 13, 12, 15, 14, 12,
16, 17, 18, 16, 18, 19,
22, 21, 20, 23, 22, 20
}
);
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"),
TestUtils.GetTexturePath("left.png"),
TestUtils.GetTexturePath("top.png"),
TestUtils.GetTexturePath("bottom.png"),
TestUtils.GetTexturePath("front.png"),
TestUtils.GetTexturePath("back.png")
});
GraphicsDevice.Submit(cmdbuf);
finishedLoading = true;
Logger.LogInfo("Finished loading!");
Logger.LogInfo("Press Left to toggle Depth-Only Mode");
Logger.LogInfo("Press Down to move the camera upwards");
Logger.LogInfo("Press Right to save a screenshot");
}
protected override void Update(System.TimeSpan delta)
{
cubeTimer += (float) delta.TotalSeconds;
previousCubeRotation = cubeRotation;
cubeRotation = Quaternion.CreateFromYawPitchRoll(
cubeTimer * 2f,
0,
cubeTimer * 2f
);
if (TestUtils.CheckButtonDown(Inputs, TestUtils.ButtonType.Bottom))
{
camPos.Y = System.MathF.Min(camPos.Y + 0.2f, 15f);
}
else
{
camPos.Y = System.MathF.Max(camPos.Y - 0.4f, 1.5f);
}
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Left))
{
depthOnlyEnabled = !depthOnlyEnabled;
Logger.LogInfo("Depth-Only Mode enabled: " + depthOnlyEnabled);
}
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Right))
{
takeScreenshot = true;
}
}
protected override void Draw(double alpha)
{
Matrix4x4 proj = Matrix4x4.CreatePerspectiveFieldOfView(
MathHelper.ToRadians(75f),
(float) MainWindow.Width / MainWindow.Height,
depthUniforms.ZNear,
depthUniforms.ZFar
);
Matrix4x4 view = Matrix4x4.CreateLookAt(
camPos,
Vector3.Zero,
Vector3.Up
);
TransformVertexUniform skyboxUniforms = new TransformVertexUniform(view * proj);
Matrix4x4 model = Matrix4x4.CreateFromQuaternion(
Quaternion.Slerp(
previousCubeRotation,
cubeRotation,
(float) alpha
)
);
TransformVertexUniform cubeUniforms = new TransformVertexUniform(model * view * proj);
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(MainWindow);
if (swapchainTexture != null)
{
if (!finishedLoading)
{
float sine = System.MathF.Abs(System.MathF.Sin(cubeTimer));
Color clearColor = new Color(sine, sine, sine);
// Just show a clear screen.
cmdbuf.BeginRenderPass(new ColorAttachmentInfo(swapchainTexture, clearColor));
cmdbuf.EndRenderPass();
}
else
{
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(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(depthOnlyEnabled ? skyboxPipelineDepthOnly : skyboxPipeline);
cmdbuf.BindVertexBuffers(skyboxVertexBuffer);
cmdbuf.BindIndexBuffer(indexBuffer, IndexElementSize.ThirtyTwo);
cmdbuf.BindFragmentSamplers(new TextureSamplerBinding(skyboxTexture, skyboxSampler));
vertexParamOffset = cmdbuf.PushVertexShaderUniforms(skyboxUniforms);
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();
}
}
}
GraphicsDevice.Submit(cmdbuf);
if (takeScreenshot)
{
if (swapchainTexture != null)
{
taskFactory.StartNew(TakeScreenshot, swapchainTexture);
}
takeScreenshot = false;
}
}
private System.Action<object?> TakeScreenshot = texture =>
{
if (texture != null)
{
((Texture) texture).SavePNG(System.IO.Path.Combine(System.AppContext.BaseDirectory, "screenshot.png"));
}
};
public static void Main(string[] args)
{
CubeGame game = new CubeGame();
game.Run();
}
}
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,142 +0,0 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Math.Float;
namespace MoonWorks.Test
{
class CullFaceGame : Game
{
private GraphicsPipeline CW_CullNonePipeline;
private GraphicsPipeline CW_CullFrontPipeline;
private GraphicsPipeline CW_CullBackPipeline;
private GraphicsPipeline CCW_CullNonePipeline;
private GraphicsPipeline CCW_CullFrontPipeline;
private GraphicsPipeline CCW_CullBackPipeline;
private Buffer cwVertexBuffer;
private Buffer ccwVertexBuffer;
private bool useClockwiseWinding;
public CullFaceGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{
Logger.LogInfo("Press Down to toggle the winding order of the triangles (default is counter-clockwise)");
// Load the shaders
ShaderModule vertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("PositionColor.vert"));
ShaderModule fragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("SolidColor.frag"));
// Create the graphics pipelines
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
MainWindow.SwapchainFormat,
vertShaderModule,
fragShaderModule
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionColorVertex>();
pipelineCreateInfo.RasterizerState = RasterizerState.CW_CullNone;
CW_CullNonePipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
pipelineCreateInfo.RasterizerState = RasterizerState.CW_CullFront;
CW_CullFrontPipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
pipelineCreateInfo.RasterizerState = RasterizerState.CW_CullBack;
CW_CullBackPipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
pipelineCreateInfo.RasterizerState = RasterizerState.CCW_CullNone;
CCW_CullNonePipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
pipelineCreateInfo.RasterizerState = RasterizerState.CCW_CullFront;
CCW_CullFrontPipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
pipelineCreateInfo.RasterizerState = RasterizerState.CCW_CullBack;
CCW_CullBackPipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create and populate the vertex buffers
cwVertexBuffer = Buffer.Create<PositionColorVertex>(GraphicsDevice, BufferUsageFlags.Vertex, 3);
ccwVertexBuffer = Buffer.Create<PositionColorVertex>(GraphicsDevice, BufferUsageFlags.Vertex, 3);
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
cmdbuf.SetBufferData(
cwVertexBuffer,
new PositionColorVertex[]
{
new PositionColorVertex(new Vector3(0, -1, 0), Color.Blue),
new PositionColorVertex(new Vector3(1, 1, 0), Color.Green),
new PositionColorVertex(new Vector3(-1, 1, 0), Color.Red),
}
);
cmdbuf.SetBufferData(
ccwVertexBuffer,
new PositionColorVertex[]
{
new PositionColorVertex(new Vector3(-1, 1, 0), Color.Red),
new PositionColorVertex(new Vector3(1, 1, 0), Color.Green),
new PositionColorVertex(new Vector3(0, -1, 0), Color.Blue),
}
);
GraphicsDevice.Submit(cmdbuf);
}
protected override void Update(System.TimeSpan delta)
{
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Bottom))
{
useClockwiseWinding = !useClockwiseWinding;
Logger.LogInfo("Using clockwise winding: " + useClockwiseWinding);
}
}
protected override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture? backbuffer = cmdbuf.AcquireSwapchainTexture(MainWindow);
if (backbuffer != null)
{
cmdbuf.BeginRenderPass(new ColorAttachmentInfo(backbuffer, Color.Black));
// Need to bind a pipeline before binding vertex buffers
cmdbuf.BindGraphicsPipeline(CW_CullNonePipeline);
if (useClockwiseWinding)
{
cmdbuf.BindVertexBuffers(cwVertexBuffer);
}
else
{
cmdbuf.BindVertexBuffers(ccwVertexBuffer);
}
cmdbuf.SetViewport(new Viewport(0, 0, 213, 240));
cmdbuf.DrawPrimitives(0, 1, 0, 0);
cmdbuf.SetViewport(new Viewport(213, 0, 213, 240));
cmdbuf.BindGraphicsPipeline(CW_CullFrontPipeline);
cmdbuf.DrawPrimitives(0, 1, 0, 0);
cmdbuf.SetViewport(new Viewport(426, 0, 213, 240));
cmdbuf.BindGraphicsPipeline(CW_CullBackPipeline);
cmdbuf.DrawPrimitives(0, 1, 0, 0);
cmdbuf.SetViewport(new Viewport(0, 240, 213, 240));
cmdbuf.BindGraphicsPipeline(CCW_CullNonePipeline);
cmdbuf.DrawPrimitives(0, 1, 0, 0);
cmdbuf.SetViewport(new Viewport(213, 240, 213, 240));
cmdbuf.BindGraphicsPipeline(CCW_CullFrontPipeline);
cmdbuf.DrawPrimitives(0, 1, 0, 0);
cmdbuf.SetViewport(new Viewport(426, 240, 213, 240));
cmdbuf.BindGraphicsPipeline(CCW_CullBackPipeline);
cmdbuf.DrawPrimitives(0, 1, 0, 0);
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
CullFaceGame game = new CullFaceGame();
game.Run();
}
}
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,295 +0,0 @@
using MoonWorks;
using MoonWorks.Math.Float;
using MoonWorks.Math;
using MoonWorks.Graphics;
namespace MoonWorks.Test
{
class DepthMSAAGame : Game
{
private GraphicsPipeline[] cubePipelines = new GraphicsPipeline[4];
private GraphicsPipeline blitPipeline;
private Texture[] renderTargets = new Texture[4];
private Texture[] depthRTs = new Texture[4];
private Sampler rtSampler;
private Buffer cubeVertexBuffer1;
private Buffer cubeVertexBuffer2;
private Buffer cubeIndexBuffer;
private Buffer quadVertexBuffer;
private Buffer quadIndexBuffer;
private float cubeTimer = 0f;
private Quaternion cubeRotation = Quaternion.Identity;
private Quaternion previousCubeRotation = Quaternion.Identity;
private Vector3 camPos = new Vector3(0, 1.5f, 4f);
private SampleCount currentSampleCount = SampleCount.Four;
public DepthMSAAGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{
Logger.LogInfo("Press Left and Right to cycle between sample counts");
Logger.LogInfo("Setting sample count to: " + currentSampleCount);
// Create the cube pipelines
ShaderModule cubeVertShaderModule = new ShaderModule(
GraphicsDevice,
TestUtils.GetShaderPath("PositionColorWithMatrix.vert")
);
ShaderModule cubeFragShaderModule = new ShaderModule(
GraphicsDevice,
TestUtils.GetShaderPath("SolidColor.frag")
);
GraphicsPipelineCreateInfo pipelineCreateInfo = new GraphicsPipelineCreateInfo
{
AttachmentInfo = new GraphicsPipelineAttachmentInfo(
TextureFormat.D32,
new ColorAttachmentDescription(
MainWindow.SwapchainFormat,
ColorAttachmentBlendState.Opaque
)
),
DepthStencilState = DepthStencilState.DepthReadWrite,
VertexShaderInfo = GraphicsShaderInfo.Create<TransformVertexUniform>(cubeVertShaderModule, "main", 0),
VertexInputState = VertexInputState.CreateSingleBinding<PositionColorVertex>(),
PrimitiveType = PrimitiveType.TriangleList,
FragmentShaderInfo = GraphicsShaderInfo.Create(cubeFragShaderModule, "main", 0),
RasterizerState = RasterizerState.CW_CullBack,
MultisampleState = MultisampleState.None
};
for (int i = 0; i < cubePipelines.Length; i += 1)
{
pipelineCreateInfo.MultisampleState.MultisampleCount = (SampleCount) i;
cubePipelines[i] = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
}
// Create the blit pipeline
ShaderModule blitVertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuad.vert"));
ShaderModule blitFragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuad.frag"));
pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
MainWindow.SwapchainFormat,
blitVertShaderModule,
blitFragShaderModule
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureVertex>();
pipelineCreateInfo.FragmentShaderInfo.SamplerBindingCount = 1;
blitPipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create the MSAA render textures and depth textures
for (int i = 0; i < renderTargets.Length; i += 1)
{
renderTargets[i] = Texture.CreateTexture2D(
GraphicsDevice,
MainWindow.Width,
MainWindow.Height,
TextureFormat.R8G8B8A8,
TextureUsageFlags.ColorTarget | TextureUsageFlags.Sampler,
1,
(SampleCount) i
);
depthRTs[i] = Texture.CreateTexture2D(
GraphicsDevice,
MainWindow.Width,
MainWindow.Height,
TextureFormat.D32,
TextureUsageFlags.DepthStencilTarget,
1,
(SampleCount) i
);
}
// Create the sampler
rtSampler = new Sampler(GraphicsDevice, SamplerCreateInfo.PointClamp);
// Create the buffers
quadVertexBuffer = Buffer.Create<PositionTextureVertex>(GraphicsDevice, BufferUsageFlags.Vertex, 4);
quadIndexBuffer = Buffer.Create<ushort>(GraphicsDevice, BufferUsageFlags.Index, 6);
cubeVertexBuffer1 = Buffer.Create<PositionColorVertex>(GraphicsDevice, BufferUsageFlags.Vertex, 24);
cubeVertexBuffer2 = Buffer.Create<PositionColorVertex>(GraphicsDevice, BufferUsageFlags.Vertex, 24);
cubeIndexBuffer = Buffer.Create<uint>(GraphicsDevice, BufferUsageFlags.Index, 36);
// Populate the GPU resources
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
cmdbuf.SetBufferData(
quadVertexBuffer,
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(
quadIndexBuffer,
new ushort[]
{
0, 1, 2,
0, 2, 3,
}
);
PositionColorVertex[] vertices = new PositionColorVertex[]
{
new PositionColorVertex(new Vector3(-1, -1, -1), new Color(1f, 0f, 0f)),
new PositionColorVertex(new Vector3(1, -1, -1), new Color(1f, 0f, 0f)),
new PositionColorVertex(new Vector3(1, 1, -1), new Color(1f, 0f, 0f)),
new PositionColorVertex(new Vector3(-1, 1, -1), new Color(1f, 0f, 0f)),
new PositionColorVertex(new Vector3(-1, -1, 1), new Color(0f, 1f, 0f)),
new PositionColorVertex(new Vector3(1, -1, 1), new Color(0f, 1f, 0f)),
new PositionColorVertex(new Vector3(1, 1, 1), new Color(0f, 1f, 0f)),
new PositionColorVertex(new Vector3(-1, 1, 1), new Color(0f, 1f, 0f)),
new PositionColorVertex(new Vector3(-1, -1, -1), new Color(0f, 0f, 1f)),
new PositionColorVertex(new Vector3(-1, 1, -1), new Color(0f, 0f, 1f)),
new PositionColorVertex(new Vector3(-1, 1, 1), new Color(0f, 0f, 1f)),
new PositionColorVertex(new Vector3(-1, -1, 1), new Color(0f, 0f, 1f)),
new PositionColorVertex(new Vector3(1, -1, -1), new Color(1f, 0.5f, 0f)),
new PositionColorVertex(new Vector3(1, 1, -1), new Color(1f, 0.5f, 0f)),
new PositionColorVertex(new Vector3(1, 1, 1), new Color(1f, 0.5f, 0f)),
new PositionColorVertex(new Vector3(1, -1, 1), new Color(1f, 0.5f, 0f)),
new PositionColorVertex(new Vector3(-1, -1, -1), new Color(1f, 0f, 0.5f)),
new PositionColorVertex(new Vector3(-1, -1, 1), new Color(1f, 0f, 0.5f)),
new PositionColorVertex(new Vector3(1, -1, 1), new Color(1f, 0f, 0.5f)),
new PositionColorVertex(new Vector3(1, -1, -1), new Color(1f, 0f, 0.5f)),
new PositionColorVertex(new Vector3(-1, 1, -1), new Color(0f, 0.5f, 0f)),
new PositionColorVertex(new Vector3(-1, 1, 1), new Color(0f, 0.5f, 0f)),
new PositionColorVertex(new Vector3(1, 1, 1), new Color(0f, 0.5f, 0f)),
new PositionColorVertex(new Vector3(1, 1, -1), new Color(0f, 0.5f, 0f))
};
cmdbuf.SetBufferData(
cubeVertexBuffer1,
vertices
);
// Scoot all the verts slightly for the second cube...
for (int i = 0; i < vertices.Length; i += 1)
{
vertices[i].Position.Z += 3;
}
cmdbuf.SetBufferData(
cubeVertexBuffer2,
vertices
);
cmdbuf.SetBufferData(
cubeIndexBuffer,
new uint[]
{
0, 1, 2, 0, 2, 3,
6, 5, 4, 7, 6, 4,
8, 9, 10, 8, 10, 11,
14, 13, 12, 15, 14, 12,
16, 17, 18, 16, 18, 19,
22, 21, 20, 23, 22, 20
}
);
GraphicsDevice.Submit(cmdbuf);
}
protected override void Update(System.TimeSpan delta)
{
SampleCount prevSampleCount = currentSampleCount;
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Left))
{
currentSampleCount -= 1;
if (currentSampleCount < 0)
{
currentSampleCount = SampleCount.Eight;
}
}
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Right))
{
currentSampleCount += 1;
if (currentSampleCount > SampleCount.Eight)
{
currentSampleCount = SampleCount.One;
}
}
if (prevSampleCount != currentSampleCount)
{
Logger.LogInfo("Setting sample count to: " + currentSampleCount);
}
// Rotate the cube
cubeTimer += (float) delta.TotalSeconds;
previousCubeRotation = cubeRotation;
cubeRotation = Quaternion.CreateFromYawPitchRoll(cubeTimer * 2f, 0, cubeTimer * 2f);
}
protected override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture? backbuffer = cmdbuf.AcquireSwapchainTexture(MainWindow);
if (backbuffer != null)
{
// Set up cube model-view-projection matrix
Matrix4x4 proj = Matrix4x4.CreatePerspectiveFieldOfView(
MathHelper.ToRadians(75f),
(float) MainWindow.Width / MainWindow.Height,
0.01f,
100f
);
Matrix4x4 view = Matrix4x4.CreateLookAt(camPos, Vector3.Zero, Vector3.Up);
Matrix4x4 model = Matrix4x4.CreateFromQuaternion(
Quaternion.Slerp(
previousCubeRotation,
cubeRotation,
(float) alpha
)
);
TransformVertexUniform cubeUniforms = new TransformVertexUniform(model * view * proj);
// Begin the MSAA RT pass
int index = (int) currentSampleCount;
cmdbuf.BeginRenderPass(
new DepthStencilAttachmentInfo(depthRTs[index], new DepthStencilValue(1, 0)),
new ColorAttachmentInfo(renderTargets[index], Color.Black)
);
cmdbuf.BindGraphicsPipeline(cubePipelines[index]);
// Draw the first cube
cmdbuf.BindVertexBuffers(cubeVertexBuffer1);
cmdbuf.BindIndexBuffer(cubeIndexBuffer, IndexElementSize.ThirtyTwo);
uint vertexParamOffset = cmdbuf.PushVertexShaderUniforms(cubeUniforms);
cmdbuf.DrawIndexedPrimitives(0, 0, 12, vertexParamOffset, 0);
// Draw the second cube
cmdbuf.BindVertexBuffers(cubeVertexBuffer2);
cmdbuf.BindIndexBuffer(cubeIndexBuffer, IndexElementSize.ThirtyTwo);
vertexParamOffset = cmdbuf.PushVertexShaderUniforms(cubeUniforms);
cmdbuf.DrawIndexedPrimitives(0, 0, 12, vertexParamOffset, 0);
cmdbuf.EndRenderPass();
// Blit the MSAA RT to the backbuffer
cmdbuf.BeginRenderPass(new ColorAttachmentInfo(backbuffer, LoadOp.DontCare));
cmdbuf.BindGraphicsPipeline(blitPipeline);
cmdbuf.BindFragmentSamplers(new TextureSamplerBinding(renderTargets[index], rtSampler));
cmdbuf.BindVertexBuffers(quadVertexBuffer);
cmdbuf.BindIndexBuffer(quadIndexBuffer, IndexElementSize.Sixteen);
cmdbuf.DrawIndexedPrimitives(0, 0, 2, 0, 0);
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
DepthMSAAGame game = new DepthMSAAGame();
game.Run();
}
}
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,81 +0,0 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Math.Float;
using System.Runtime.InteropServices;
namespace MoonWorks.Test
{
class DrawIndirectGame : Game
{
private GraphicsPipeline graphicsPipeline;
private Buffer vertexBuffer;
private Buffer drawBuffer;
public DrawIndirectGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{
// Load the shaders
ShaderModule vertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("PositionColor.vert"));
ShaderModule fragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("SolidColor.frag"));
// Create the graphics pipeline
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
MainWindow.SwapchainFormat,
vertShaderModule,
fragShaderModule
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionColorVertex>();
graphicsPipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create and populate the vertex buffer
vertexBuffer = Buffer.Create<PositionColorVertex>(GraphicsDevice, BufferUsageFlags.Vertex, 6);
drawBuffer = Buffer.Create<IndirectDrawCommand>(GraphicsDevice, BufferUsageFlags.Indirect, 2);
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
cmdbuf.SetBufferData(
vertexBuffer,
new PositionColorVertex[]
{
new PositionColorVertex(new Vector3(-0.5f, -1, 0), Color.Blue),
new PositionColorVertex(new Vector3(-1f, 1, 0), Color.Green),
new PositionColorVertex(new Vector3(0f, 1, 0), Color.Red),
new PositionColorVertex(new Vector3(.5f, -1, 0), Color.Blue),
new PositionColorVertex(new Vector3(1f, 1, 0), Color.Green),
new PositionColorVertex(new Vector3(0f, 1, 0), Color.Red),
}
);
cmdbuf.SetBufferData(
drawBuffer,
new IndirectDrawCommand[]
{
new IndirectDrawCommand(3, 1, 3, 0),
new IndirectDrawCommand(3, 1, 0, 0),
}
);
GraphicsDevice.Submit(cmdbuf);
}
protected override void Update(System.TimeSpan delta) { }
protected override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture? backbuffer = cmdbuf.AcquireSwapchainTexture(MainWindow);
if (backbuffer != null)
{
cmdbuf.BeginRenderPass(new ColorAttachmentInfo(backbuffer, Color.CornflowerBlue));
cmdbuf.BindGraphicsPipeline(graphicsPipeline);
cmdbuf.BindVertexBuffers(new BufferBinding(vertexBuffer, 0));
cmdbuf.DrawPrimitivesIndirect(drawBuffer, 0, 2, (uint) Marshal.SizeOf<IndirectDrawCommand>(), 0, 0);
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
DrawIndirectGame game = new DrawIndirectGame();
game.Run();
}
}
}

View File

@ -0,0 +1,196 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
using MoonWorks.Math.Float;
namespace MoonWorksGraphicsTests;
class BasicComputeExample : Example
{
private GraphicsPipeline DrawPipeline;
private Texture Texture;
private Sampler Sampler;
private Buffer VertexBuffer;
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Window.SetTitle("BasicCompute");
// Create the compute pipeline that writes texture data
ComputePipeline fillTextureComputePipeline = new ComputePipeline(
GraphicsDevice,
TestUtils.GetShaderPath("FillTexture.comp"),
"main",
new ComputePipelineCreateInfo
{
ShaderFormat = ShaderFormat.SPIRV,
ReadWriteStorageTextureCount = 1,
ThreadCountX = 8,
ThreadCountY = 8,
ThreadCountZ = 1
}
);
// Create the compute pipeline that calculates squares of numbers
ComputePipeline calculateSquaresComputePipeline = new ComputePipeline(
GraphicsDevice,
TestUtils.GetShaderPath("CalculateSquares.comp"),
"main",
new ComputePipelineCreateInfo
{
ShaderFormat = ShaderFormat.SPIRV,
ReadWriteStorageBufferCount = 1,
ThreadCountX = 8,
ThreadCountY = 1,
ThreadCountZ = 1
}
);
// Create the graphics pipeline
Shader vertShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("TexturedQuad.vert"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Vertex,
ShaderFormat = ShaderFormat.SPIRV
}
);
Shader fragShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("TexturedQuad.frag"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Fragment,
ShaderFormat = ShaderFormat.SPIRV,
SamplerCount = 1
}
);
GraphicsPipelineCreateInfo drawPipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
Window.SwapchainFormat,
vertShader,
fragShader
);
drawPipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureVertex>();
DrawPipeline = new GraphicsPipeline(
GraphicsDevice,
drawPipelineCreateInfo
);
// Create buffers and textures
uint[] squares = new uint[64];
Buffer squaresBuffer = Buffer.Create<uint>(
GraphicsDevice,
BufferUsageFlags.ComputeStorageWrite,
(uint) squares.Length
);
TransferBuffer transferBuffer = new TransferBuffer(
GraphicsDevice,
TransferUsage.Buffer,
TransferBufferMapFlags.Read,
squaresBuffer.Size
);
Texture = Texture.CreateTexture2D(
GraphicsDevice,
Window.Width,
Window.Height,
TextureFormat.R8G8B8A8,
TextureUsageFlags.ComputeStorageWrite | TextureUsageFlags.Sampler
);
Sampler = new Sampler(GraphicsDevice, new SamplerCreateInfo());
// Upload GPU resources and dispatch compute work
var resourceUploader = new ResourceUploader(GraphicsDevice);
VertexBuffer = resourceUploader.CreateBuffer(
[
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)),
],
BufferUsageFlags.Vertex
);
resourceUploader.Upload();
resourceUploader.Dispose();
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
// This should result in a bright yellow texture!
var computePass = cmdbuf.BeginComputePass(new StorageTextureReadWriteBinding
{
TextureSlice = Texture,
Cycle = false
});
computePass.BindComputePipeline(fillTextureComputePipeline);
computePass.Dispatch(Texture.Width / 8, Texture.Height / 8, 1);
cmdbuf.EndComputePass(computePass);
// This calculates the squares of the first N integers!
computePass = cmdbuf.BeginComputePass(new StorageBufferReadWriteBinding
{
Buffer = squaresBuffer,
Cycle = false
});
computePass.BindComputePipeline(calculateSquaresComputePipeline);
computePass.Dispatch((uint) squares.Length / 8, 1, 1);
cmdbuf.EndComputePass(computePass);
var copyPass = cmdbuf.BeginCopyPass();
copyPass.DownloadFromBuffer(squaresBuffer, transferBuffer, new BufferCopy(0, 0, squaresBuffer.Size));
cmdbuf.EndCopyPass(copyPass);
var fence = GraphicsDevice.SubmitAndAcquireFence(cmdbuf);
GraphicsDevice.WaitForFence(fence);
GraphicsDevice.ReleaseFence(fence);
// Print the squares!
transferBuffer.GetData<uint>(squares, 0);
Logger.LogInfo("Squares of the first " + squares.Length + " integers: " + string.Join(", ", squares));
}
public override void Update(System.TimeSpan delta) { }
public override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
var renderPass = cmdbuf.BeginRenderPass(new ColorAttachmentInfo(swapchainTexture, false, Color.CornflowerBlue));
renderPass.BindGraphicsPipeline(DrawPipeline);
renderPass.BindFragmentSampler(new TextureSamplerBinding(Texture, Sampler));
renderPass.BindVertexBuffer(VertexBuffer);
renderPass.DrawPrimitives(0, 2);
cmdbuf.EndRenderPass(renderPass);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
DrawPipeline.Dispose();
Texture.Dispose();
Sampler.Dispose();
VertexBuffer.Dispose();
}
}

View File

@ -0,0 +1,137 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
using MoonWorks.Math.Float;
namespace MoonWorksGraphicsTests
{
class BasicStencilExample : Example
{
private GraphicsPipeline MaskerPipeline;
private GraphicsPipeline MaskeePipeline;
private Buffer VertexBuffer;
private Texture DepthStencilTexture;
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Window.SetTitle("BasicStencil");
// Load the shaders
Shader vertShaderModule = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("PositionColor.vert"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Vertex,
ShaderFormat = ShaderFormat.SPIRV
}
);
Shader fragShaderModule = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("SolidColor.frag"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Fragment,
ShaderFormat = ShaderFormat.SPIRV
}
);
// Create the graphics pipelines
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
Window.SwapchainFormat,
vertShaderModule,
fragShaderModule
);
pipelineCreateInfo.AttachmentInfo.HasDepthStencilAttachment = true;
pipelineCreateInfo.AttachmentInfo.DepthStencilFormat = TextureFormat.D24_UNORM_S8_UINT;
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionColorVertex>();
pipelineCreateInfo.DepthStencilState = new DepthStencilState
{
StencilTestEnable = true,
FrontStencilState = new StencilOpState
{
CompareOp = CompareOp.Never,
FailOp = StencilOp.Replace,
},
Reference = 1,
WriteMask = 0xFF
};
MaskerPipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
pipelineCreateInfo.DepthStencilState = new DepthStencilState
{
StencilTestEnable = true,
FrontStencilState = new StencilOpState
{
CompareOp = CompareOp.Equal,
},
Reference = 0,
CompareMask = 0xFF,
WriteMask = 0
};
MaskeePipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create and populate the GPU resources
DepthStencilTexture = Texture.CreateTexture2D(
GraphicsDevice,
Window.Width,
Window.Height,
TextureFormat.D24_UNORM_S8_UINT,
TextureUsageFlags.DepthStencil
);
var resourceUploader = new ResourceUploader(GraphicsDevice);
VertexBuffer = resourceUploader.CreateBuffer(
[
new PositionColorVertex(new Vector3(-0.5f, -0.5f, 0), Color.Yellow),
new PositionColorVertex(new Vector3( 0.5f, -0.5f, 0), Color.Yellow),
new PositionColorVertex(new Vector3( 0, 0.5f, 0), Color.Yellow),
new PositionColorVertex(new Vector3(-1, -1, 0), Color.Red),
new PositionColorVertex(new Vector3( 1, -1, 0), Color.Lime),
new PositionColorVertex(new Vector3( 0, 1, 0), Color.Blue),
],
BufferUsageFlags.Vertex
);
resourceUploader.Upload();
resourceUploader.Dispose();
}
public override void Update(System.TimeSpan delta) { }
public override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
var renderPass = cmdbuf.BeginRenderPass(
new DepthStencilAttachmentInfo(DepthStencilTexture, true, new DepthStencilValue(0, 0), StoreOp.DontCare, StoreOp.DontCare),
new ColorAttachmentInfo(swapchainTexture, false, Color.Black)
);
renderPass.BindGraphicsPipeline(MaskerPipeline);
renderPass.BindVertexBuffer(VertexBuffer);
renderPass.DrawPrimitives(0, 1);
renderPass.BindGraphicsPipeline(MaskeePipeline);
renderPass.DrawPrimitives(3, 1);
cmdbuf.EndRenderPass(renderPass);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
MaskerPipeline.Dispose();
MaskeePipeline.Dispose();
VertexBuffer.Dispose();
DepthStencilTexture.Dispose();
}
}
}

View File

@ -0,0 +1,117 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
namespace MoonWorksGraphicsTests;
class BasicTriangleExample : Example
{
private GraphicsPipeline FillPipeline;
private GraphicsPipeline LinePipeline;
private Viewport SmallViewport = new Viewport(160, 120, 320, 240);
private Rect ScissorRect = new Rect(320, 240, 320, 240);
private bool UseWireframeMode;
private bool UseSmallViewport;
private bool UseScissorRect;
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Inputs = inputs;
Window.SetTitle("BasicTriangle");
Logger.LogInfo("Press Left to toggle wireframe mode\nPress Down to toggle small viewport\nPress Right to toggle scissor rect");
Shader vertShaderModule = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("RawTriangle.vert"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Vertex,
ShaderFormat = ShaderFormat.SPIRV
}
);
Shader fragShaderModule = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("SolidColor.frag"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Fragment,
ShaderFormat = ShaderFormat.SPIRV
}
);
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
Window.SwapchainFormat,
vertShaderModule,
fragShaderModule
);
FillPipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
pipelineCreateInfo.RasterizerState.FillMode = FillMode.Line;
LinePipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
}
public override void Update(System.TimeSpan delta)
{
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Left))
{
UseWireframeMode = !UseWireframeMode;
Logger.LogInfo("Using wireframe mode: " + UseWireframeMode);
}
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Bottom))
{
UseSmallViewport = !UseSmallViewport;
Logger.LogInfo("Using small viewport: " + UseSmallViewport);
}
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Right))
{
UseScissorRect = !UseScissorRect;
Logger.LogInfo("Using scissor rect: " + UseScissorRect);
}
}
public override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
var renderPass = cmdbuf.BeginRenderPass(
new ColorAttachmentInfo(swapchainTexture, false, Color.Black)
);
renderPass.BindGraphicsPipeline(UseWireframeMode ? LinePipeline : FillPipeline);
if (UseSmallViewport)
{
renderPass.SetViewport(SmallViewport);
}
if (UseScissorRect)
{
renderPass.SetScissor(ScissorRect);
}
renderPass.DrawPrimitives(0, 1);
cmdbuf.EndRenderPass(renderPass);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
FillPipeline.Dispose();
LinePipeline.Dispose();
}
}

View File

@ -0,0 +1,36 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
namespace MoonWorksGraphicsTests;
class ClearScreenExample : Example
{
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Window.SetTitle("ClearScreen");
}
public override void Update(System.TimeSpan delta) { }
public override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
var renderPass = cmdbuf.BeginRenderPass(
new ColorAttachmentInfo(swapchainTexture, false, Color.CornflowerBlue)
);
cmdbuf.EndRenderPass(renderPass);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
}
}

View File

@ -0,0 +1,75 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
namespace MoonWorksGraphicsTests
{
class ClearScreen_MultiWindowExample : Example
{
private Window SecondaryWindow;
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Window.SetTitle("ClearScreen");
Window.SetPosition(SDL2.SDL.SDL_WINDOWPOS_CENTERED, SDL2.SDL.SDL_WINDOWPOS_CENTERED);
var (windowX, windowY) = Window.Position;
Window.SetPosition(windowX - 360, windowY);
SecondaryWindow = new Window(
new WindowCreateInfo("Secondary Window", 640, 480, ScreenMode.Windowed, false, false),
SDL2.SDL.SDL_WindowFlags.SDL_WINDOW_VULKAN
);
(windowX, windowY) = SecondaryWindow.Position;
SecondaryWindow.SetPosition(windowX + 360, windowY);
GraphicsDevice.ClaimWindow(SecondaryWindow, SwapchainComposition.SDR, PresentMode.VSync);
}
public override void Update(System.TimeSpan delta) { }
public override void Draw(double alpha)
{
CommandBuffer cmdbuf;
Texture swapchainTexture;
if (Window.Claimed)
{
cmdbuf = GraphicsDevice.AcquireCommandBuffer();
swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
var renderPass = cmdbuf.BeginRenderPass(
new ColorAttachmentInfo(swapchainTexture, false, Color.CornflowerBlue)
);
cmdbuf.EndRenderPass(renderPass);
}
GraphicsDevice.Submit(cmdbuf);
}
if (SecondaryWindow.Claimed)
{
cmdbuf = GraphicsDevice.AcquireCommandBuffer();
swapchainTexture = cmdbuf.AcquireSwapchainTexture(SecondaryWindow);
if (swapchainTexture != null)
{
var renderPass = cmdbuf.BeginRenderPass(
new ColorAttachmentInfo(swapchainTexture, false, Color.Aquamarine)
);
cmdbuf.EndRenderPass(renderPass);
}
GraphicsDevice.Submit(cmdbuf);
}
}
public override void Destroy()
{
GraphicsDevice.UnclaimWindow(SecondaryWindow);
SecondaryWindow.Dispose();
Window.SetPosition(SDL2.SDL.SDL_WINDOWPOS_CENTERED, SDL2.SDL.SDL_WINDOWPOS_CENTERED);
}
}
}

View File

@ -0,0 +1,166 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
using MoonWorks.Math.Float;
namespace MoonWorksGraphicsTests;
class CompressedTexturesExample : Example
{
private GraphicsPipeline Pipeline;
private Buffer VertexBuffer;
private Buffer IndexBuffer;
private Sampler Sampler;
private Texture[] Textures;
private string[] TextureNames =
[
"BC1",
"BC2",
"BC3",
"BC7"
];
private int CurrentTextureIndex;
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Inputs = inputs;
Window.SetTitle("CompressedTextures");
Logger.LogInfo("Press Left and Right to cycle between textures");
Logger.LogInfo("Setting texture to: " + TextureNames[0]);
// Load the shaders
Shader vertShaderModule = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("TexturedQuad.vert"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Vertex,
ShaderFormat = ShaderFormat.SPIRV
}
);
Shader fragShaderModule = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("TexturedQuad.frag"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Fragment,
ShaderFormat = ShaderFormat.SPIRV,
SamplerCount = 1
}
);
// Create the graphics pipeline
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
Window.SwapchainFormat,
vertShaderModule,
fragShaderModule
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureVertex>();
Pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create sampler
Sampler = new Sampler(GraphicsDevice, SamplerCreateInfo.LinearWrap);
// Create texture array
Textures = new Texture[TextureNames.Length];
// Create and populate the GPU resources
var resourceUploader = new ResourceUploader(GraphicsDevice);
VertexBuffer = resourceUploader.CreateBuffer(
[
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))
],
BufferUsageFlags.Vertex
);
IndexBuffer = resourceUploader.CreateBuffer<ushort>(
[
0, 1, 2,
0, 2, 3,
],
BufferUsageFlags.Index
);
for (int i = 0; i < TextureNames.Length; i += 1)
{
Logger.LogInfo(TextureNames[i]);
Textures[i] = resourceUploader.CreateTextureFromDDS(TestUtils.GetTexturePath(TextureNames[i] + ".dds"));
}
resourceUploader.Upload();
resourceUploader.Dispose();
}
public override void Update(System.TimeSpan delta)
{
int prevSamplerIndex = CurrentTextureIndex;
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Left))
{
CurrentTextureIndex -= 1;
if (CurrentTextureIndex < 0)
{
CurrentTextureIndex = TextureNames.Length - 1;
}
}
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Right))
{
CurrentTextureIndex += 1;
if (CurrentTextureIndex >= TextureNames.Length)
{
CurrentTextureIndex = 0;
}
}
if (prevSamplerIndex != CurrentTextureIndex)
{
Logger.LogInfo("Setting texture to: " + TextureNames[CurrentTextureIndex]);
}
}
public override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
var renderPass = cmdbuf.BeginRenderPass(
new ColorAttachmentInfo(swapchainTexture, false, Color.Black)
);
renderPass.BindGraphicsPipeline(Pipeline);
renderPass.BindVertexBuffer(VertexBuffer);
renderPass.BindIndexBuffer(IndexBuffer, IndexElementSize.Sixteen);
renderPass.BindFragmentSampler(new TextureSamplerBinding(Textures[CurrentTextureIndex], Sampler));
renderPass.DrawIndexedPrimitives(0, 0, 2);
cmdbuf.EndRenderPass(renderPass);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
Pipeline.Dispose();
VertexBuffer.Dispose();
IndexBuffer.Dispose();
Sampler.Dispose();
for (int i = 0; i < TextureNames.Length; i += 1)
{
Textures[i].Dispose();
}
}
}

View File

@ -0,0 +1,244 @@
using System;
using System.Runtime.InteropServices;
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
using MoonWorks.Math.Float;
using Buffer = MoonWorks.Graphics.Buffer;
namespace MoonWorksGraphicsTests;
class ComputeSpriteBatchExample : Example
{
ComputePipeline ComputePipeline;
GraphicsPipeline RenderPipeline;
Sampler Sampler;
Texture SpriteTexture;
TransferBuffer SpriteComputeTransferBuffer;
Buffer SpriteComputeBuffer;
Buffer SpriteVertexBuffer;
Buffer SpriteIndexBuffer;
const int MAX_SPRITE_COUNT = 8192;
Random Random = new Random();
[StructLayout(LayoutKind.Explicit, Size = 48)]
struct ComputeSpriteData
{
[FieldOffset(0)]
public Vector3 Position;
[FieldOffset(12)]
public float Rotation;
[FieldOffset(16)]
public Vector2 Size;
[FieldOffset(32)]
public Vector4 Color;
}
public override unsafe void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Window.SetTitle("ComputeSpriteBatch");
Shader vertShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("TexturedQuadColorWithMatrix.vert"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Vertex,
ShaderFormat = ShaderFormat.SPIRV,
UniformBufferCount = 1
}
);
Shader fragShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("TexturedQuadColor.frag"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Fragment,
ShaderFormat = ShaderFormat.SPIRV,
SamplerCount = 1
}
);
GraphicsPipelineCreateInfo renderPipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
Window.SwapchainFormat,
vertShader,
fragShader
);
renderPipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureColorVertex>();
RenderPipeline = new GraphicsPipeline(GraphicsDevice, renderPipelineCreateInfo);
ComputePipeline = new ComputePipeline(
GraphicsDevice,
TestUtils.GetShaderPath("SpriteBatch.comp"),
"main",
new ComputePipelineCreateInfo
{
ShaderFormat = ShaderFormat.SPIRV,
ReadOnlyStorageBufferCount = 1,
ReadWriteStorageBufferCount = 1,
ThreadCountX = 64,
ThreadCountY = 1,
ThreadCountZ = 1
}
);
Sampler = new Sampler(GraphicsDevice, SamplerCreateInfo.PointClamp);
// Create and populate the sprite texture
var resourceUploader = new ResourceUploader(GraphicsDevice);
SpriteTexture = resourceUploader.CreateTexture2DFromCompressed(TestUtils.GetTexturePath("ravioli.png"));
resourceUploader.Upload();
resourceUploader.Dispose();
SpriteComputeTransferBuffer = TransferBuffer.Create<ComputeSpriteData>(
GraphicsDevice,
TransferUsage.Buffer,
TransferBufferMapFlags.Write,
MAX_SPRITE_COUNT
);
SpriteComputeBuffer = Buffer.Create<ComputeSpriteData>(
GraphicsDevice,
BufferUsageFlags.ComputeStorageRead,
MAX_SPRITE_COUNT
);
SpriteVertexBuffer = Buffer.Create<PositionTextureColorVertex>(
GraphicsDevice,
BufferUsageFlags.ComputeStorageWrite | BufferUsageFlags.Vertex,
MAX_SPRITE_COUNT * 4
);
SpriteIndexBuffer = Buffer.Create<uint>(
GraphicsDevice,
BufferUsageFlags.Index,
MAX_SPRITE_COUNT * 6
);
TransferBuffer spriteIndexTransferBuffer = TransferBuffer.Create<uint>(
GraphicsDevice,
TransferUsage.Buffer,
TransferBufferMapFlags.Write,
MAX_SPRITE_COUNT * 6
);
spriteIndexTransferBuffer.Map(false, out byte* mapPointer);
uint *indexPointer = (uint*) mapPointer;
for (uint i = 0, j = 0; i < MAX_SPRITE_COUNT * 6; i += 6, j += 4)
{
indexPointer[i] = j;
indexPointer[i + 1] = j + 1;
indexPointer[i + 2] = j + 2;
indexPointer[i + 3] = j + 3;
indexPointer[i + 4] = j + 2;
indexPointer[i + 5] = j + 1;
}
spriteIndexTransferBuffer.Unmap();
var cmdbuf = GraphicsDevice.AcquireCommandBuffer();
var copyPass = cmdbuf.BeginCopyPass();
copyPass.UploadToBuffer(spriteIndexTransferBuffer, SpriteIndexBuffer, false);
cmdbuf.EndCopyPass(copyPass);
GraphicsDevice.Submit(cmdbuf);
}
public override void Update(TimeSpan delta)
{
}
public override unsafe void Draw(double alpha)
{
Matrix4x4 cameraMatrix =
Matrix4x4.CreateOrthographicOffCenter(
0,
640,
480,
0,
0,
-1f
);
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
// Build sprite compute transfer
SpriteComputeTransferBuffer.Map(true, out byte* mapPointer);
ComputeSpriteData *dataPointer = (ComputeSpriteData*) mapPointer;
for (var i = 0; i < MAX_SPRITE_COUNT; i += 1)
{
dataPointer[i] = new ComputeSpriteData
{
Position = new Vector3(Random.Next(640), Random.Next(480), 0),
Rotation = (float) (Random.NextDouble() * System.Math.PI * 2),
Size = new Vector2(32, 32),
Color = new Vector4(1f, 1f, 1f, 1f)
};
}
SpriteComputeTransferBuffer.Unmap();
// Upload compute data to buffer
var copyPass = cmdbuf.BeginCopyPass();
copyPass.UploadToBuffer(SpriteComputeTransferBuffer, SpriteComputeBuffer, true);
cmdbuf.EndCopyPass(copyPass);
// Set up compute pass to build sprite vertex buffer
var computePass = cmdbuf.BeginComputePass(new StorageBufferReadWriteBinding
{
Buffer = SpriteVertexBuffer,
Cycle = true
});
computePass.BindComputePipeline(ComputePipeline);
computePass.BindStorageBuffer(SpriteComputeBuffer);
computePass.Dispatch(MAX_SPRITE_COUNT / 64, 1, 1);
cmdbuf.EndComputePass(computePass);
// Render sprites using vertex buffer
var renderPass = cmdbuf.BeginRenderPass(
new ColorAttachmentInfo(swapchainTexture, false, Color.Black)
);
renderPass.BindGraphicsPipeline(RenderPipeline);
renderPass.BindVertexBuffer(SpriteVertexBuffer);
renderPass.BindIndexBuffer(SpriteIndexBuffer, IndexElementSize.ThirtyTwo);
renderPass.BindFragmentSampler(new TextureSamplerBinding(SpriteTexture, Sampler));
renderPass.PushVertexUniformData(cameraMatrix);
renderPass.DrawIndexedPrimitives(0, 0, MAX_SPRITE_COUNT * 2);
cmdbuf.EndRenderPass(renderPass);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
ComputePipeline.Dispose();
RenderPipeline.Dispose();
Sampler.Dispose();
SpriteTexture.Dispose();
SpriteComputeTransferBuffer.Dispose();
SpriteComputeBuffer.Dispose();
SpriteVertexBuffer.Dispose();
SpriteIndexBuffer.Dispose();
}
}

View File

@ -0,0 +1,80 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
namespace MoonWorksGraphicsTests;
class ComputeUniformsExample : Example
{
private ComputePipeline GradientPipeline;
private Texture RenderTexture;
record struct GradientTextureComputeUniforms(float Time);
private GradientTextureComputeUniforms Uniforms;
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Window.SetTitle("ComputeUniforms");
Uniforms.Time = 0;
// Create the compute pipeline that writes texture data
GradientPipeline = new ComputePipeline(
GraphicsDevice,
TestUtils.GetShaderPath("GradientTexture.comp"),
"main",
new ComputePipelineCreateInfo
{
ShaderFormat = ShaderFormat.SPIRV,
ReadWriteStorageTextureCount = 1,
UniformBufferCount = 1,
ThreadCountX = 8,
ThreadCountY = 8,
ThreadCountZ = 1
}
);
RenderTexture = Texture.CreateTexture2D(
GraphicsDevice,
Window.Width,
Window.Height,
TextureFormat.R8G8B8A8,
TextureUsageFlags.ComputeStorageWrite | TextureUsageFlags.Sampler
);
}
public override void Update(System.TimeSpan delta)
{
Uniforms.Time += (float) delta.TotalSeconds;
}
public override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
var computePass = cmdbuf.BeginComputePass(new StorageTextureReadWriteBinding
{
TextureSlice = RenderTexture,
Cycle = true
});
computePass.BindComputePipeline(GradientPipeline);
computePass.PushUniformData(Uniforms);
computePass.Dispatch(RenderTexture.Width / 8, RenderTexture.Height / 8, 1);
cmdbuf.EndComputePass(computePass);
cmdbuf.Blit(RenderTexture, swapchainTexture, Filter.Linear, false);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
GradientPipeline.Dispose();
RenderTexture.Dispose();
}
}

View File

@ -0,0 +1,184 @@
using System.Runtime.InteropServices;
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
using MoonWorks.Math.Float;
namespace MoonWorksGraphicsTests
{
class CopyTextureExample : Example
{
private Texture OriginalTexture;
private Texture TextureCopy;
private Texture TextureSmall;
public override unsafe void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Window.SetTitle("CopyTexture");
// Create and populate the GPU resources
var resourceUploader = new ResourceUploader(GraphicsDevice);
OriginalTexture = resourceUploader.CreateTexture2DFromCompressed(
TestUtils.GetTexturePath("ravioli.png")
);
resourceUploader.Upload();
resourceUploader.Dispose();
// Load the texture bytes so we can compare them.
var pixels = ImageUtils.GetPixelDataFromFile(
TestUtils.GetTexturePath("ravioli.png"),
out var width,
out var height,
out var byteCount
);
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
var textureCreateInfo = new TextureCreateInfo
{
Width = OriginalTexture.Width,
Height = OriginalTexture.Height,
Depth = OriginalTexture.Depth,
IsCube = OriginalTexture.IsCube,
LayerCount = OriginalTexture.LayerCount,
LevelCount = OriginalTexture.LevelCount,
SampleCount = OriginalTexture.SampleCount,
Format = OriginalTexture.Format,
UsageFlags = OriginalTexture.UsageFlags
};
// Create a 1:1 copy of the texture
TextureCopy = new Texture(GraphicsDevice, textureCreateInfo);
// Create a download transfer buffer
TransferBuffer compareBuffer = new TransferBuffer(
GraphicsDevice,
TransferUsage.Texture,
TransferBufferMapFlags.Read,
byteCount
);
var copyPass = cmdbuf.BeginCopyPass();
copyPass.CopyTextureToTexture(
OriginalTexture,
TextureCopy,
false
);
cmdbuf.EndCopyPass(copyPass);
// Create a half-sized copy of this texture
textureCreateInfo.Width /= 2;
textureCreateInfo.Height /= 2;
textureCreateInfo.UsageFlags |= TextureUsageFlags.ColorTarget;
TextureSmall = new Texture(GraphicsDevice, textureCreateInfo);
// Render the half-size copy
cmdbuf.Blit(OriginalTexture, TextureSmall, Filter.Linear, false);
// Copy the texture to a transfer buffer
copyPass = cmdbuf.BeginCopyPass();
copyPass.DownloadFromTexture(
TextureCopy,
compareBuffer,
new BufferImageCopy(0, 0, 0)
);
cmdbuf.EndCopyPass(copyPass);
var fence = GraphicsDevice.SubmitAndAcquireFence(cmdbuf);
GraphicsDevice.WaitForFence(fence);
GraphicsDevice.ReleaseFence(fence);
// Compare the original bytes to the copied bytes.
var copiedBytes = NativeMemory.Alloc(byteCount);
var copiedSpan = new System.Span<byte>(copiedBytes, (int) byteCount);
compareBuffer.GetData(copiedSpan);
var originalSpan = new System.Span<byte>(pixels, (int)byteCount);
if (System.MemoryExtensions.SequenceEqual(originalSpan, copiedSpan))
{
Logger.LogInfo("SUCCESS! Original texture bytes and the downloaded bytes match!");
}
else
{
Logger.LogError("FAIL! Original texture bytes do not match downloaded bytes!");
}
RefreshCS.Refresh.Refresh_Image_Free(pixels);
NativeMemory.Free(copiedBytes);
}
public override void Update(System.TimeSpan delta) { }
public override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
var clearPass = cmdbuf.BeginRenderPass(
new ColorAttachmentInfo(swapchainTexture, false, Color.Black)
);
cmdbuf.EndRenderPass(clearPass);
cmdbuf.Blit(
OriginalTexture,
new TextureRegion
{
TextureSlice = swapchainTexture,
Width = swapchainTexture.Width / 2,
Height = swapchainTexture.Height / 2,
Depth = 1
},
Filter.Nearest,
false
);
cmdbuf.Blit(
TextureCopy,
new TextureRegion
{
TextureSlice = swapchainTexture,
X = swapchainTexture.Width / 2,
Y = 0,
Width = swapchainTexture.Width / 2,
Height = swapchainTexture.Height / 2,
Depth = 1
},
Filter.Nearest,
false
);
cmdbuf.Blit(
TextureSmall,
new TextureRegion
{
TextureSlice = swapchainTexture,
X = swapchainTexture.Width / 4,
Y = swapchainTexture.Height / 2,
Width = swapchainTexture.Width / 2,
Height = swapchainTexture.Height / 2,
Depth = 1
},
Filter.Nearest,
false
);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
OriginalTexture.Dispose();
TextureCopy.Dispose();
TextureSmall.Dispose();
}
}
}

597
Examples/CubeExample.cs Normal file
View File

@ -0,0 +1,597 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
using MoonWorks.Math;
using MoonWorks.Math.Float;
using System;
using System.IO;
using System.Threading.Tasks;
using Buffer = MoonWorks.Graphics.Buffer;
namespace MoonWorksGraphicsTests
{
struct DepthUniforms
{
public float ZNear;
public float ZFar;
public DepthUniforms(float zNear, float zFar)
{
ZNear = zNear;
ZFar = zFar;
}
}
class CubeExample : Example
{
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 TransferBuffer ScreenshotTransferBuffer;
private Texture ScreenshotTexture;
private Fence ScreenshotFence;
private Texture SkyboxTexture;
private Sampler SkyboxSampler;
private bool takeScreenshot;
private bool screenshotInProgress;
private bool swapchainDownloaded; // don't want to take screenshot if the swapchain was invalid
private bool finishedLoading;
private float cubeTimer;
private Quaternion cubeRotation;
private Quaternion previousCubeRotation;
private bool depthOnlyEnabled;
private Vector3 camPos;
// Upload cubemap layers one at a time to minimize transfer size
unsafe void LoadCubemap(string[] imagePaths)
{
var cubemapUploader = new ResourceUploader(GraphicsDevice);
for (uint i = 0; i < imagePaths.Length; i++)
{
var textureRegion = new TextureRegion
{
TextureSlice = new TextureSlice
{
Texture = SkyboxTexture,
MipLevel = 0,
Layer = i,
},
X = 0,
Y = 0,
Z = 0,
Width = SkyboxTexture.Width,
Height = SkyboxTexture.Height,
Depth = 1
};
cubemapUploader.SetTextureDataFromCompressed(
textureRegion,
imagePaths[i]
);
cubemapUploader.UploadAndWait();
}
cubemapUploader.Dispose();
}
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Inputs = inputs;
Window.SetTitle("Cube");
finishedLoading = false;
cubeTimer = 0;
cubeRotation = Quaternion.Identity;
previousCubeRotation = Quaternion.Identity;
depthOnlyEnabled = false;
camPos = new Vector3(0, 1.5f, 4);
Shader cubeVertShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("PositionColorWithMatrix.vert"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Vertex,
ShaderFormat = ShaderFormat.SPIRV,
UniformBufferCount = 1
}
);
Shader cubeFragShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("SolidColor.frag"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Fragment,
ShaderFormat = ShaderFormat.SPIRV
}
);
Shader skyboxVertShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("Skybox.vert"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Vertex,
ShaderFormat = ShaderFormat.SPIRV,
UniformBufferCount = 1
}
);
Shader skyboxFragShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("Skybox.frag"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Fragment,
ShaderFormat = ShaderFormat.SPIRV,
SamplerCount = 1
}
);
Shader blitVertShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("TexturedQuad.vert"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Vertex,
ShaderFormat = ShaderFormat.SPIRV
}
);
Shader blitFragShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("TexturedDepthQuad.frag"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Fragment,
ShaderFormat = ShaderFormat.SPIRV,
SamplerCount = 1,
UniformBufferCount = 1
}
);
DepthTexture = Texture.CreateTexture2D(
GraphicsDevice,
Window.Width,
Window.Height,
TextureFormat.D16_UNORM,
TextureUsageFlags.DepthStencil | TextureUsageFlags.Sampler
);
DepthTexture.Name = "Depth Texture";
DepthSampler = new Sampler(GraphicsDevice, new SamplerCreateInfo());
DepthUniforms = new DepthUniforms(0.01f, 100f);
SkyboxTexture = Texture.CreateTextureCube(
GraphicsDevice,
2048,
TextureFormat.R8G8B8A8,
TextureUsageFlags.Sampler
);
SkyboxTexture.Name = "Skybox";
SkyboxSampler = new Sampler(GraphicsDevice, new SamplerCreateInfo());
ScreenshotTransferBuffer = new TransferBuffer(
GraphicsDevice,
TransferUsage.Texture,
TransferBufferMapFlags.Read,
Window.Width * Window.Height * 4
);
ScreenshotTexture = Texture.CreateTexture2D(
GraphicsDevice,
Window.Width,
Window.Height,
Window.SwapchainFormat,
TextureUsageFlags.Sampler
);
ScreenshotTexture.Name = "Screenshot";
Task loadingTask = Task.Run(() => UploadGPUAssets());
// Create the cube pipelines
GraphicsPipelineCreateInfo cubePipelineCreateInfo = new GraphicsPipelineCreateInfo
{
AttachmentInfo = new GraphicsPipelineAttachmentInfo(
TextureFormat.D16_UNORM,
new ColorAttachmentDescription(
Window.SwapchainFormat,
ColorAttachmentBlendState.Opaque
)
),
DepthStencilState = DepthStencilState.DepthReadWrite,
VertexInputState = VertexInputState.CreateSingleBinding<PositionColorVertex>(),
PrimitiveType = PrimitiveType.TriangleList,
RasterizerState = RasterizerState.CW_CullBack,
MultisampleState = MultisampleState.None,
VertexShader = cubeVertShader,
FragmentShader = cubeFragShader
};
CubePipeline = new GraphicsPipeline(GraphicsDevice, cubePipelineCreateInfo);
cubePipelineCreateInfo.AttachmentInfo = new GraphicsPipelineAttachmentInfo(TextureFormat.D16_UNORM);
CubePipelineDepthOnly = new GraphicsPipeline(GraphicsDevice, cubePipelineCreateInfo);
// Create the skybox pipelines
GraphicsPipelineCreateInfo skyboxPipelineCreateInfo = new GraphicsPipelineCreateInfo
{
AttachmentInfo = new GraphicsPipelineAttachmentInfo(
TextureFormat.D16_UNORM,
new ColorAttachmentDescription(
Window.SwapchainFormat,
ColorAttachmentBlendState.Opaque
)
),
DepthStencilState = DepthStencilState.DepthReadWrite,
VertexInputState = VertexInputState.CreateSingleBinding<PositionVertex>(),
PrimitiveType = PrimitiveType.TriangleList,
RasterizerState = RasterizerState.CW_CullNone,
MultisampleState = MultisampleState.None,
VertexShader = skyboxVertShader,
FragmentShader = skyboxFragShader
};
SkyboxPipeline = new GraphicsPipeline(GraphicsDevice, skyboxPipelineCreateInfo);
skyboxPipelineCreateInfo.AttachmentInfo = new GraphicsPipelineAttachmentInfo(TextureFormat.D16_UNORM);
SkyboxPipelineDepthOnly = new GraphicsPipeline(GraphicsDevice, skyboxPipelineCreateInfo);
// Create the blit pipeline
GraphicsPipelineCreateInfo blitPipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
Window.SwapchainFormat,
blitVertShader,
blitFragShader
);
blitPipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureVertex>();
BlitPipeline = new GraphicsPipeline(GraphicsDevice, blitPipelineCreateInfo);
}
private void UploadGPUAssets()
{
Logger.LogInfo("Loading...");
var cubeVertexData = new Span<PositionColorVertex>([
new PositionColorVertex(new Vector3(-1, -1, -1), new Color(1f, 0f, 0f)),
new PositionColorVertex(new Vector3(1, -1, -1), new Color(1f, 0f, 0f)),
new PositionColorVertex(new Vector3(1, 1, -1), new Color(1f, 0f, 0f)),
new PositionColorVertex(new Vector3(-1, 1, -1), new Color(1f, 0f, 0f)),
new PositionColorVertex(new Vector3(-1, -1, 1), new Color(0f, 1f, 0f)),
new PositionColorVertex(new Vector3(1, -1, 1), new Color(0f, 1f, 0f)),
new PositionColorVertex(new Vector3(1, 1, 1), new Color(0f, 1f, 0f)),
new PositionColorVertex(new Vector3(-1, 1, 1), new Color(0f, 1f, 0f)),
new PositionColorVertex(new Vector3(-1, -1, -1), new Color(0f, 0f, 1f)),
new PositionColorVertex(new Vector3(-1, 1, -1), new Color(0f, 0f, 1f)),
new PositionColorVertex(new Vector3(-1, 1, 1), new Color(0f, 0f, 1f)),
new PositionColorVertex(new Vector3(-1, -1, 1), new Color(0f, 0f, 1f)),
new PositionColorVertex(new Vector3(1, -1, -1), new Color(1f, 0.5f, 0f)),
new PositionColorVertex(new Vector3(1, 1, -1), new Color(1f, 0.5f, 0f)),
new PositionColorVertex(new Vector3(1, 1, 1), new Color(1f, 0.5f, 0f)),
new PositionColorVertex(new Vector3(1, -1, 1), new Color(1f, 0.5f, 0f)),
new PositionColorVertex(new Vector3(-1, -1, -1), new Color(1f, 0f, 0.5f)),
new PositionColorVertex(new Vector3(-1, -1, 1), new Color(1f, 0f, 0.5f)),
new PositionColorVertex(new Vector3(1, -1, 1), new Color(1f, 0f, 0.5f)),
new PositionColorVertex(new Vector3(1, -1, -1), new Color(1f, 0f, 0.5f)),
new PositionColorVertex(new Vector3(-1, 1, -1), new Color(0f, 0.5f, 0f)),
new PositionColorVertex(new Vector3(-1, 1, 1), new Color(0f, 0.5f, 0f)),
new PositionColorVertex(new Vector3(1, 1, 1), new Color(0f, 0.5f, 0f)),
new PositionColorVertex(new Vector3(1, 1, -1), new Color(0f, 0.5f, 0f))
]);
var skyboxVertexData = new Span<PositionVertex>([
new PositionVertex(new Vector3(-10, -10, -10)),
new PositionVertex(new Vector3(10, -10, -10)),
new PositionVertex(new Vector3(10, 10, -10)),
new PositionVertex(new Vector3(-10, 10, -10)),
new PositionVertex(new Vector3(-10, -10, 10)),
new PositionVertex(new Vector3(10, -10, 10)),
new PositionVertex(new Vector3(10, 10, 10)),
new PositionVertex(new Vector3(-10, 10, 10)),
new PositionVertex(new Vector3(-10, -10, -10)),
new PositionVertex(new Vector3(-10, 10, -10)),
new PositionVertex(new Vector3(-10, 10, 10)),
new PositionVertex(new Vector3(-10, -10, 10)),
new PositionVertex(new Vector3(10, -10, -10)),
new PositionVertex(new Vector3(10, 10, -10)),
new PositionVertex(new Vector3(10, 10, 10)),
new PositionVertex(new Vector3(10, -10, 10)),
new PositionVertex(new Vector3(-10, -10, -10)),
new PositionVertex(new Vector3(-10, -10, 10)),
new PositionVertex(new Vector3(10, -10, 10)),
new PositionVertex(new Vector3(10, -10, -10)),
new PositionVertex(new Vector3(-10, 10, -10)),
new PositionVertex(new Vector3(-10, 10, 10)),
new PositionVertex(new Vector3(10, 10, 10)),
new PositionVertex(new Vector3(10, 10, -10))
]);
var indexData = new Span<uint>([
0, 1, 2, 0, 2, 3,
6, 5, 4, 7, 6, 4,
8, 9, 10, 8, 10, 11,
14, 13, 12, 15, 14, 12,
16, 17, 18, 16, 18, 19,
22, 21, 20, 23, 22, 20
]);
var blitVertexData = new Span<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)),
]);
var resourceUploader = new ResourceUploader(GraphicsDevice);
CubeVertexBuffer = resourceUploader.CreateBuffer(cubeVertexData, BufferUsageFlags.Vertex);
skyboxVertexBuffer = resourceUploader.CreateBuffer(skyboxVertexData, BufferUsageFlags.Vertex);
IndexBuffer = resourceUploader.CreateBuffer(indexData, BufferUsageFlags.Index);
BlitVertexBuffer = resourceUploader.CreateBuffer(blitVertexData, BufferUsageFlags.Vertex);
CubeVertexBuffer.Name = "Cube Vertices";
skyboxVertexBuffer.Name = "Skybox Vertices";
IndexBuffer.Name = "Cube Indices";
BlitVertexBuffer.Name = "Blit Vertices";
resourceUploader.Upload();
resourceUploader.Dispose();
LoadCubemap(new string[]
{
TestUtils.GetTexturePath("right.png"),
TestUtils.GetTexturePath("left.png"),
TestUtils.GetTexturePath("top.png"),
TestUtils.GetTexturePath("bottom.png"),
TestUtils.GetTexturePath("front.png"),
TestUtils.GetTexturePath("back.png")
});
finishedLoading = true;
Logger.LogInfo("Finished loading!");
Logger.LogInfo("Press Left to toggle Depth-Only Mode");
Logger.LogInfo("Press Down to move the camera upwards");
Logger.LogInfo("Press Right to save a screenshot");
}
public override void Update(System.TimeSpan delta)
{
cubeTimer += (float) delta.TotalSeconds;
previousCubeRotation = cubeRotation;
cubeRotation = Quaternion.CreateFromYawPitchRoll(
cubeTimer * 2f,
0,
cubeTimer * 2f
);
if (TestUtils.CheckButtonDown(Inputs, TestUtils.ButtonType.Bottom))
{
camPos.Y = System.MathF.Min(camPos.Y + 0.2f, 15f);
}
else
{
camPos.Y = System.MathF.Max(camPos.Y - 0.4f, 1.5f);
}
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Left))
{
depthOnlyEnabled = !depthOnlyEnabled;
Logger.LogInfo("Depth-Only Mode enabled: " + depthOnlyEnabled);
}
if (!screenshotInProgress && TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Right))
{
takeScreenshot = true;
}
}
public override void Draw(double alpha)
{
Matrix4x4 proj = Matrix4x4.CreatePerspectiveFieldOfView(
MathHelper.ToRadians(75f),
(float) Window.Width / Window.Height,
DepthUniforms.ZNear,
DepthUniforms.ZFar
);
Matrix4x4 view = Matrix4x4.CreateLookAt(
camPos,
Vector3.Zero,
Vector3.Up
);
TransformVertexUniform skyboxUniforms = new TransformVertexUniform(view * proj);
Matrix4x4 model = Matrix4x4.CreateFromQuaternion(
Quaternion.Slerp(
previousCubeRotation,
cubeRotation,
(float) alpha
)
);
TransformVertexUniform cubeUniforms = new TransformVertexUniform(model * view * proj);
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
if (!finishedLoading)
{
float sine = System.MathF.Abs(System.MathF.Sin(cubeTimer));
Color clearColor = new Color(sine, sine, sine);
// Just show a clear screen.
var renderPass = cmdbuf.BeginRenderPass(
new ColorAttachmentInfo(
swapchainTexture,
false,
clearColor
)
);
cmdbuf.EndRenderPass(renderPass);
}
else
{
RenderPass renderPass;
if (!depthOnlyEnabled)
{
renderPass = cmdbuf.BeginRenderPass(
new DepthStencilAttachmentInfo(DepthTexture, true, new DepthStencilValue(1f, 0)),
new ColorAttachmentInfo(swapchainTexture, false, LoadOp.DontCare)
);
}
else
{
renderPass = cmdbuf.BeginRenderPass(
new DepthStencilAttachmentInfo(DepthTexture, true, new DepthStencilValue(1f, 0), StoreOp.Store)
);
}
// Draw cube
renderPass.BindGraphicsPipeline(depthOnlyEnabled ? CubePipelineDepthOnly : CubePipeline);
renderPass.BindVertexBuffer(CubeVertexBuffer);
renderPass.BindIndexBuffer(IndexBuffer, IndexElementSize.ThirtyTwo);
renderPass.PushVertexUniformData(cubeUniforms);
renderPass.DrawIndexedPrimitives(0, 0, 12);
// Draw skybox
renderPass.BindGraphicsPipeline(depthOnlyEnabled ? SkyboxPipelineDepthOnly : SkyboxPipeline);
renderPass.BindVertexBuffer(skyboxVertexBuffer);
renderPass.BindIndexBuffer(IndexBuffer, IndexElementSize.ThirtyTwo);
renderPass.BindFragmentSampler(new TextureSamplerBinding(SkyboxTexture, SkyboxSampler));
renderPass.PushVertexUniformData(skyboxUniforms);
renderPass.DrawIndexedPrimitives(0, 0, 12);
cmdbuf.EndRenderPass(renderPass);
if (depthOnlyEnabled)
{
// Draw the depth buffer as a grayscale image
renderPass = cmdbuf.BeginRenderPass(
new ColorAttachmentInfo(
swapchainTexture,
false,
LoadOp.Load
)
);
renderPass.BindGraphicsPipeline(BlitPipeline);
renderPass.BindFragmentSampler(new TextureSamplerBinding(DepthTexture, DepthSampler));
renderPass.BindVertexBuffer(BlitVertexBuffer);
renderPass.PushFragmentUniformData(DepthUniforms);
renderPass.DrawPrimitives(0, 2);
cmdbuf.EndRenderPass(renderPass);
}
if (takeScreenshot)
{
var copyPass = cmdbuf.BeginCopyPass();
copyPass.DownloadFromTexture(swapchainTexture, ScreenshotTransferBuffer, new BufferImageCopy(0, 0, 0));
cmdbuf.EndCopyPass(copyPass);
swapchainDownloaded = true;
}
}
}
if (takeScreenshot && swapchainDownloaded)
{
ScreenshotFence = GraphicsDevice.SubmitAndAcquireFence(cmdbuf);
Task.Run(TakeScreenshot);
takeScreenshot = false;
swapchainDownloaded = false;
}
else
{
GraphicsDevice.Submit(cmdbuf);
}
}
private unsafe void TakeScreenshot()
{
screenshotInProgress = true;
GraphicsDevice.WaitForFence(ScreenshotFence);
ImageUtils.SavePNG(
Path.Combine(System.AppContext.BaseDirectory, "screenshot.png"),
ScreenshotTransferBuffer,
0,
(int) ScreenshotTexture.Width,
(int) ScreenshotTexture.Height,
ScreenshotTexture.Format == TextureFormat.B8G8R8A8
);
GraphicsDevice.ReleaseFence(ScreenshotFence);
ScreenshotFence = null;
screenshotInProgress = false;
}
public override void Destroy()
{
CubePipeline.Dispose();
CubePipelineDepthOnly.Dispose();
SkyboxPipeline.Dispose();
SkyboxPipelineDepthOnly.Dispose();
BlitPipeline.Dispose();
DepthTexture.Dispose();
DepthSampler.Dispose();
CubeVertexBuffer.Dispose();
skyboxVertexBuffer.Dispose();
BlitVertexBuffer.Dispose();
IndexBuffer.Dispose();
ScreenshotTransferBuffer.Dispose();
ScreenshotTexture.Dispose();
SkyboxTexture.Dispose();
SkyboxSampler.Dispose();
}
}
}

179
Examples/CullFaceExample.cs Normal file
View File

@ -0,0 +1,179 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
using MoonWorks.Math.Float;
namespace MoonWorksGraphicsTests;
class CullFaceExample : Example
{
private GraphicsPipeline CW_CullNonePipeline;
private GraphicsPipeline CW_CullFrontPipeline;
private GraphicsPipeline CW_CullBackPipeline;
private GraphicsPipeline CCW_CullNonePipeline;
private GraphicsPipeline CCW_CullFrontPipeline;
private GraphicsPipeline CCW_CullBackPipeline;
private Buffer CW_VertexBuffer;
private Buffer CCW_VertexBuffer;
private bool UseClockwiseWinding;
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Inputs = inputs;
Window.SetTitle("CullFace");
Logger.LogInfo("Press Down to toggle the winding order of the triangles (default is counter-clockwise)");
// Load the shaders
Shader vertShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("PositionColor.vert"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Vertex,
ShaderFormat = ShaderFormat.SPIRV
}
);
Shader fragShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("SolidColor.frag"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Fragment,
ShaderFormat = ShaderFormat.SPIRV
}
);
// Create the graphics pipelines
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
Window.SwapchainFormat,
vertShader,
fragShader
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionColorVertex>();
pipelineCreateInfo.RasterizerState = RasterizerState.CW_CullNone;
CW_CullNonePipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
pipelineCreateInfo.RasterizerState = RasterizerState.CW_CullFront;
CW_CullFrontPipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
pipelineCreateInfo.RasterizerState = RasterizerState.CW_CullBack;
CW_CullBackPipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
pipelineCreateInfo.RasterizerState = RasterizerState.CCW_CullNone;
CCW_CullNonePipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
pipelineCreateInfo.RasterizerState = RasterizerState.CCW_CullFront;
CCW_CullFrontPipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
pipelineCreateInfo.RasterizerState = RasterizerState.CCW_CullBack;
CCW_CullBackPipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create and populate the vertex buffers
var resourceUploader = new ResourceUploader(GraphicsDevice);
CW_VertexBuffer = resourceUploader.CreateBuffer(
[
new PositionColorVertex(new Vector3( 0, 1, 0), Color.Blue),
new PositionColorVertex(new Vector3( 1, -1, 0), Color.Green),
new PositionColorVertex(new Vector3(-1, -1, 0), Color.Red),
],
BufferUsageFlags.Vertex
);
CCW_VertexBuffer = resourceUploader.CreateBuffer(
[
new PositionColorVertex(new Vector3(-1, -1, 0), Color.Red),
new PositionColorVertex(new Vector3( 1, -1, 0), Color.Green),
new PositionColorVertex(new Vector3( 0, 1, 0), Color.Blue)
],
BufferUsageFlags.Vertex
);
resourceUploader.Upload();
resourceUploader.Dispose();
}
public override void Update(System.TimeSpan delta)
{
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Bottom))
{
UseClockwiseWinding = !UseClockwiseWinding;
Logger.LogInfo("Using clockwise winding: " + UseClockwiseWinding);
}
}
public override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
var renderPass = cmdbuf.BeginRenderPass(
new ColorAttachmentInfo(
swapchainTexture,
false,
Color.Black
)
);
// Need to bind a pipeline before binding vertex buffers
renderPass.BindGraphicsPipeline(CW_CullNonePipeline);
if (UseClockwiseWinding)
{
renderPass.BindVertexBuffer(CW_VertexBuffer);
}
else
{
renderPass.BindVertexBuffer(CCW_VertexBuffer);
}
renderPass.SetViewport(new Viewport(0, 0, 213, 240));
renderPass.DrawPrimitives(0, 1);
renderPass.SetViewport(new Viewport(213, 0, 213, 240));
renderPass.BindGraphicsPipeline(CW_CullFrontPipeline);
renderPass.DrawPrimitives(0, 1);
renderPass.SetViewport(new Viewport(426, 0, 213, 240));
renderPass.BindGraphicsPipeline(CW_CullBackPipeline);
renderPass.DrawPrimitives(0, 1);
renderPass.SetViewport(new Viewport(0, 240, 213, 240));
renderPass.BindGraphicsPipeline(CCW_CullNonePipeline);
renderPass.DrawPrimitives(0, 1);
renderPass.SetViewport(new Viewport(213, 240, 213, 240));
renderPass.BindGraphicsPipeline(CCW_CullFrontPipeline);
renderPass.DrawPrimitives(0, 1);
renderPass.SetViewport(new Viewport(426, 240, 213, 240));
renderPass.BindGraphicsPipeline(CCW_CullBackPipeline);
renderPass.DrawPrimitives(0, 1);
cmdbuf.EndRenderPass(renderPass);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
CW_CullNonePipeline.Dispose();
CW_CullFrontPipeline.Dispose();
CW_CullBackPipeline.Dispose();
CCW_CullNonePipeline.Dispose();
CCW_CullFrontPipeline.Dispose();
CCW_CullBackPipeline.Dispose();
CW_VertexBuffer.Dispose();
CCW_VertexBuffer.Dispose();
}
}

View File

@ -0,0 +1,282 @@
using MoonWorks;
using MoonWorks.Math.Float;
using MoonWorks.Math;
using MoonWorks.Graphics;
using MoonWorks.Input;
namespace MoonWorksGraphicsTests;
class DepthMSAAExample : Example
{
private GraphicsPipeline[] CubePipelines = new GraphicsPipeline[4];
private Texture[] RenderTargets = new Texture[4];
private Texture[] DepthRTs = new Texture[4];
private Buffer CubeVertexBuffer1;
private Buffer CubeVertexBuffer2;
private Buffer CubeIndexBuffer;
private float cubeTimer;
private Quaternion cubeRotation;
private Quaternion previousCubeRotation;
private Vector3 camPos;
private SampleCount currentSampleCount;
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Inputs = inputs;
Window.SetTitle("DepthMSAA");
cubeTimer = 0;
cubeRotation = Quaternion.Identity;
previousCubeRotation = Quaternion.Identity;
camPos = new Vector3(0, 1.5f, 4);
currentSampleCount = SampleCount.Four;
Logger.LogInfo("Press Left and Right to cycle between sample counts");
Logger.LogInfo("Setting sample count to: " + currentSampleCount);
// Create the cube pipelines
Shader cubeVertShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("PositionColorWithMatrix.vert"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Vertex,
ShaderFormat = ShaderFormat.SPIRV,
UniformBufferCount = 1
}
);
Shader cubeFragShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("SolidColor.frag"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Fragment,
ShaderFormat = ShaderFormat.SPIRV
}
);
GraphicsPipelineCreateInfo pipelineCreateInfo = new GraphicsPipelineCreateInfo
{
AttachmentInfo = new GraphicsPipelineAttachmentInfo(
TextureFormat.D32_SFLOAT,
new ColorAttachmentDescription(
Window.SwapchainFormat,
ColorAttachmentBlendState.Opaque
)
),
DepthStencilState = DepthStencilState.DepthReadWrite,
VertexInputState = VertexInputState.CreateSingleBinding<PositionColorVertex>(),
PrimitiveType = PrimitiveType.TriangleList,
RasterizerState = RasterizerState.CW_CullBack,
MultisampleState = MultisampleState.None,
VertexShader = cubeVertShader,
FragmentShader = cubeFragShader
};
for (int i = 0; i < CubePipelines.Length; i += 1)
{
pipelineCreateInfo.MultisampleState.MultisampleCount = (SampleCount) i;
CubePipelines[i] = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
}
// Create the MSAA render textures and depth textures
for (int i = 0; i < RenderTargets.Length; i += 1)
{
RenderTargets[i] = Texture.CreateTexture2D(
GraphicsDevice,
Window.Width,
Window.Height,
Window.SwapchainFormat,
TextureUsageFlags.ColorTarget | TextureUsageFlags.Sampler,
1,
(SampleCount) i
);
DepthRTs[i] = Texture.CreateTexture2D(
GraphicsDevice,
Window.Width,
Window.Height,
TextureFormat.D32_SFLOAT,
TextureUsageFlags.DepthStencil,
1,
(SampleCount) i
);
}
// Create the buffers
var resourceUploader = new ResourceUploader(GraphicsDevice);
var cubeVertexData = new System.Span<PositionColorVertex>(
[
new PositionColorVertex(new Vector3(-1, -1, -1), new Color(1f, 0f, 0f)),
new PositionColorVertex(new Vector3(1, -1, -1), new Color(1f, 0f, 0f)),
new PositionColorVertex(new Vector3(1, 1, -1), new Color(1f, 0f, 0f)),
new PositionColorVertex(new Vector3(-1, 1, -1), new Color(1f, 0f, 0f)),
new PositionColorVertex(new Vector3(-1, -1, 1), new Color(0f, 1f, 0f)),
new PositionColorVertex(new Vector3(1, -1, 1), new Color(0f, 1f, 0f)),
new PositionColorVertex(new Vector3(1, 1, 1), new Color(0f, 1f, 0f)),
new PositionColorVertex(new Vector3(-1, 1, 1), new Color(0f, 1f, 0f)),
new PositionColorVertex(new Vector3(-1, -1, -1), new Color(0f, 0f, 1f)),
new PositionColorVertex(new Vector3(-1, 1, -1), new Color(0f, 0f, 1f)),
new PositionColorVertex(new Vector3(-1, 1, 1), new Color(0f, 0f, 1f)),
new PositionColorVertex(new Vector3(-1, -1, 1), new Color(0f, 0f, 1f)),
new PositionColorVertex(new Vector3(1, -1, -1), new Color(1f, 0.5f, 0f)),
new PositionColorVertex(new Vector3(1, 1, -1), new Color(1f, 0.5f, 0f)),
new PositionColorVertex(new Vector3(1, 1, 1), new Color(1f, 0.5f, 0f)),
new PositionColorVertex(new Vector3(1, -1, 1), new Color(1f, 0.5f, 0f)),
new PositionColorVertex(new Vector3(-1, -1, -1), new Color(1f, 0f, 0.5f)),
new PositionColorVertex(new Vector3(-1, -1, 1), new Color(1f, 0f, 0.5f)),
new PositionColorVertex(new Vector3(1, -1, 1), new Color(1f, 0f, 0.5f)),
new PositionColorVertex(new Vector3(1, -1, -1), new Color(1f, 0f, 0.5f)),
new PositionColorVertex(new Vector3(-1, 1, -1), new Color(0f, 0.5f, 0f)),
new PositionColorVertex(new Vector3(-1, 1, 1), new Color(0f, 0.5f, 0f)),
new PositionColorVertex(new Vector3(1, 1, 1), new Color(0f, 0.5f, 0f)),
new PositionColorVertex(new Vector3(1, 1, -1), new Color(0f, 0.5f, 0f))
]);
CubeVertexBuffer1 = resourceUploader.CreateBuffer(
cubeVertexData,
BufferUsageFlags.Vertex
);
// Scoot all the verts slightly for the second cube...
for (int i = 0; i < cubeVertexData.Length; i += 1)
{
cubeVertexData[i].Position.Z += 3;
}
CubeVertexBuffer2 = resourceUploader.CreateBuffer(
cubeVertexData,
BufferUsageFlags.Vertex
);
CubeIndexBuffer = resourceUploader.CreateBuffer<uint>(
[
0, 1, 2, 0, 2, 3,
6, 5, 4, 7, 6, 4,
8, 9, 10, 8, 10, 11,
14, 13, 12, 15, 14, 12,
16, 17, 18, 16, 18, 19,
22, 21, 20, 23, 22, 20
],
BufferUsageFlags.Index
);
resourceUploader.Upload();
resourceUploader.Dispose();
}
public override void Update(System.TimeSpan delta)
{
SampleCount prevSampleCount = currentSampleCount;
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Left))
{
currentSampleCount -= 1;
if (currentSampleCount < 0)
{
currentSampleCount = SampleCount.Eight;
}
}
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Right))
{
currentSampleCount += 1;
if (currentSampleCount > SampleCount.Eight)
{
currentSampleCount = SampleCount.One;
}
}
if (prevSampleCount != currentSampleCount)
{
Logger.LogInfo("Setting sample count to: " + currentSampleCount);
}
// Rotate the cube
cubeTimer += (float) delta.TotalSeconds;
previousCubeRotation = cubeRotation;
cubeRotation = Quaternion.CreateFromYawPitchRoll(cubeTimer * 2f, 0, cubeTimer * 2f);
}
public override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
// Set up cube model-view-projection matrix
Matrix4x4 proj = Matrix4x4.CreatePerspectiveFieldOfView(
MathHelper.ToRadians(75f),
(float) Window.Width / Window.Height,
0.01f,
100f
);
Matrix4x4 view = Matrix4x4.CreateLookAt(camPos, Vector3.Zero, Vector3.Up);
Matrix4x4 model = Matrix4x4.CreateFromQuaternion(
Quaternion.Slerp(
previousCubeRotation,
cubeRotation,
(float) alpha
)
);
TransformVertexUniform cubeUniforms = new TransformVertexUniform(model * view * proj);
// Begin the MSAA RT pass
int index = (int) currentSampleCount;
var renderPass = cmdbuf.BeginRenderPass(
new DepthStencilAttachmentInfo(DepthRTs[index], true, new DepthStencilValue(1, 0)),
new ColorAttachmentInfo(RenderTargets[index], true, Color.Black)
);
renderPass.BindGraphicsPipeline(CubePipelines[index]);
// Draw the first cube
renderPass.BindVertexBuffer(CubeVertexBuffer1);
renderPass.BindIndexBuffer(CubeIndexBuffer, IndexElementSize.ThirtyTwo);
renderPass.PushVertexUniformData(cubeUniforms);
renderPass.DrawIndexedPrimitives(0, 0, 12);
// Draw the second cube
renderPass.BindVertexBuffer(CubeVertexBuffer2);
renderPass.BindIndexBuffer(CubeIndexBuffer, IndexElementSize.ThirtyTwo);
renderPass.PushVertexUniformData(cubeUniforms);
renderPass.DrawIndexedPrimitives(0, 0, 12);
cmdbuf.EndRenderPass(renderPass);
// Blit the MSAA RT to the backbuffer
cmdbuf.Blit(
RenderTargets[index],
swapchainTexture,
Filter.Nearest,
false
);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
for (var i = 0; i < 4; i += 1)
{
CubePipelines[i].Dispose();
RenderTargets[i].Dispose();
DepthRTs[i].Dispose();
}
CubeVertexBuffer1.Dispose();
CubeVertexBuffer2.Dispose();
CubeIndexBuffer.Dispose();
}
}

View File

@ -0,0 +1,111 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
using MoonWorks.Math.Float;
using System.Runtime.InteropServices;
namespace MoonWorksGraphicsTests;
class DrawIndirectExample : Example
{
private GraphicsPipeline GraphicsPipeline;
private Buffer VertexBuffer;
private Buffer DrawBuffer;
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Window.SetTitle("DrawIndirect");
// Load the shaders
Shader vertShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("PositionColor.vert"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Vertex,
ShaderFormat = ShaderFormat.SPIRV
}
);
Shader fragShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("SolidColor.frag"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Fragment,
ShaderFormat = ShaderFormat.SPIRV
}
);
// Create the graphics pipeline
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
Window.SwapchainFormat,
vertShader,
fragShader
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionColorVertex>();
GraphicsPipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create and populate the vertex buffer
var resourceUploader = new ResourceUploader(GraphicsDevice);
VertexBuffer = resourceUploader.CreateBuffer(
[
new PositionColorVertex(new Vector3(-0.5f, 1, 0), Color.Blue),
new PositionColorVertex(new Vector3( -1f, -1, 0), Color.Green),
new PositionColorVertex(new Vector3( 0f, -1, 0), Color.Red),
new PositionColorVertex(new Vector3(0.5f, 1, 0), Color.Blue),
new PositionColorVertex(new Vector3( 1f, -1, 0), Color.Green),
new PositionColorVertex(new Vector3( 0f, -1, 0), Color.Red),
],
BufferUsageFlags.Vertex
);
DrawBuffer = resourceUploader.CreateBuffer(
[
new IndirectDrawCommand(3, 1, 3, 0),
new IndirectDrawCommand(3, 1, 0, 0),
],
BufferUsageFlags.Indirect
);
resourceUploader.Upload();
resourceUploader.Dispose();
}
public override void Update(System.TimeSpan delta) { }
public override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
var renderPass = cmdbuf.BeginRenderPass(
new ColorAttachmentInfo(
swapchainTexture,
false,
Color.Black
)
);
renderPass.BindGraphicsPipeline(GraphicsPipeline);
renderPass.BindVertexBuffer(VertexBuffer);
renderPass.DrawPrimitivesIndirect(DrawBuffer, 0, 2, (uint) Marshal.SizeOf<IndirectDrawCommand>());
cmdbuf.EndRenderPass(renderPass);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
GraphicsPipeline.Dispose();
VertexBuffer.Dispose();
DrawBuffer.Dispose();
}
}

18
Examples/Example.cs Normal file
View File

@ -0,0 +1,18 @@
using System;
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
namespace MoonWorksGraphicsTests;
public abstract class Example
{
protected Window Window;
public GraphicsDevice GraphicsDevice;
public Inputs Inputs;
public abstract void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs);
public abstract void Update(TimeSpan delta);
public abstract void Draw(double alpha);
public abstract void Destroy();
}

View File

@ -0,0 +1,143 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
using MoonWorks.Math.Float;
using System.Runtime.InteropServices;
namespace MoonWorksGraphicsTests;
class GetBufferDataExample : Example
{
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Window.SetTitle("GetBufferData");
var vertices = new System.Span<PositionVertex>(
[
new PositionVertex(new Vector3(0, 0, 0)),
new PositionVertex(new Vector3(0, 0, 1)),
new PositionVertex(new Vector3(0, 1, 0)),
new PositionVertex(new Vector3(0, 1, 1)),
new PositionVertex(new Vector3(1, 0, 0)),
new PositionVertex(new Vector3(1, 0, 1)),
new PositionVertex(new Vector3(1, 1, 0)),
new PositionVertex(new Vector3(1, 1, 1)),
]);
var otherVerts = new System.Span<PositionVertex>(
[
new PositionVertex(new Vector3(1, 2, 3)),
new PositionVertex(new Vector3(4, 5, 6)),
new PositionVertex(new Vector3(7, 8, 9))
]);
int vertexSize = Marshal.SizeOf<PositionVertex>();
var resourceUploader = new ResourceUploader(GraphicsDevice);
var vertexBuffer = resourceUploader.CreateBuffer(vertices, BufferUsageFlags.Vertex);
resourceUploader.Upload();
resourceUploader.Dispose();
var transferBuffer = new TransferBuffer(
GraphicsDevice,
TransferUsage.Buffer,
TransferBufferMapFlags.Read | TransferBufferMapFlags.Write,
vertexBuffer.Size
);
// Read back and print out the vertex values
var cmdbuf = GraphicsDevice.AcquireCommandBuffer();
var copyPass = cmdbuf.BeginCopyPass();
copyPass.DownloadFromBuffer(
vertexBuffer,
transferBuffer,
new BufferCopy(0, 0, vertexBuffer.Size)
);
cmdbuf.EndCopyPass(copyPass);
GraphicsDevice.Submit(cmdbuf);
PositionVertex[] readbackVertices = new PositionVertex[vertices.Length];
transferBuffer.GetData<PositionVertex>(readbackVertices);
for (int i = 0; i < readbackVertices.Length; i += 1)
{
Logger.LogInfo(readbackVertices[i].ToString());
}
// Change the first three vertices and upload
transferBuffer.SetData(otherVerts, false);
cmdbuf = GraphicsDevice.AcquireCommandBuffer();
copyPass = cmdbuf.BeginCopyPass();
copyPass.UploadToBuffer(transferBuffer, vertexBuffer, false);
copyPass.DownloadFromBuffer(vertexBuffer, transferBuffer, new BufferCopy(0, 0, vertexBuffer.Size));
cmdbuf.EndCopyPass(copyPass);
var fence = GraphicsDevice.SubmitAndAcquireFence(cmdbuf);
GraphicsDevice.WaitForFence(fence);
GraphicsDevice.ReleaseFence(fence);
// Read the updated buffer
transferBuffer.GetData<PositionVertex>(readbackVertices);
Logger.LogInfo("=== Change first three vertices ===");
for (int i = 0; i < readbackVertices.Length; i += 1)
{
Logger.LogInfo(readbackVertices[i].ToString());
}
// Change the last two vertices and upload
cmdbuf = GraphicsDevice.AcquireCommandBuffer();
var lastTwoSpan = otherVerts.Slice(1, 2);
transferBuffer.SetData(lastTwoSpan, false);
copyPass = cmdbuf.BeginCopyPass();
copyPass.UploadToBuffer<PositionVertex>(
transferBuffer,
vertexBuffer,
0,
(uint)(vertices.Length - 2),
2,
false
);
copyPass.DownloadFromBuffer(vertexBuffer, transferBuffer, new BufferCopy(0, 0, vertexBuffer.Size));
cmdbuf.EndCopyPass(copyPass);
fence = GraphicsDevice.SubmitAndAcquireFence(cmdbuf);
GraphicsDevice.WaitForFence(fence);
GraphicsDevice.ReleaseFence(fence);
// Read the updated buffer
transferBuffer.GetData<PositionVertex>(readbackVertices);
Logger.LogInfo("=== Change last two vertices ===");
for (int i = 0; i < readbackVertices.Length; i += 1)
{
Logger.LogInfo(readbackVertices[i].ToString());
}
vertexBuffer.Dispose();
transferBuffer.Dispose();
}
public override void Update(System.TimeSpan delta) { }
public override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
var renderPass = cmdbuf.BeginRenderPass(
new ColorAttachmentInfo(
swapchainTexture,
false,
Color.Black
)
);
cmdbuf.EndRenderPass(renderPass);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
}
}

View File

@ -0,0 +1,137 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
using MoonWorks.Math.Float;
namespace MoonWorksGraphicsTests;
class InstancingAndOffsetsExample : Example
{
private GraphicsPipeline Pipeline;
private Buffer VertexBuffer;
private Buffer IndexBuffer;
private bool useVertexOffset;
private bool useIndexOffset;
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Inputs = inputs;
Window.SetTitle("InstancingAndOffsets");
Logger.LogInfo("Press Left to toggle vertex offset\nPress Right to toggle index offset");
// Load the shaders
Shader vertShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("PositionColorInstanced.vert"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Vertex,
ShaderFormat = ShaderFormat.SPIRV
}
);
Shader fragShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("SolidColor.frag"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Fragment,
ShaderFormat = ShaderFormat.SPIRV
}
);
// Create the graphics pipeline
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
Window.SwapchainFormat,
vertShader,
fragShader
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionColorVertex>();
Pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create and populate the vertex and index buffers
var resourceUploader = new ResourceUploader(GraphicsDevice);
VertexBuffer = resourceUploader.CreateBuffer(
[
new PositionColorVertex(new Vector3(-1, -1, 0), Color.Red),
new PositionColorVertex(new Vector3( 1, -1, 0), Color.Lime),
new PositionColorVertex(new Vector3( 0, 1, 0), Color.Blue),
new PositionColorVertex(new Vector3(-1, -1, 0), Color.Orange),
new PositionColorVertex(new Vector3( 1, -1, 0), Color.Green),
new PositionColorVertex(new Vector3( 0, 1, 0), Color.Aqua),
new PositionColorVertex(new Vector3(-1, -1, 0), Color.White),
new PositionColorVertex(new Vector3( 1, -1, 0), Color.White),
new PositionColorVertex(new Vector3( 0, 1, 0), Color.White),
],
BufferUsageFlags.Vertex
);
IndexBuffer = resourceUploader.CreateBuffer<ushort>(
[
0, 1, 2,
3, 4, 5,
],
BufferUsageFlags.Index
);
resourceUploader.Upload();
resourceUploader.Dispose();
}
public override void Update(System.TimeSpan delta)
{
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Left))
{
useVertexOffset = !useVertexOffset;
Logger.LogInfo("Using vertex offset: " + useVertexOffset);
}
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Right))
{
useIndexOffset = !useIndexOffset;
Logger.LogInfo("Using index offset: " + useIndexOffset);
}
}
public override void Draw(double alpha)
{
uint vertexOffset = useVertexOffset ? 3u : 0;
uint indexOffset = useIndexOffset ? 3u : 0;
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
var renderPass = cmdbuf.BeginRenderPass(
new ColorAttachmentInfo(
swapchainTexture,
false,
Color.Black
)
);
renderPass.BindGraphicsPipeline(Pipeline);
renderPass.BindVertexBuffer(VertexBuffer);
renderPass.BindIndexBuffer(IndexBuffer, IndexElementSize.Sixteen);
renderPass.DrawIndexedPrimitives(vertexOffset, indexOffset, 1, 16);
cmdbuf.EndRenderPass(renderPass);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
Pipeline.Dispose();
VertexBuffer.Dispose();
IndexBuffer.Dispose();
}
}

284
Examples/MSAACubeExample.cs Normal file
View File

@ -0,0 +1,284 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Math.Float;
using MoonWorks.Math;
using MoonWorks.Input;
namespace MoonWorksGraphicsTests;
class MSAACubeExample : Example
{
private GraphicsPipeline[] MsaaPipelines = new GraphicsPipeline[4];
private GraphicsPipeline CubemapPipeline;
private Texture[] RenderTargets = new Texture[4];
private Buffer VertexBuffer;
private Buffer IndexBuffer;
private Sampler Sampler;
private Vector3 camPos;
private SampleCount currentSampleCount;
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Inputs = inputs;
Window.SetTitle("MSAACube");
Logger.LogInfo("Press Down to view the other side of the cubemap");
Logger.LogInfo("Press Left and Right to cycle between sample counts");
Logger.LogInfo("Setting sample count to: " + currentSampleCount);
camPos = new Vector3(0, 0, 4);
currentSampleCount = SampleCount.Four;
// Create the MSAA pipelines
Shader triangleVertShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("RawTriangle.vert"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Vertex,
ShaderFormat = ShaderFormat.SPIRV
}
);
Shader triangleFragShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("SolidColor.frag"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Fragment,
ShaderFormat = ShaderFormat.SPIRV
}
);
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
TextureFormat.R8G8B8A8,
triangleVertShader,
triangleFragShader
);
for (int i = 0; i < MsaaPipelines.Length; i += 1)
{
pipelineCreateInfo.MultisampleState.MultisampleCount = (SampleCount)i;
MsaaPipelines[i] = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
}
// Create the cubemap pipeline
Shader cubemapVertShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("Skybox.vert"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Vertex,
ShaderFormat = ShaderFormat.SPIRV,
UniformBufferCount = 1
}
);
Shader cubemapFragShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("Skybox.frag"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Fragment,
ShaderFormat = ShaderFormat.SPIRV,
SamplerCount = 1
}
);
pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
Window.SwapchainFormat,
cubemapVertShader,
cubemapFragShader
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionVertex>();
CubemapPipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create the MSAA render targets
for (int i = 0; i < RenderTargets.Length; i++)
{
TextureCreateInfo cubeCreateInfo = new TextureCreateInfo
{
Width = 16,
Height = 16,
Format = TextureFormat.R8G8B8A8,
Depth = 1,
LevelCount = 1,
SampleCount = (SampleCount)i,
UsageFlags = TextureUsageFlags.ColorTarget | TextureUsageFlags.Sampler,
IsCube = true,
LayerCount = 6
};
RenderTargets[i] = new Texture(GraphicsDevice, cubeCreateInfo);
}
// Create samplers
Sampler = new Sampler(GraphicsDevice, SamplerCreateInfo.PointClamp);
// Create and populate the GPU resources
var resourceUploader = new ResourceUploader(GraphicsDevice);
VertexBuffer = resourceUploader.CreateBuffer(
[
new PositionVertex(new Vector3(-10, -10, -10)),
new PositionVertex(new Vector3(10, -10, -10)),
new PositionVertex(new Vector3(10, 10, -10)),
new PositionVertex(new Vector3(-10, 10, -10)),
new PositionVertex(new Vector3(-10, -10, 10)),
new PositionVertex(new Vector3(10, -10, 10)),
new PositionVertex(new Vector3(10, 10, 10)),
new PositionVertex(new Vector3(-10, 10, 10)),
new PositionVertex(new Vector3(-10, -10, -10)),
new PositionVertex(new Vector3(-10, 10, -10)),
new PositionVertex(new Vector3(-10, 10, 10)),
new PositionVertex(new Vector3(-10, -10, 10)),
new PositionVertex(new Vector3(10, -10, -10)),
new PositionVertex(new Vector3(10, 10, -10)),
new PositionVertex(new Vector3(10, 10, 10)),
new PositionVertex(new Vector3(10, -10, 10)),
new PositionVertex(new Vector3(-10, -10, -10)),
new PositionVertex(new Vector3(-10, -10, 10)),
new PositionVertex(new Vector3(10, -10, 10)),
new PositionVertex(new Vector3(10, -10, -10)),
new PositionVertex(new Vector3(-10, 10, -10)),
new PositionVertex(new Vector3(-10, 10, 10)),
new PositionVertex(new Vector3(10, 10, 10)),
new PositionVertex(new Vector3(10, 10, -10))
],
BufferUsageFlags.Vertex
);
IndexBuffer = resourceUploader.CreateBuffer<ushort>(
[
0, 1, 2, 0, 2, 3,
6, 5, 4, 7, 6, 4,
8, 9, 10, 8, 10, 11,
14, 13, 12, 15, 14, 12,
16, 17, 18, 16, 18, 19,
22, 21, 20, 23, 22, 20
],
BufferUsageFlags.Index
);
resourceUploader.Upload();
resourceUploader.Dispose();
}
public override void Update(System.TimeSpan delta)
{
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Bottom))
{
camPos.Z *= -1;
}
SampleCount prevSampleCount = currentSampleCount;
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Left))
{
currentSampleCount -= 1;
if (currentSampleCount < 0)
{
currentSampleCount = SampleCount.Eight;
}
}
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Right))
{
currentSampleCount += 1;
if (currentSampleCount > SampleCount.Eight)
{
currentSampleCount = SampleCount.One;
}
}
if (prevSampleCount != currentSampleCount)
{
Logger.LogInfo("Setting sample count to: " + currentSampleCount);
}
}
public override void Draw(double alpha)
{
Matrix4x4 proj = Matrix4x4.CreatePerspectiveFieldOfView(
MathHelper.ToRadians(75f),
(float)Window.Width / Window.Height,
0.01f,
100f
);
Matrix4x4 view = Matrix4x4.CreateLookAt(
camPos,
Vector3.Zero,
Vector3.Up
);
TransformVertexUniform vertUniforms = new TransformVertexUniform(view * proj);
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
// Get a reference to the RT for the given sample count
int rtIndex = (int) currentSampleCount;
Texture rt = RenderTargets[rtIndex];
ColorAttachmentInfo rtAttachmentInfo = new ColorAttachmentInfo(
rt,
true,
Color.Black
);
RenderPass renderPass;
// Render a triangle to each slice of the cubemap
for (uint i = 0; i < 6; i += 1)
{
rtAttachmentInfo.TextureSlice.Layer = i;
renderPass = cmdbuf.BeginRenderPass(rtAttachmentInfo);
renderPass.BindGraphicsPipeline(MsaaPipelines[rtIndex]);
renderPass.DrawPrimitives(0, 1);
cmdbuf.EndRenderPass(renderPass);
}
renderPass = cmdbuf.BeginRenderPass(
new ColorAttachmentInfo(
swapchainTexture,
false,
Color.Black
)
);
renderPass.BindGraphicsPipeline(CubemapPipeline);
renderPass.BindVertexBuffer(VertexBuffer);
renderPass.BindIndexBuffer(IndexBuffer, IndexElementSize.Sixteen);
renderPass.BindFragmentSampler(new TextureSamplerBinding(rt, Sampler));
renderPass.PushVertexUniformData(vertUniforms);
renderPass.DrawIndexedPrimitives(0, 0, 12);
cmdbuf.EndRenderPass(renderPass);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
for (var i = 0; i < 4; i += 1)
{
MsaaPipelines[i].Dispose();
RenderTargets[i].Dispose();
}
CubemapPipeline.Dispose();
VertexBuffer.Dispose();
IndexBuffer.Dispose();
Sampler.Dispose();
}
}

156
Examples/MSAAExample.cs Normal file
View File

@ -0,0 +1,156 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
namespace MoonWorksGraphicsTests;
class MSAAExample : Example
{
private GraphicsPipeline[] MsaaPipelines = new GraphicsPipeline[4];
private Texture[] RenderTargets = new Texture[4];
private Sampler RTSampler;
private SampleCount currentSampleCount;
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Inputs = inputs;
Window.SetTitle("MSAA");
currentSampleCount = SampleCount.Four;
Logger.LogInfo("Press Left and Right to cycle between sample counts");
Logger.LogInfo("Setting sample count to: " + currentSampleCount);
// Create the MSAA pipelines
Shader triangleVertShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("RawTriangle.vert"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Vertex,
ShaderFormat = ShaderFormat.SPIRV
}
);
Shader triangleFragShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("SolidColor.frag"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Fragment,
ShaderFormat = ShaderFormat.SPIRV
}
);
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
TextureFormat.R8G8B8A8,
triangleVertShader,
triangleFragShader
);
for (int i = 0; i < MsaaPipelines.Length; i += 1)
{
pipelineCreateInfo.MultisampleState.MultisampleCount = (SampleCount) i;
MsaaPipelines[i] = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
}
// Create the blit pipeline
/*
ShaderModule blitVertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuad.vert"));
ShaderModule blitFragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuad.frag"));
pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
MainWindow.SwapchainFormat,
blitVertShaderModule,
blitFragShaderModule
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureVertex>();
pipelineCreateInfo.FragmentShaderInfo.SamplerBindingCount = 1;
blitPipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
*/
// Create the MSAA render textures
for (int i = 0; i < RenderTargets.Length; i += 1)
{
RenderTargets[i] = Texture.CreateTexture2D(
GraphicsDevice,
Window.Width,
Window.Height,
TextureFormat.R8G8B8A8,
TextureUsageFlags.ColorTarget | TextureUsageFlags.Sampler,
1,
(SampleCount) i
);
}
// Create the sampler
RTSampler = new Sampler(GraphicsDevice, SamplerCreateInfo.PointClamp);
}
public override void Update(System.TimeSpan delta)
{
SampleCount prevSampleCount = currentSampleCount;
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Left))
{
currentSampleCount -= 1;
if (currentSampleCount < 0)
{
currentSampleCount = SampleCount.Eight;
}
}
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Right))
{
currentSampleCount += 1;
if (currentSampleCount > SampleCount.Eight)
{
currentSampleCount = SampleCount.One;
}
}
if (prevSampleCount != currentSampleCount)
{
Logger.LogInfo("Setting sample count to: " + currentSampleCount);
}
}
public override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
Texture rt = RenderTargets[(int) currentSampleCount];
var renderPass = cmdbuf.BeginRenderPass(
new ColorAttachmentInfo(
rt,
true,
Color.Black
)
);
renderPass.BindGraphicsPipeline(MsaaPipelines[(int) currentSampleCount]);
renderPass.DrawPrimitives(0, 1);
cmdbuf.EndRenderPass(renderPass);
cmdbuf.Blit(rt, swapchainTexture, Filter.Nearest, false);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
for (var i = 0; i < 4; i += 1)
{
MsaaPipelines[i].Dispose();
RenderTargets[i].Dispose();
}
RTSampler.Dispose();
}
}

View File

@ -0,0 +1,94 @@
using System;
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
namespace MoonWorksGraphicsTests;
class RenderTexture2DArrayExample : Example
{
private Texture RenderTarget;
private float t;
private Color[] colors =
[
Color.Red,
Color.Green,
Color.Blue,
];
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Window.SetTitle("RenderTexture2DArray");
RenderTarget = Texture.CreateTexture2DArray(
GraphicsDevice,
16,
16,
(uint) colors.Length,
TextureFormat.R8G8B8A8,
TextureUsageFlags.ColorTarget | TextureUsageFlags.Sampler
);
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
// Clear each depth slice of the RT to a different color
for (uint i = 0; i < colors.Length; i += 1)
{
ColorAttachmentInfo attachmentInfo = new ColorAttachmentInfo
{
TextureSlice = new TextureSlice
{
Texture = RenderTarget,
Layer = i,
MipLevel = 0
},
ClearColor = colors[i],
LoadOp = LoadOp.Clear,
StoreOp = StoreOp.Store
};
var renderPass = cmdbuf.BeginRenderPass(attachmentInfo);
cmdbuf.EndRenderPass(renderPass);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Update(System.TimeSpan delta) { }
public override void Draw(double alpha)
{
t += 0.01f;
t %= 3;
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
cmdbuf.Blit(
new TextureRegion
{
TextureSlice = new TextureSlice
{
Texture = RenderTarget,
Layer = (uint) MathF.Floor(t)
},
Depth = 1
},
swapchainTexture,
Filter.Nearest,
false
);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
RenderTarget.Dispose();
}
}

View File

@ -0,0 +1,118 @@
using System;
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
namespace MoonWorksGraphicsTests;
class RenderTexture2DExample : Example
{
private Texture[] textures = new Texture[4];
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Window.SetTitle("RenderTexture2D");
for (int i = 0; i < textures.Length; i += 1)
{
textures[i] = Texture.CreateTexture2D(
GraphicsDevice,
Window.Width / 4,
Window.Height / 4,
TextureFormat.R8G8B8A8,
TextureUsageFlags.ColorTarget | TextureUsageFlags.Sampler
);
}
}
public override void Update(System.TimeSpan delta) { }
public override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
var renderPass = cmdbuf.BeginRenderPass(new ColorAttachmentInfo(textures[0], false, Color.Red));
cmdbuf.EndRenderPass(renderPass);
renderPass = cmdbuf.BeginRenderPass(new ColorAttachmentInfo(textures[1], false, Color.Blue));
cmdbuf.EndRenderPass(renderPass);
renderPass = cmdbuf.BeginRenderPass(new ColorAttachmentInfo(textures[2], false, Color.Green));
cmdbuf.EndRenderPass(renderPass);
renderPass = cmdbuf.BeginRenderPass(new ColorAttachmentInfo(textures[3], false, Color.Yellow));
cmdbuf.EndRenderPass(renderPass);
cmdbuf.Blit(
textures[0],
new TextureRegion
{
TextureSlice = swapchainTexture,
Width = swapchainTexture.Width / 2,
Height = swapchainTexture.Height / 2,
Depth = 1
},
Filter.Nearest,
false
);
cmdbuf.Blit(
textures[1],
new TextureRegion
{
TextureSlice = swapchainTexture,
X = swapchainTexture.Width / 2,
Width = swapchainTexture.Width / 2,
Height = swapchainTexture.Height / 2,
Depth = 1
},
Filter.Nearest,
false
);
cmdbuf.Blit(
textures[2],
new TextureRegion
{
TextureSlice = swapchainTexture,
Y = swapchainTexture.Height / 2,
Width = swapchainTexture.Width / 2,
Height = swapchainTexture.Height / 2,
Depth = 1
},
Filter.Nearest,
false
);
cmdbuf.Blit(
textures[3],
new TextureRegion
{
TextureSlice = swapchainTexture,
X = swapchainTexture.Width / 2,
Y = swapchainTexture.Height / 2,
Width = swapchainTexture.Width / 2,
Height = swapchainTexture.Height / 2,
Depth = 1
},
Filter.Nearest,
false
);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
for (var i = 0; i < 4; i += 1)
{
textures[i].Dispose();
}
}
}

View File

@ -0,0 +1,210 @@
using MoonWorks.Graphics;
using MoonWorks.Math.Float;
using MoonWorks.Math;
using MoonWorks;
using MoonWorks.Input;
namespace MoonWorksGraphicsTests;
class RenderTextureCubeExample : Example
{
private GraphicsPipeline pipeline;
private Buffer vertexBuffer;
private Buffer indexBuffer;
private Texture cubemap;
private Sampler sampler;
private Vector3 camPos = new Vector3(0, 0, 4f);
private Color[] colors = new Color[]
{
Color.Red,
Color.Green,
Color.Blue,
Color.Orange,
Color.Yellow,
Color.Purple,
};
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Inputs = inputs;
Window.SetTitle("RenderTextureCube");
Logger.LogInfo("Press Down to view the other side of the cubemap");
// Load the shaders
Shader vertShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("Skybox.vert"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Vertex,
ShaderFormat = ShaderFormat.SPIRV,
UniformBufferCount = 1
}
);
Shader fragShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("Skybox.frag"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Fragment,
ShaderFormat = ShaderFormat.SPIRV,
SamplerCount = 1
}
);
// Create the graphics pipeline
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
Window.SwapchainFormat,
vertShader,
fragShader
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionVertex>();
pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create samplers
sampler = new Sampler(GraphicsDevice, SamplerCreateInfo.PointClamp);
// Create and populate the GPU resources
var resourceUploader = new ResourceUploader(GraphicsDevice);
vertexBuffer = resourceUploader.CreateBuffer(
[
new PositionVertex(new Vector3(-10, -10, -10)),
new PositionVertex(new Vector3(10, -10, -10)),
new PositionVertex(new Vector3(10, 10, -10)),
new PositionVertex(new Vector3(-10, 10, -10)),
new PositionVertex(new Vector3(-10, -10, 10)),
new PositionVertex(new Vector3(10, -10, 10)),
new PositionVertex(new Vector3(10, 10, 10)),
new PositionVertex(new Vector3(-10, 10, 10)),
new PositionVertex(new Vector3(-10, -10, -10)),
new PositionVertex(new Vector3(-10, 10, -10)),
new PositionVertex(new Vector3(-10, 10, 10)),
new PositionVertex(new Vector3(-10, -10, 10)),
new PositionVertex(new Vector3(10, -10, -10)),
new PositionVertex(new Vector3(10, 10, -10)),
new PositionVertex(new Vector3(10, 10, 10)),
new PositionVertex(new Vector3(10, -10, 10)),
new PositionVertex(new Vector3(-10, -10, -10)),
new PositionVertex(new Vector3(-10, -10, 10)),
new PositionVertex(new Vector3(10, -10, 10)),
new PositionVertex(new Vector3(10, -10, -10)),
new PositionVertex(new Vector3(-10, 10, -10)),
new PositionVertex(new Vector3(-10, 10, 10)),
new PositionVertex(new Vector3(10, 10, 10)),
new PositionVertex(new Vector3(10, 10, -10))
],
BufferUsageFlags.Vertex
);
indexBuffer = resourceUploader.CreateBuffer<ushort>(
[
0, 1, 2, 0, 2, 3,
6, 5, 4, 7, 6, 4,
8, 9, 10, 8, 10, 11,
14, 13, 12, 15, 14, 12,
16, 17, 18, 16, 18, 19,
22, 21, 20, 23, 22, 20
],
BufferUsageFlags.Index
);
resourceUploader.Upload();
resourceUploader.Dispose();
cubemap = Texture.CreateTextureCube(
GraphicsDevice,
16,
TextureFormat.R8G8B8A8,
TextureUsageFlags.ColorTarget | TextureUsageFlags.Sampler
);
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
// Clear each slice of the cubemap to a different color
for (uint i = 0; i < 6; i += 1)
{
ColorAttachmentInfo attachmentInfo = new ColorAttachmentInfo
{
TextureSlice = new TextureSlice
{
Texture = cubemap,
Layer = i,
MipLevel = 0
},
ClearColor = colors[i],
LoadOp = LoadOp.Clear,
StoreOp = StoreOp.Store
};
var renderPass = cmdbuf.BeginRenderPass(attachmentInfo);
cmdbuf.EndRenderPass(renderPass);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Update(System.TimeSpan delta)
{
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Bottom))
{
camPos.Z *= -1;
}
}
public override void Draw(double alpha)
{
Matrix4x4 proj = Matrix4x4.CreatePerspectiveFieldOfView(
MathHelper.ToRadians(75f),
(float) Window.Width / Window.Height,
0.01f,
100f
);
Matrix4x4 view = Matrix4x4.CreateLookAt(
camPos,
Vector3.Zero,
Vector3.Up
);
TransformVertexUniform vertUniforms = new TransformVertexUniform(view * proj);
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
var renderPass = cmdbuf.BeginRenderPass(
new ColorAttachmentInfo(
swapchainTexture,
false,
Color.Black
)
);
renderPass.BindGraphicsPipeline(pipeline);
renderPass.BindVertexBuffer(vertexBuffer);
renderPass.BindIndexBuffer(indexBuffer, IndexElementSize.Sixteen);
renderPass.BindFragmentSampler(new TextureSamplerBinding(cubemap, sampler));
renderPass.PushVertexUniformData(vertUniforms);
renderPass.DrawIndexedPrimitives(0, 0, 12);
cmdbuf.EndRenderPass(renderPass);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
}
}

View File

@ -0,0 +1,228 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
using MoonWorks.Math.Float;
namespace MoonWorksGraphicsTests;
class RenderTextureMipmapsExample : Example
{
private GraphicsPipeline Pipeline;
private Buffer VertexBuffer;
private Buffer IndexBuffer;
private Texture Texture;
private Sampler[] Samplers = new Sampler[5];
private float scale = 0.5f;
private int currentSamplerIndex = 0;
private Color[] colors =
[
Color.Red,
Color.Green,
Color.Blue,
Color.Yellow,
];
private string GetSamplerString(int index)
{
switch (index)
{
case 0:
return "PointClamp";
case 1:
return "LinearClamp";
case 2:
return "PointClamp with Mip LOD Bias = 0.25";
case 3:
return "PointClamp with Min LOD = 1";
case 4:
return "PointClamp with Max LOD = 1";
default:
throw new System.Exception("Unknown sampler!");
}
}
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Inputs = inputs;
Window.SetTitle("RenderTextureMipmaps");
Logger.LogInfo("Press Left and Right to shrink/expand the scale of the quad");
Logger.LogInfo("Press Down to cycle through sampler states");
Logger.LogInfo(GetSamplerString(currentSamplerIndex));
// Load the shaders
Shader vertShaderModule = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("TexturedQuadWithMatrix.vert"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Vertex,
ShaderFormat = ShaderFormat.SPIRV,
UniformBufferCount = 1
}
);
Shader fragShaderModule = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("TexturedQuad.frag"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Fragment,
ShaderFormat = ShaderFormat.SPIRV,
SamplerCount = 1
}
);
// Create the graphics pipeline
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
Window.SwapchainFormat,
vertShaderModule,
fragShaderModule
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureVertex>();
Pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create samplers
SamplerCreateInfo samplerCreateInfo = SamplerCreateInfo.PointClamp;
Samplers[0] = new Sampler(GraphicsDevice, samplerCreateInfo);
samplerCreateInfo = SamplerCreateInfo.LinearClamp;
Samplers[1] = new Sampler(GraphicsDevice, samplerCreateInfo);
samplerCreateInfo = SamplerCreateInfo.PointClamp;
samplerCreateInfo.MipLodBias = 0.25f;
Samplers[2] = new Sampler(GraphicsDevice, samplerCreateInfo);
samplerCreateInfo = SamplerCreateInfo.PointClamp;
samplerCreateInfo.MinLod = 1;
Samplers[3] = new Sampler(GraphicsDevice, samplerCreateInfo);
samplerCreateInfo = SamplerCreateInfo.PointClamp;
samplerCreateInfo.MaxLod = 1;
Samplers[4] = new Sampler(GraphicsDevice, samplerCreateInfo);
// Create and populate the GPU resources
var resourceUploader = new ResourceUploader(GraphicsDevice);
VertexBuffer = resourceUploader.CreateBuffer(
[
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)),
],
BufferUsageFlags.Vertex
);
IndexBuffer = resourceUploader.CreateBuffer<ushort>(
[
0, 1, 2,
0, 2, 3,
],
BufferUsageFlags.Index
);
resourceUploader.Upload();
resourceUploader.Dispose();
Texture = Texture.CreateTexture2D(
GraphicsDevice,
Window.Width,
Window.Height,
TextureFormat.R8G8B8A8,
TextureUsageFlags.ColorTarget | TextureUsageFlags.Sampler,
4
);
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
// Clear each mip level to a different color
for (uint i = 0; i < Texture.LevelCount; i += 1)
{
ColorAttachmentInfo attachmentInfo = new ColorAttachmentInfo
{
TextureSlice = new TextureSlice
{
Texture = Texture,
Layer = 0,
MipLevel = i
},
ClearColor = colors[i],
LoadOp = LoadOp.Clear,
StoreOp = StoreOp.Store,
Cycle = false
};
var renderPass = cmdbuf.BeginRenderPass(attachmentInfo);
cmdbuf.EndRenderPass(renderPass);
}
GraphicsDevice.Submit(cmdbuf);
}
public 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);
}
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Bottom))
{
currentSamplerIndex = (currentSamplerIndex + 1) % Samplers.Length;
Logger.LogInfo(GetSamplerString(currentSamplerIndex));
}
}
public override void Draw(double alpha)
{
TransformVertexUniform vertUniforms = new TransformVertexUniform(Matrix4x4.CreateScale(scale, scale, 1));
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
var renderPass = cmdbuf.BeginRenderPass(
new ColorAttachmentInfo(
swapchainTexture,
false,
Color.Black
)
);
renderPass.BindGraphicsPipeline(Pipeline);
renderPass.BindVertexBuffer(VertexBuffer);
renderPass.BindIndexBuffer(IndexBuffer, IndexElementSize.Sixteen);
renderPass.BindFragmentSampler(new TextureSamplerBinding(Texture, Samplers[currentSamplerIndex]));
renderPass.PushVertexUniformData(vertUniforms);
renderPass.DrawIndexedPrimitives(0, 0, 2);
cmdbuf.EndRenderPass(renderPass);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
Pipeline.Dispose();
VertexBuffer.Dispose();
IndexBuffer.Dispose();
Texture.Dispose();
for (var i = 0; i < 5; i += 1)
{
Samplers[i].Dispose();
}
}
}

View File

@ -0,0 +1,89 @@
using System;
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
namespace MoonWorksGraphicsTests;
class StoreLoadExample : Example
{
private GraphicsPipeline FillPipeline;
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Window.SetTitle("StoreLoad");
Shader vertShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("RawTriangle.vert"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Vertex,
ShaderFormat = ShaderFormat.SPIRV
}
);
Shader fragShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("SolidColor.frag"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Fragment,
ShaderFormat = ShaderFormat.SPIRV
}
);
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
Window.SwapchainFormat,
vertShader,
fragShader
);
FillPipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
}
public override void Update(TimeSpan delta)
{
}
public override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
var renderPass = cmdbuf.BeginRenderPass(
new ColorAttachmentInfo(
swapchainTexture,
false,
Color.Blue
)
);
renderPass.BindGraphicsPipeline(FillPipeline);
renderPass.DrawPrimitives(0, 1);
cmdbuf.EndRenderPass(renderPass);
renderPass = cmdbuf.BeginRenderPass(
new ColorAttachmentInfo(
swapchainTexture,
false,
LoadOp.Load,
StoreOp.Store
)
);
cmdbuf.EndRenderPass(renderPass);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
FillPipeline.Dispose();
}
}

View File

@ -0,0 +1,227 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
using MoonWorks.Math.Float;
namespace MoonWorksGraphicsTests;
class Texture3DCopyExample : Example
{
private GraphicsPipeline Pipeline;
private Buffer VertexBuffer;
private Buffer IndexBuffer;
private Texture RenderTexture;
private Texture Texture3D;
private Sampler Sampler;
private float t;
private Color[] colors =
[
Color.Red,
Color.Green,
Color.Blue,
];
struct FragUniform
{
public float Depth;
public FragUniform(float depth)
{
Depth = depth;
}
}
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Window.SetTitle("Texture3DCopy");
// Load the shaders
Shader vertShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("TexturedQuad.vert"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Vertex,
ShaderFormat = ShaderFormat.SPIRV
}
);
Shader fragShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("TexturedQuad3D.frag"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Fragment,
ShaderFormat = ShaderFormat.SPIRV,
SamplerCount = 1,
UniformBufferCount = 1
}
);
// Create the graphics pipeline
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
Window.SwapchainFormat,
vertShader,
fragShader
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureVertex>();
Pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create samplers
Sampler = new Sampler(GraphicsDevice, SamplerCreateInfo.LinearWrap);
// Create and populate the GPU resources
var resourceUploader = new ResourceUploader(GraphicsDevice);
VertexBuffer = resourceUploader.CreateBuffer(
[
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)),
],
BufferUsageFlags.Vertex
);
IndexBuffer = resourceUploader.CreateBuffer<ushort>(
[
0, 1, 2,
0, 2, 3,
],
BufferUsageFlags.Index
);
resourceUploader.Upload();
resourceUploader.Dispose();
RenderTexture = Texture.CreateTexture2DArray(
GraphicsDevice,
16,
16,
(uint) colors.Length,
TextureFormat.R8G8B8A8,
TextureUsageFlags.ColorTarget | TextureUsageFlags.Sampler
);
Texture3D = new Texture(GraphicsDevice, new TextureCreateInfo
{
Width = 16,
Height = 16,
Depth = 3,
IsCube = false,
LayerCount = 1,
LevelCount = 1,
SampleCount = SampleCount.One,
Format = TextureFormat.R8G8B8A8,
UsageFlags = TextureUsageFlags.Sampler
});
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
// Clear each layer slice of the RT to a different color
for (uint i = 0; i < colors.Length; i += 1)
{
ColorAttachmentInfo attachmentInfo = new ColorAttachmentInfo
{
TextureSlice = new TextureSlice
{
Texture = RenderTexture,
Layer = i,
MipLevel = 0
},
ClearColor = colors[i],
LoadOp = LoadOp.Clear,
StoreOp = StoreOp.Store
};
var renderPass = cmdbuf.BeginRenderPass(attachmentInfo);
cmdbuf.EndRenderPass(renderPass);
}
// Copy each layer slice to a different 3D depth
var copyPass = cmdbuf.BeginCopyPass();
for (var i = 0; i < 3; i += 1)
{
copyPass.CopyTextureToTexture(
new TextureRegion
{
TextureSlice = new TextureSlice
{
Texture = RenderTexture,
Layer = (uint) i,
MipLevel = 0
},
X = 0,
Y = 0,
Z = 0,
Width = 16,
Height = 16,
Depth = 1
},
new TextureRegion
{
TextureSlice = new TextureSlice
{
Texture = Texture3D,
Layer = 0,
MipLevel = 0
},
X = 0,
Y = 0,
Z = (uint) i,
Width = 16,
Height = 16,
Depth = 1
},
false
);
}
cmdbuf.EndCopyPass(copyPass);
GraphicsDevice.Submit(cmdbuf);
}
public override void Update(System.TimeSpan delta) { }
public override void Draw(double alpha)
{
t += 0.01f;
FragUniform fragUniform = new FragUniform(t);
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
var renderPass = cmdbuf.BeginRenderPass(
new ColorAttachmentInfo(
swapchainTexture,
false,
Color.Black
)
);
renderPass.BindGraphicsPipeline(Pipeline);
renderPass.BindVertexBuffer(VertexBuffer);
renderPass.BindIndexBuffer(IndexBuffer, IndexElementSize.Sixteen);
renderPass.BindFragmentSampler(new TextureSamplerBinding(Texture3D, Sampler));
renderPass.PushFragmentUniformData(fragUniform);
renderPass.DrawIndexedPrimitives(0, 0, 2);
cmdbuf.EndRenderPass(renderPass);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
Pipeline.Dispose();
VertexBuffer.Dispose();
IndexBuffer.Dispose();
RenderTexture.Dispose();
Texture3D.Dispose();
Sampler.Dispose();
}
}

View File

@ -0,0 +1,198 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
using MoonWorks.Math.Float;
namespace MoonWorksGraphicsTests;
class Texture3DExample : Example
{
private GraphicsPipeline Pipeline;
private Buffer VertexBuffer;
private Buffer IndexBuffer;
private Texture Texture;
private Sampler Sampler;
private int currentDepth = 0;
struct FragUniform
{
public float Depth;
public FragUniform(float depth)
{
Depth = depth;
}
}
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Inputs = inputs;
Window.SetTitle("Texture3D");
Logger.LogInfo("Press Left and Right to cycle between depth slices");
// Load the shaders
Shader vertShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("TexturedQuad.vert"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Vertex,
ShaderFormat = ShaderFormat.SPIRV
}
);
Shader fragShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("TexturedQuad3D.frag"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Fragment,
ShaderFormat = ShaderFormat.SPIRV,
SamplerCount = 1,
UniformBufferCount = 1
}
);
// Create the graphics pipeline
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
Window.SwapchainFormat,
vertShader,
fragShader
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureVertex>();
Pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create samplers
Sampler = new Sampler(GraphicsDevice, SamplerCreateInfo.PointClamp);
// Create and populate the GPU resources
var resourceUploader = new ResourceUploader(GraphicsDevice);
VertexBuffer = resourceUploader.CreateBuffer(
[
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))
],
BufferUsageFlags.Vertex
);
IndexBuffer = resourceUploader.CreateBuffer<ushort>(
[
0, 1, 2,
0, 2, 3,
],
BufferUsageFlags.Index
);
Texture = Texture.CreateTexture3D(
GraphicsDevice,
16,
16,
7,
TextureFormat.R8G8B8A8,
TextureUsageFlags.Sampler
);
// Load each depth subimage of the 3D texture
for (uint i = 0; i < Texture.Depth; i += 1)
{
var region = new TextureRegion
{
TextureSlice = new TextureSlice
{
Texture = Texture,
MipLevel = 0,
Layer = 0
},
X = 0,
Y = 0,
Z = i,
Width = Texture.Width,
Height = Texture.Height,
Depth = 1
};
resourceUploader.SetTextureDataFromCompressed(
region,
TestUtils.GetTexturePath($"tex3d_{i}.png")
);
}
resourceUploader.Upload();
resourceUploader.Dispose();
}
public override void Update(System.TimeSpan delta)
{
int prevDepth = currentDepth;
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Left))
{
currentDepth -= 1;
if (currentDepth < 0)
{
currentDepth = (int) Texture.Depth - 1;
}
}
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Right))
{
currentDepth += 1;
if (currentDepth >= Texture.Depth)
{
currentDepth = 0;
}
}
if (prevDepth != currentDepth)
{
Logger.LogInfo("Setting depth to: " + currentDepth);
}
}
public override void Draw(double alpha)
{
FragUniform fragUniform = new FragUniform((float)currentDepth / Texture.Depth + 0.01f);
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
var renderPass = cmdbuf.BeginRenderPass(
new ColorAttachmentInfo(
swapchainTexture,
false,
Color.Black
)
);
renderPass.BindGraphicsPipeline(Pipeline);
renderPass.BindVertexBuffer(VertexBuffer);
renderPass.BindIndexBuffer(IndexBuffer, IndexElementSize.Sixteen);
renderPass.BindFragmentSampler(new TextureSamplerBinding(Texture, Sampler));
renderPass.PushFragmentUniformData(fragUniform);
renderPass.DrawIndexedPrimitives(0, 0, 2);
cmdbuf.EndRenderPass(renderPass);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
Pipeline.Dispose();
VertexBuffer.Dispose();
IndexBuffer.Dispose();
Texture.Dispose();
Sampler.Dispose();
}
}

View File

@ -0,0 +1,174 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
using MoonWorks.Math.Float;
namespace MoonWorksGraphicsTests;
class TextureMipmapsExample : Example
{
private GraphicsPipeline Pipeline;
private Buffer VertexBuffer;
private Buffer IndexBuffer;
private Texture Texture;
private Sampler Sampler;
private float scale = 0.5f;
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Inputs = inputs;
Window.SetTitle("TextureMipmaps");
Logger.LogInfo("Press Left and Right to shrink/expand the scale of the quad");
// Load the shaders
Shader vertShaderModule = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("TexturedQuadWithMatrix.vert"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Vertex,
ShaderFormat = ShaderFormat.SPIRV,
UniformBufferCount = 1
}
);
Shader fragShaderModule = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("TexturedQuad.frag"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Fragment,
ShaderFormat = ShaderFormat.SPIRV,
SamplerCount = 1
}
);
// Create the graphics pipeline
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
Window.SwapchainFormat,
vertShaderModule,
fragShaderModule
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureVertex>();
Pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
Sampler = new Sampler(GraphicsDevice, SamplerCreateInfo.PointClamp);
// Create and populate the GPU resources
Texture = Texture.CreateTexture2D(
GraphicsDevice,
256,
256,
TextureFormat.R8G8B8A8,
TextureUsageFlags.Sampler,
4
);
var resourceUploader = new ResourceUploader(GraphicsDevice);
VertexBuffer = resourceUploader.CreateBuffer(
[
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)),
],
BufferUsageFlags.Vertex
);
IndexBuffer = resourceUploader.CreateBuffer<ushort>(
[
0, 1, 2,
0, 2, 3
],
BufferUsageFlags.Index
);
// Set the various mip levels
for (uint i = 0; i < Texture.LevelCount; i += 1)
{
var w = Texture.Width >> (int) i;
var h = Texture.Height >> (int) i;
var region = new TextureRegion
{
TextureSlice = new TextureSlice
{
Texture = Texture,
Layer = 0,
MipLevel = i
},
X = 0,
Y = 0,
Z = 0,
Width = w,
Height = h,
Depth = 1
};
resourceUploader.SetTextureDataFromCompressed(
region,
TestUtils.GetTexturePath($"mip{i}.png")
);
}
resourceUploader.Upload();
resourceUploader.Dispose();
}
public 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);
}
}
public override void Draw(double alpha)
{
TransformVertexUniform vertUniforms = new TransformVertexUniform(Matrix4x4.CreateScale(scale, scale, 1));
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
var renderPass = cmdbuf.BeginRenderPass(
new ColorAttachmentInfo(
swapchainTexture,
false,
Color.Black
)
);
renderPass.BindGraphicsPipeline(Pipeline);
renderPass.BindVertexBuffer(VertexBuffer);
renderPass.BindIndexBuffer(IndexBuffer, IndexElementSize.Sixteen);
renderPass.BindFragmentSampler(new TextureSamplerBinding(Texture, Sampler));
renderPass.PushVertexUniformData(vertUniforms);
renderPass.DrawIndexedPrimitives(0, 0, 2);
cmdbuf.EndRenderPass(renderPass);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
Pipeline.Dispose();
VertexBuffer.Dispose();
IndexBuffer.Dispose();
Texture.Dispose();
Sampler.Dispose();
}
}

View File

@ -0,0 +1,165 @@
using System.Runtime.InteropServices;
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
using MoonWorks.Math.Float;
namespace MoonWorksGraphicsTests;
class TexturedAnimatedQuadExample : Example
{
private GraphicsPipeline Pipeline;
private Buffer VertexBuffer;
private Buffer IndexBuffer;
private Texture Texture;
private Sampler Sampler;
private float t;
[StructLayout(LayoutKind.Sequential)]
private struct FragmentUniforms
{
public Vector4 MultiplyColor;
public FragmentUniforms(Vector4 multiplyColor)
{
MultiplyColor = multiplyColor;
}
}
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Window.SetTitle("TexturedAnimatedQuad");
// Load the shaders
Shader vertShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("TexturedQuadWithMatrix.vert"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Vertex,
ShaderFormat = ShaderFormat.SPIRV,
UniformBufferCount = 1
}
);
Shader fragShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("TexturedQuadWithMultiplyColor.frag"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Fragment,
ShaderFormat = ShaderFormat.SPIRV,
SamplerCount = 1,
UniformBufferCount = 1
}
);
// Create the graphics pipeline
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
Window.SwapchainFormat,
vertShader,
fragShader
);
pipelineCreateInfo.AttachmentInfo.ColorAttachmentDescriptions[0].BlendState = ColorAttachmentBlendState.AlphaBlend;
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureVertex>();
Pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
Sampler = new Sampler(GraphicsDevice, SamplerCreateInfo.PointClamp);
// Create and populate the GPU resources
var resourceUploader = new ResourceUploader(GraphicsDevice);
VertexBuffer = resourceUploader.CreateBuffer(
[
new PositionTextureVertex(new Vector3(-0.5f, -0.5f, 0), new Vector2(0, 0)),
new PositionTextureVertex(new Vector3(0.5f, -0.5f, 0), new Vector2(1, 0)),
new PositionTextureVertex(new Vector3(0.5f, 0.5f, 0), new Vector2(1, 1)),
new PositionTextureVertex(new Vector3(-0.5f, 0.5f, 0), new Vector2(0, 1)),
],
BufferUsageFlags.Vertex
);
IndexBuffer = resourceUploader.CreateBuffer<ushort>(
[
0, 1, 2,
0, 2, 3,
],
BufferUsageFlags.Index
);
Texture = resourceUploader.CreateTexture2DFromCompressed(TestUtils.GetTexturePath("ravioli.png"));
resourceUploader.Upload();
resourceUploader.Dispose();
}
public override void Update(System.TimeSpan delta)
{
t += (float) delta.TotalSeconds;
}
public override void Draw(double alpha)
{
TransformVertexUniform vertUniforms;
FragmentUniforms fragUniforms;
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
var renderPass = cmdbuf.BeginRenderPass(new ColorAttachmentInfo(swapchainTexture, false, Color.Black));
renderPass.BindGraphicsPipeline(Pipeline);
renderPass.BindVertexBuffer(VertexBuffer);
renderPass.BindIndexBuffer(IndexBuffer, IndexElementSize.Sixteen);
renderPass.BindFragmentSampler(new TextureSamplerBinding(Texture, Sampler));
// Top-left
vertUniforms = new TransformVertexUniform(Matrix4x4.CreateRotationZ(t) * Matrix4x4.CreateTranslation(new Vector3(-0.5f, -0.5f, 0)));
fragUniforms = new FragmentUniforms(new Vector4(1f, 0.5f + System.MathF.Sin(t) * 0.5f, 1f, 1f));
renderPass.PushVertexUniformData(vertUniforms);
renderPass.PushFragmentUniformData(fragUniforms);
renderPass.DrawIndexedPrimitives(0, 0, 2);
// Top-right
vertUniforms = new TransformVertexUniform(Matrix4x4.CreateRotationZ((2 * System.MathF.PI) - t) * Matrix4x4.CreateTranslation(new Vector3(0.5f, -0.5f, 0)));
fragUniforms = new FragmentUniforms(new Vector4(1f, 0.5f + System.MathF.Cos(t) * 0.5f, 1f, 1f));
renderPass.PushVertexUniformData(vertUniforms);
renderPass.PushFragmentUniformData(fragUniforms);
renderPass.DrawIndexedPrimitives(0, 0, 2);
// Bottom-left
vertUniforms = new TransformVertexUniform(Matrix4x4.CreateRotationZ(t) * Matrix4x4.CreateTranslation(new Vector3(-0.5f, 0.5f, 0)));
fragUniforms = new FragmentUniforms(new Vector4(1f, 0.5f + System.MathF.Sin(t) * 0.2f, 1f, 1f));
renderPass.PushVertexUniformData(vertUniforms);
renderPass.PushFragmentUniformData(fragUniforms);
renderPass.DrawIndexedPrimitives(0, 0, 2);
// Bottom-right
vertUniforms = new TransformVertexUniform(Matrix4x4.CreateRotationZ(t) * Matrix4x4.CreateTranslation(new Vector3(0.5f, 0.5f, 0)));
fragUniforms = new FragmentUniforms(new Vector4(1f, 0.5f + System.MathF.Cos(t) * 1f, 1f, 1f));
renderPass.PushVertexUniformData(vertUniforms);
renderPass.PushFragmentUniformData(fragUniforms);
renderPass.DrawIndexedPrimitives(0, 0, 2);
cmdbuf.EndRenderPass(renderPass);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
Pipeline.Dispose();
VertexBuffer.Dispose();
IndexBuffer.Dispose();
Texture.Dispose();
Sampler.Dispose();
}
}

View File

@ -0,0 +1,210 @@
using System;
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
using MoonWorks.Math.Float;
using Buffer = MoonWorks.Graphics.Buffer;
namespace MoonWorksGraphicsTests;
class TexturedQuadExample : Example
{
private GraphicsPipeline pipeline;
private Buffer vertexBuffer;
private Buffer indexBuffer;
private Sampler[] samplers = new Sampler[6];
private string[] samplerNames = new string[]
{
"PointClamp",
"PointWrap",
"LinearClamp",
"LinearWrap",
"AnisotropicClamp",
"AnisotropicWrap"
};
private int currentSamplerIndex;
private Texture[] textures = new Texture[4];
private string[] imageLoadFormatNames = new string[]
{
"PNG from file",
"PNG from memory",
"QOI from file",
"QOI from memory"
};
private int currentTextureIndex;
private System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Inputs = inputs;
Window.SetTitle("TexturedQuad");
Logger.LogInfo("Press Left and Right to cycle between sampler states");
Logger.LogInfo("Setting sampler state to: " + samplerNames[0]);
Logger.LogInfo("Press Down to cycle between image load formats");
Logger.LogInfo("Setting image format to: " + imageLoadFormatNames[0]);
var pngBytes = System.IO.File.ReadAllBytes(TestUtils.GetTexturePath("ravioli.png"));
var qoiBytes = System.IO.File.ReadAllBytes(TestUtils.GetTexturePath("ravioli.qoi"));
Logger.LogInfo(pngBytes.Length.ToString());
Logger.LogInfo(qoiBytes.Length.ToString());
// Load the shaders
Shader vertShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("TexturedQuad.vert"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Vertex,
ShaderFormat = ShaderFormat.SPIRV
}
);
Shader fragShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("TexturedQuad.frag"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Fragment,
ShaderFormat = ShaderFormat.SPIRV,
SamplerCount = 1
}
);
// Create the graphics pipeline
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
Window.SwapchainFormat,
vertShader,
fragShader
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureVertex>();
pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create samplers
samplers[0] = new Sampler(GraphicsDevice, SamplerCreateInfo.PointClamp);
samplers[1] = new Sampler(GraphicsDevice, SamplerCreateInfo.PointWrap);
samplers[2] = new Sampler(GraphicsDevice, SamplerCreateInfo.LinearClamp);
samplers[3] = new Sampler(GraphicsDevice, SamplerCreateInfo.LinearWrap);
samplers[4] = new Sampler(GraphicsDevice, SamplerCreateInfo.AnisotropicClamp);
samplers[5] = new Sampler(GraphicsDevice, SamplerCreateInfo.AnisotropicWrap);
var vertexData = new Span<PositionTextureVertex>([
new PositionTextureVertex(new Vector3(-1, 1, 0), new Vector2(0, 0)),
new PositionTextureVertex(new Vector3( 1, 1, 0), new Vector2(4, 0)),
new PositionTextureVertex(new Vector3( 1, -1, 0), new Vector2(4, 4)),
new PositionTextureVertex(new Vector3(-1, -1, 0), new Vector2(0, 4)),
]);
var indexData = new Span<ushort>([
0, 1, 2,
0, 2, 3,
]);
// Create and populate the GPU resources
var resourceUploader = new ResourceUploader(GraphicsDevice);
vertexBuffer = resourceUploader.CreateBuffer(vertexData, BufferUsageFlags.Vertex);
indexBuffer = resourceUploader.CreateBuffer(indexData, BufferUsageFlags.Index);
textures[0] = resourceUploader.CreateTexture2DFromCompressed(TestUtils.GetTexturePath("ravioli.png"));
textures[1] = resourceUploader.CreateTexture2DFromCompressed(pngBytes);
textures[2] = resourceUploader.CreateTexture2DFromCompressed(TestUtils.GetTexturePath("ravioli.qoi"));
textures[3] = resourceUploader.CreateTexture2DFromCompressed(qoiBytes);
resourceUploader.Upload();
resourceUploader.Dispose();
}
public override void Update(System.TimeSpan delta)
{
int prevSamplerIndex = currentSamplerIndex;
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Left))
{
currentSamplerIndex -= 1;
if (currentSamplerIndex < 0)
{
currentSamplerIndex = samplers.Length - 1;
}
}
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Right))
{
currentSamplerIndex += 1;
if (currentSamplerIndex >= samplers.Length)
{
currentSamplerIndex = 0;
}
}
if (prevSamplerIndex != currentSamplerIndex)
{
Logger.LogInfo("Setting sampler state to: " + samplerNames[currentSamplerIndex]);
}
int prevTextureIndex = currentTextureIndex;
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Bottom))
{
currentTextureIndex = (currentTextureIndex + 1) % imageLoadFormatNames.Length;
}
if (prevTextureIndex != currentTextureIndex)
{
Logger.LogInfo("Setting texture format to: " + imageLoadFormatNames[currentTextureIndex]);
}
}
public override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
var renderPass = cmdbuf.BeginRenderPass(
new ColorAttachmentInfo(
swapchainTexture,
false,
Color.Black
)
);
renderPass.BindGraphicsPipeline(pipeline);
renderPass.BindVertexBuffer(vertexBuffer);
renderPass.BindIndexBuffer(indexBuffer, IndexElementSize.Sixteen);
renderPass.BindFragmentSampler(new TextureSamplerBinding(textures[currentTextureIndex], samplers[currentSamplerIndex]));
renderPass.DrawIndexedPrimitives(0, 0, 2);
cmdbuf.EndRenderPass(renderPass);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
pipeline.Dispose();
vertexBuffer.Dispose();
indexBuffer.Dispose();
for (var i = 0; i < samplers.Length; i += 1)
{
samplers[i].Dispose();
}
for (var i = 0; i < textures.Length; i += 1)
{
textures[i].Dispose();
}
}
}

View File

@ -0,0 +1,96 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
using MoonWorks.Math.Float;
namespace MoonWorksGraphicsTests;
class TriangleVertexBufferExample : Example
{
private GraphicsPipeline Pipeline;
private Buffer VertexBuffer;
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Window.SetTitle("TriangleVertexBuffer");
// Load the shaders
Shader vertShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("PositionColor.vert"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Vertex,
ShaderFormat = ShaderFormat.SPIRV
}
);
Shader fragShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("SolidColor.frag"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Fragment,
ShaderFormat = ShaderFormat.SPIRV
}
);
// Create the graphics pipeline
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
Window.SwapchainFormat,
vertShader,
fragShader
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionColorVertex>();
Pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create and populate the vertex buffer
var resourceUploader = new ResourceUploader(GraphicsDevice);
VertexBuffer = resourceUploader.CreateBuffer(
[
new PositionColorVertex(new Vector3(-1, -1, 0), Color.Red),
new PositionColorVertex(new Vector3( 1, -1, 0), Color.Lime),
new PositionColorVertex(new Vector3( 0, 1, 0), Color.Blue),
],
BufferUsageFlags.Vertex
);
resourceUploader.Upload();
resourceUploader.Dispose();
}
public override void Update(System.TimeSpan delta) { }
public override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
var renderPass = cmdbuf.BeginRenderPass(
new ColorAttachmentInfo(
swapchainTexture,
false,
Color.Black
)
);
renderPass.BindGraphicsPipeline(Pipeline);
renderPass.BindVertexBuffer(VertexBuffer);
renderPass.DrawPrimitives(0, 1);
cmdbuf.EndRenderPass(renderPass);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
Pipeline.Dispose();
VertexBuffer.Dispose();
}
}

View File

@ -0,0 +1,113 @@
using System;
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
using MoonWorks.Math.Float;
using Buffer = MoonWorks.Graphics.Buffer;
namespace MoonWorksGraphicsTests;
class VertexSamplerExample : Example
{
private GraphicsPipeline Pipeline;
private Buffer VertexBuffer;
private Texture Texture;
private Sampler Sampler;
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Window.SetTitle("VertexSampler");
// Load the shaders
Shader vertShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("PositionSampler.vert"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Vertex,
ShaderFormat = ShaderFormat.SPIRV,
SamplerCount = 1
}
);
Shader fragShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("SolidColor.frag"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Fragment,
ShaderFormat = ShaderFormat.SPIRV
}
);
// Create the graphics pipeline
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
Window.SwapchainFormat,
vertShader,
fragShader
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureVertex>();
Pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create and populate the GPU resources
Sampler = new Sampler(GraphicsDevice, SamplerCreateInfo.PointClamp);
var resourceUploader = new ResourceUploader(GraphicsDevice);
VertexBuffer = resourceUploader.CreateBuffer(
[
new PositionTextureVertex(new Vector3(-1, -1, 0), new Vector2(0, 0)),
new PositionTextureVertex(new Vector3( 1, -1, 0), new Vector2(0.334f, 0)),
new PositionTextureVertex(new Vector3( 0, 1, 0), new Vector2(0.667f, 0)),
],
BufferUsageFlags.Vertex
);
Texture = resourceUploader.CreateTexture2D(
new Span<Color>([Color.Yellow, Color.Indigo, Color.HotPink]),
3,
1
);
resourceUploader.Upload();
resourceUploader.Dispose();
}
public override void Update(System.TimeSpan delta) { }
public override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
var renderPass = cmdbuf.BeginRenderPass(
new ColorAttachmentInfo(
swapchainTexture,
false,
Color.Black
)
);
renderPass.BindGraphicsPipeline(Pipeline);
renderPass.BindVertexBuffer(VertexBuffer);
renderPass.BindVertexSampler(new TextureSamplerBinding(Texture, Sampler));
renderPass.DrawPrimitives(0, 1);
cmdbuf.EndRenderPass(renderPass);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
Pipeline.Dispose();
VertexBuffer.Dispose();
Texture.Dispose();
Sampler.Dispose();
}
}

View File

@ -0,0 +1,53 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Video;
using MoonWorks.Input;
namespace MoonWorksGraphicsTests;
class VideoPlayerExample : Example
{
private VideoAV1 Video;
private VideoPlayer VideoPlayer;
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Window.SetTitle("VideoPlayer");
// Load the video
Video = new VideoAV1(GraphicsDevice, TestUtils.GetVideoPath("hello.obu"), 25);
// Play the video
VideoPlayer = new VideoPlayer(GraphicsDevice);
VideoPlayer.Load(Video);
VideoPlayer.Loop = true;
VideoPlayer.Play();
}
public override void Update(System.TimeSpan delta)
{
VideoPlayer.Render();
}
public override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
cmdbuf.Blit(VideoPlayer.RenderTexture, swapchainTexture, Filter.Linear, false);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
VideoPlayer.Stop();
VideoPlayer.Unload();
VideoPlayer.Dispose();
Video.Dispose();
}
}

View File

@ -0,0 +1,118 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Input;
namespace MoonWorksGraphicsTests;
class WindowResizingExample : Example
{
private GraphicsPipeline pipeline;
private int currentResolutionIndex;
private record struct Res(uint Width, uint Height);
private Res[] resolutions =
[
new Res(640, 480),
new Res(1280, 720),
new Res(1024, 1024),
new Res(1600, 900),
new Res(1920, 1080),
new Res(3200, 1800),
new Res(3840, 2160),
];
public override void Init(Window window, GraphicsDevice graphicsDevice, Inputs inputs)
{
Window = window;
GraphicsDevice = graphicsDevice;
Inputs = inputs;
Window.SetTitle("WindowResizing");
Logger.LogInfo("Press left and right to resize the window!");
Shader vertShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("RawTriangle.vert"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Vertex,
ShaderFormat = ShaderFormat.SPIRV
}
);
Shader fragShader = new Shader(
GraphicsDevice,
TestUtils.GetShaderPath("SolidColor.frag"),
"main",
new ShaderCreateInfo
{
ShaderStage = ShaderStage.Fragment,
ShaderFormat = ShaderFormat.SPIRV
}
);
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
Window.SwapchainFormat,
vertShader,
fragShader
);
pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
}
public override void Update(System.TimeSpan delta)
{
int prevResolutionIndex = currentResolutionIndex;
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Left))
{
currentResolutionIndex -= 1;
if (currentResolutionIndex < 0)
{
currentResolutionIndex = resolutions.Length - 1;
}
}
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Right))
{
currentResolutionIndex += 1;
if (currentResolutionIndex >= resolutions.Length)
{
currentResolutionIndex = 0;
}
}
if (prevResolutionIndex != currentResolutionIndex)
{
Logger.LogInfo("Setting resolution to: " + resolutions[currentResolutionIndex]);
Window.SetSize(resolutions[currentResolutionIndex].Width, resolutions[currentResolutionIndex].Height);
}
}
public override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture swapchainTexture = cmdbuf.AcquireSwapchainTexture(Window);
if (swapchainTexture != null)
{
var renderPass = cmdbuf.BeginRenderPass(
new ColorAttachmentInfo(
swapchainTexture,
false,
Color.Black
)
);
renderPass.BindGraphicsPipeline(pipeline);
renderPass.DrawPrimitives(0, 1);
cmdbuf.EndRenderPass(renderPass);
}
GraphicsDevice.Submit(cmdbuf);
}
public override void Destroy()
{
pipeline.Dispose();
Window.SetSize(640, 480);
}
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,113 +0,0 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Math.Float;
using System.Runtime.InteropServices;
namespace MoonWorks.Test
{
class GetBufferDataGame : Game
{
public GetBufferDataGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{
PositionVertex[] vertices = new PositionVertex[]
{
new PositionVertex(new Vector3(0, 0, 0)),
new PositionVertex(new Vector3(0, 0, 1)),
new PositionVertex(new Vector3(0, 1, 0)),
new PositionVertex(new Vector3(0, 1, 1)),
new PositionVertex(new Vector3(1, 0, 0)),
new PositionVertex(new Vector3(1, 0, 1)),
new PositionVertex(new Vector3(1, 1, 0)),
new PositionVertex(new Vector3(1, 1, 1)),
};
PositionVertex[] otherVerts = new PositionVertex[]
{
new PositionVertex(new Vector3(1, 2, 3)),
new PositionVertex(new Vector3(4, 5, 6)),
new PositionVertex(new Vector3(7, 8, 9))
};
int vertexSize = Marshal.SizeOf<PositionVertex>();
Buffer vertexBuffer = Buffer.Create<PositionVertex>(
GraphicsDevice,
BufferUsageFlags.Vertex,
(uint) vertices.Length
);
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
cmdbuf.SetBufferData(vertexBuffer, vertices);
var fence = GraphicsDevice.SubmitAndAcquireFence(cmdbuf);
// Wait for the vertices to finish uploading...
GraphicsDevice.WaitForFences(fence);
GraphicsDevice.ReleaseFence(fence);
// Read back and print out the vertex values
PositionVertex[] readbackVertices = new PositionVertex[vertices.Length];
vertexBuffer.GetData(readbackVertices);
for (int i = 0; i < readbackVertices.Length; i += 1)
{
Logger.LogInfo(readbackVertices[i].ToString());
}
// Change the first three vertices
cmdbuf = GraphicsDevice.AcquireCommandBuffer();
cmdbuf.SetBufferData(vertexBuffer, otherVerts);
fence = GraphicsDevice.SubmitAndAcquireFence(cmdbuf);
GraphicsDevice.WaitForFences(fence);
GraphicsDevice.ReleaseFence(fence);
// Read the updated buffer
vertexBuffer.GetData(readbackVertices);
Logger.LogInfo("=== Change first three vertices ===");
for (int i = 0; i < readbackVertices.Length; i += 1)
{
Logger.LogInfo(readbackVertices[i].ToString());
}
// Change the last two vertices
cmdbuf = GraphicsDevice.AcquireCommandBuffer();
cmdbuf.SetBufferData(
vertexBuffer,
otherVerts,
(uint) (vertexSize * (vertices.Length - 2)),
1,
2
);
fence = GraphicsDevice.SubmitAndAcquireFence(cmdbuf);
GraphicsDevice.WaitForFences(fence);
GraphicsDevice.ReleaseFence(fence);
// Read the updated buffer
vertexBuffer.GetData(readbackVertices);
Logger.LogInfo("=== Change last two vertices ===");
for (int i = 0; i < readbackVertices.Length; i += 1)
{
Logger.LogInfo(readbackVertices[i].ToString());
}
}
protected override void Update(System.TimeSpan delta) { }
protected override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture? swapchainTexture = cmdbuf.AcquireSwapchainTexture(MainWindow);
if (swapchainTexture != null)
{
cmdbuf.BeginRenderPass(new ColorAttachmentInfo(swapchainTexture, Color.Black));
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
GetBufferDataGame game = new GetBufferDataGame();
game.Run();
}
}
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,106 +0,0 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Math.Float;
namespace MoonWorks.Test
{
class InstancingAndOffsetsGame : Game
{
private GraphicsPipeline pipeline;
private Buffer vertexBuffer;
private Buffer indexBuffer;
private bool useVertexOffset;
private bool useIndexOffset;
public InstancingAndOffsetsGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{
Logger.LogInfo("Press Left to toggle vertex offset\nPress Right to toggle index offset");
// Load the shaders
ShaderModule vertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("PositionColorInstanced.vert"));
ShaderModule fragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("SolidColor.frag"));
// Create the graphics pipeline
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
MainWindow.SwapchainFormat,
vertShaderModule,
fragShaderModule
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionColorVertex>();
pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create and populate the vertex and index buffers
vertexBuffer = Buffer.Create<PositionColorVertex>(GraphicsDevice, BufferUsageFlags.Vertex, 9);
indexBuffer = Buffer.Create<ushort>(GraphicsDevice, BufferUsageFlags.Index, 6);
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
cmdbuf.SetBufferData(
vertexBuffer,
new PositionColorVertex[]
{
new PositionColorVertex(new Vector3(-1, 1, 0), Color.Red),
new PositionColorVertex(new Vector3(1, 1, 0), Color.Lime),
new PositionColorVertex(new Vector3(0, -1, 0), Color.Blue),
new PositionColorVertex(new Vector3(-1, 1, 0), Color.Orange),
new PositionColorVertex(new Vector3(1, 1, 0), Color.Green),
new PositionColorVertex(new Vector3(0, -1, 0), Color.Aqua),
new PositionColorVertex(new Vector3(-1, 1, 0), Color.White),
new PositionColorVertex(new Vector3(1, 1, 0), Color.White),
new PositionColorVertex(new Vector3(0, -1, 0), Color.White),
}
);
cmdbuf.SetBufferData(
indexBuffer,
new ushort[]
{
0, 1, 2,
3, 4, 5,
}
);
GraphicsDevice.Submit(cmdbuf);
}
protected override void Update(System.TimeSpan delta)
{
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Left))
{
useVertexOffset = !useVertexOffset;
Logger.LogInfo("Using vertex offset: " + useVertexOffset);
}
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Right))
{
useIndexOffset = !useIndexOffset;
Logger.LogInfo("Using index offset: " + useIndexOffset);
}
}
protected override void Draw(double alpha)
{
uint vertexOffset = useVertexOffset ? 3u : 0;
uint indexOffset = useIndexOffset ? 3u : 0;
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.DrawInstancedPrimitives(vertexOffset, indexOffset, 1, 16, 0, 0);
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
InstancingAndOffsetsGame p = new InstancingAndOffsetsGame();
p.Run();
}
}
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,152 +0,0 @@
using MoonWorks;
using MoonWorks.Math.Float;
using MoonWorks.Graphics;
namespace MoonWorks.Test
{
class MSAAGame : Game
{
private GraphicsPipeline[] msaaPipelines = new GraphicsPipeline[4];
private GraphicsPipeline blitPipeline;
private Texture[] renderTargets = new Texture[4];
private Sampler rtSampler;
private Buffer quadVertexBuffer;
private Buffer quadIndexBuffer;
private SampleCount currentSampleCount = SampleCount.Four;
public MSAAGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{
Logger.LogInfo("Press Left and Right to cycle between sample counts");
Logger.LogInfo("Setting sample count to: " + currentSampleCount);
// Create the MSAA pipelines
ShaderModule triangleVertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("RawTriangle.vert"));
ShaderModule triangleFragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("SolidColor.frag"));
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
TextureFormat.R8G8B8A8,
triangleVertShaderModule,
triangleFragShaderModule
);
for (int i = 0; i < msaaPipelines.Length; i += 1)
{
pipelineCreateInfo.MultisampleState.MultisampleCount = (SampleCount) i;
msaaPipelines[i] = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
}
// Create the blit pipeline
ShaderModule blitVertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuad.vert"));
ShaderModule blitFragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuad.frag"));
pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
MainWindow.SwapchainFormat,
blitVertShaderModule,
blitFragShaderModule
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureVertex>();
pipelineCreateInfo.FragmentShaderInfo.SamplerBindingCount = 1;
blitPipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create the MSAA render textures
for (int i = 0; i < renderTargets.Length; i += 1)
{
renderTargets[i] = Texture.CreateTexture2D(
GraphicsDevice,
MainWindow.Width,
MainWindow.Height,
TextureFormat.R8G8B8A8,
TextureUsageFlags.ColorTarget | TextureUsageFlags.Sampler,
1,
(SampleCount) i
);
}
// Create the sampler
rtSampler = new Sampler(GraphicsDevice, SamplerCreateInfo.PointClamp);
// Create and populate the vertex and index buffers
quadVertexBuffer = Buffer.Create<PositionTextureVertex>(GraphicsDevice, BufferUsageFlags.Vertex, 4);
quadIndexBuffer = Buffer.Create<ushort>(GraphicsDevice, BufferUsageFlags.Index, 6);
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
cmdbuf.SetBufferData(
quadVertexBuffer,
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(
quadIndexBuffer,
new ushort[]
{
0, 1, 2,
0, 2, 3,
}
);
GraphicsDevice.Submit(cmdbuf);
}
protected override void Update(System.TimeSpan delta)
{
SampleCount prevSampleCount = currentSampleCount;
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Left))
{
currentSampleCount -= 1;
if (currentSampleCount < 0)
{
currentSampleCount = SampleCount.Eight;
}
}
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Right))
{
currentSampleCount += 1;
if (currentSampleCount > SampleCount.Eight)
{
currentSampleCount = SampleCount.One;
}
}
if (prevSampleCount != currentSampleCount)
{
Logger.LogInfo("Setting sample count to: " + currentSampleCount);
}
}
protected override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture? backbuffer = cmdbuf.AcquireSwapchainTexture(MainWindow);
if (backbuffer != null)
{
Texture rt = renderTargets[(int) currentSampleCount];
cmdbuf.BeginRenderPass(new ColorAttachmentInfo(rt, Color.Black));
cmdbuf.BindGraphicsPipeline(msaaPipelines[(int) currentSampleCount]);
cmdbuf.DrawPrimitives(0, 1, 0, 0);
cmdbuf.EndRenderPass();
cmdbuf.BeginRenderPass(new ColorAttachmentInfo(backbuffer, LoadOp.DontCare));
cmdbuf.BindGraphicsPipeline(blitPipeline);
cmdbuf.BindFragmentSamplers(new TextureSamplerBinding(rt, rtSampler));
cmdbuf.BindVertexBuffers(quadVertexBuffer);
cmdbuf.BindIndexBuffer(quadIndexBuffer, IndexElementSize.Sixteen);
cmdbuf.DrawIndexedPrimitives(0, 0, 2, 0, 0);
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
MSAAGame game = new MSAAGame();
game.Run();
}
}
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,223 +0,0 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Math.Float;
using MoonWorks.Math;
using System.Runtime.InteropServices;
namespace MoonWorks.Test
{
class MSAACubeGame : Game
{
private GraphicsPipeline[] msaaPipelines = new GraphicsPipeline[4];
private GraphicsPipeline cubemapPipeline;
private Texture[] renderTargets = new Texture[4];
private Buffer vertexBuffer;
private Buffer indexBuffer;
private Sampler sampler;
private Vector3 camPos = new Vector3(0, 0, 4f);
private SampleCount currentSampleCount = SampleCount.Four;
public MSAACubeGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{
Logger.LogInfo("Press Down to view the other side of the cubemap");
Logger.LogInfo("Press Left and Right to cycle between sample counts");
Logger.LogInfo("Setting sample count to: " + currentSampleCount);
// Create the MSAA pipelines
ShaderModule triangleVertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("RawTriangle.vert"));
ShaderModule triangleFragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("SolidColor.frag"));
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
TextureFormat.R8G8B8A8,
triangleVertShaderModule,
triangleFragShaderModule
);
for (int i = 0; i < msaaPipelines.Length; i += 1)
{
pipelineCreateInfo.MultisampleState.MultisampleCount = (SampleCount)i;
msaaPipelines[i] = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
}
// Create the cubemap pipeline
ShaderModule cubemapVertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("Skybox.vert"));
ShaderModule cubemapFragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("Skybox.frag"));
pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
MainWindow.SwapchainFormat,
cubemapVertShaderModule,
cubemapFragShaderModule
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionVertex>();
pipelineCreateInfo.VertexShaderInfo.UniformBufferSize = (uint)Marshal.SizeOf<TransformVertexUniform>();
pipelineCreateInfo.FragmentShaderInfo.SamplerBindingCount = 1;
cubemapPipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create the MSAA render targets
for (int i = 0; i < renderTargets.Length; i++)
{
TextureCreateInfo cubeCreateInfo = new TextureCreateInfo
{
Width = 16,
Height = 16,
Format = TextureFormat.R8G8B8A8,
Depth = 1,
LevelCount = 1,
SampleCount = (SampleCount)i,
UsageFlags = TextureUsageFlags.ColorTarget | TextureUsageFlags.Sampler,
IsCube = true
};
renderTargets[i] = new Texture(GraphicsDevice, cubeCreateInfo);
}
// Create samplers
sampler = new Sampler(GraphicsDevice, SamplerCreateInfo.PointClamp);
// Create and populate the GPU resources
vertexBuffer = Buffer.Create<PositionVertex>(GraphicsDevice, BufferUsageFlags.Vertex, 24);
indexBuffer = Buffer.Create<ushort>(GraphicsDevice, BufferUsageFlags.Index, 36);
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
cmdbuf.SetBufferData(
vertexBuffer,
new PositionVertex[]
{
new PositionVertex(new Vector3(-10, -10, -10)),
new PositionVertex(new Vector3(10, -10, -10)),
new PositionVertex(new Vector3(10, 10, -10)),
new PositionVertex(new Vector3(-10, 10, -10)),
new PositionVertex(new Vector3(-10, -10, 10)),
new PositionVertex(new Vector3(10, -10, 10)),
new PositionVertex(new Vector3(10, 10, 10)),
new PositionVertex(new Vector3(-10, 10, 10)),
new PositionVertex(new Vector3(-10, -10, -10)),
new PositionVertex(new Vector3(-10, 10, -10)),
new PositionVertex(new Vector3(-10, 10, 10)),
new PositionVertex(new Vector3(-10, -10, 10)),
new PositionVertex(new Vector3(10, -10, -10)),
new PositionVertex(new Vector3(10, 10, -10)),
new PositionVertex(new Vector3(10, 10, 10)),
new PositionVertex(new Vector3(10, -10, 10)),
new PositionVertex(new Vector3(-10, -10, -10)),
new PositionVertex(new Vector3(-10, -10, 10)),
new PositionVertex(new Vector3(10, -10, 10)),
new PositionVertex(new Vector3(10, -10, -10)),
new PositionVertex(new Vector3(-10, 10, -10)),
new PositionVertex(new Vector3(-10, 10, 10)),
new PositionVertex(new Vector3(10, 10, 10)),
new PositionVertex(new Vector3(10, 10, -10))
}
);
cmdbuf.SetBufferData(
indexBuffer,
new ushort[]
{
0, 1, 2, 0, 2, 3,
6, 5, 4, 7, 6, 4,
8, 9, 10, 8, 10, 11,
14, 13, 12, 15, 14, 12,
16, 17, 18, 16, 18, 19,
22, 21, 20, 23, 22, 20
}
);
GraphicsDevice.Submit(cmdbuf);
}
protected override void Update(System.TimeSpan delta)
{
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Bottom))
{
camPos.Z *= -1;
}
SampleCount prevSampleCount = currentSampleCount;
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Left))
{
currentSampleCount -= 1;
if (currentSampleCount < 0)
{
currentSampleCount = SampleCount.Eight;
}
}
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Right))
{
currentSampleCount += 1;
if (currentSampleCount > SampleCount.Eight)
{
currentSampleCount = SampleCount.One;
}
}
if (prevSampleCount != currentSampleCount)
{
Logger.LogInfo("Setting sample count to: " + currentSampleCount);
}
}
protected override void Draw(double alpha)
{
Matrix4x4 proj = Matrix4x4.CreatePerspectiveFieldOfView(
MathHelper.ToRadians(75f),
(float)MainWindow.Width / MainWindow.Height,
0.01f,
100f
);
Matrix4x4 view = Matrix4x4.CreateLookAt(
camPos,
Vector3.Zero,
Vector3.Up
);
TransformVertexUniform vertUniforms = new TransformVertexUniform(view * proj);
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture? backbuffer = cmdbuf.AcquireSwapchainTexture(MainWindow);
if (backbuffer != null)
{
// Get a reference to the RT for the given sample count
int rtIndex = (int) currentSampleCount;
Texture rt = renderTargets[rtIndex];
ColorAttachmentInfo rtAttachmentInfo = new ColorAttachmentInfo(
rt,
Color.Black
);
// Render a triangle to each slice of the cubemap
for (uint i = 0; i < 6; i += 1)
{
rtAttachmentInfo.Layer = i;
cmdbuf.BeginRenderPass(rtAttachmentInfo);
cmdbuf.BindGraphicsPipeline(msaaPipelines[rtIndex]);
cmdbuf.DrawPrimitives(0, 1, 0, 0);
cmdbuf.EndRenderPass();
}
cmdbuf.BeginRenderPass(new ColorAttachmentInfo(backbuffer, Color.Black));
cmdbuf.BindGraphicsPipeline(cubemapPipeline);
cmdbuf.BindVertexBuffers(vertexBuffer);
cmdbuf.BindIndexBuffer(indexBuffer, IndexElementSize.Sixteen);
cmdbuf.BindFragmentSamplers(new TextureSamplerBinding(rt, sampler));
uint vertexUniformOffset = cmdbuf.PushVertexShaderUniforms(vertUniforms);
cmdbuf.DrawIndexedPrimitives(0, 0, 12, vertexUniformOffset, 0);
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
MSAACubeGame game = new MSAACubeGame();
game.Run();
}
}
}

View File

@ -1,23 +0,0 @@
#version 450
#define LOCAL_SIZE 8
layout (local_size_x = LOCAL_SIZE, local_size_y = LOCAL_SIZE, local_size_z = 1) in;
layout (set = 1, binding = 0, rgba8) uniform writeonly image2D outImage;
layout(set = 2, binding = 0) uniform UBO
{
uvec2 workgroupSize;
} ubo;
void main()
{
vec2 coord = gl_GlobalInvocationID.xy;
vec2 totalWorkgroupSize = vec2(ubo.workgroupSize) * vec2(LOCAL_SIZE);
vec4 col = vec4(
coord.x / totalWorkgroupSize.x,
coord.y / totalWorkgroupSize.y,
1.0,
1.0
);
imageStore(outImage, ivec2(coord), col);
}

View File

@ -1,22 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>library</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Content Include="..\MoonWorks.Test.Common\Content\**\*.*">
<Link>Content\%(RecursiveDir)%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<Import Project=".\CopyMoonlibs.targets" />
</Project>

View File

@ -1,135 +0,0 @@
using MoonWorks.Graphics;
namespace MoonWorks.Test
{
public static class TestUtils
{
public static WindowCreateInfo GetStandardWindowCreateInfo()
{
return new WindowCreateInfo(
"Main Window",
640,
480,
ScreenMode.Windowed,
PresentMode.FIFO
);
}
public static FrameLimiterSettings GetStandardFrameLimiterSettings()
{
return new FrameLimiterSettings(
FrameLimiterMode.Capped,
60
);
}
public static GraphicsPipelineCreateInfo GetStandardGraphicsPipelineCreateInfo(
TextureFormat swapchainFormat,
ShaderModule vertShaderModule,
ShaderModule fragShaderModule
) {
return new GraphicsPipelineCreateInfo
{
AttachmentInfo = new GraphicsPipelineAttachmentInfo(
new ColorAttachmentDescription(
swapchainFormat,
ColorAttachmentBlendState.Opaque
)
),
DepthStencilState = DepthStencilState.Disable,
MultisampleState = MultisampleState.None,
PrimitiveType = PrimitiveType.TriangleList,
RasterizerState = RasterizerState.CCW_CullNone,
VertexInputState = VertexInputState.Empty,
VertexShaderInfo = GraphicsShaderInfo.Create(vertShaderModule, "main", 0),
FragmentShaderInfo = GraphicsShaderInfo.Create(fragShaderModule, "main", 0)
};
}
public static string GetShaderPath(string shaderName)
{
return SDL2.SDL.SDL_GetBasePath() + "Content/Shaders/Compiled/" + shaderName + ".refresh";
}
public static string GetTexturePath(string textureName)
{
return SDL2.SDL.SDL_GetBasePath() + "Content/Textures/" + textureName;
}
public static string GetVideoPath(string videoName)
{
return SDL2.SDL.SDL_GetBasePath() + "Content/Videos/" + videoName;
}
public enum ButtonType
{
Left, // A/left arrow on keyboard, left face button on gamepad
Bottom, // S/down arrow on keyboard, bottom face button on gamepad
Right // D/right arrow on keyboard, right face button on gamepad
}
public static bool CheckButtonPressed(Input.Inputs inputs, ButtonType buttonType)
{
bool pressed = false;
if (buttonType == ButtonType.Left)
{
pressed = (
(inputs.GamepadExists(0) && inputs.GetGamepad(0).DpadLeft.IsPressed) ||
inputs.Keyboard.IsPressed(Input.KeyCode.A) ||
inputs.Keyboard.IsPressed(Input.KeyCode.Left)
);
}
else if (buttonType == ButtonType.Bottom)
{
pressed = (
(inputs.GamepadExists(0) && inputs.GetGamepad(0).DpadDown.IsPressed) ||
inputs.Keyboard.IsPressed(Input.KeyCode.S) ||
inputs.Keyboard.IsPressed(Input.KeyCode.Down)
);
}
else if (buttonType == ButtonType.Right)
{
pressed = (
(inputs.GamepadExists(0) && inputs.GetGamepad(0).DpadRight.IsPressed) ||
inputs.Keyboard.IsPressed(Input.KeyCode.D) ||
inputs.Keyboard.IsPressed(Input.KeyCode.Right)
);
}
return pressed;
}
public static bool CheckButtonDown(Input.Inputs inputs, ButtonType buttonType)
{
bool down = false;
if (buttonType == ButtonType.Left)
{
down = (
(inputs.GamepadExists(0) && inputs.GetGamepad(0).DpadLeft.IsDown) ||
inputs.Keyboard.IsDown(Input.KeyCode.A) ||
inputs.Keyboard.IsDown(Input.KeyCode.Left)
);
}
else if (buttonType == ButtonType.Bottom)
{
down = (
(inputs.GamepadExists(0) && inputs.GetGamepad(0).DpadDown.IsDown) ||
inputs.Keyboard.IsDown(Input.KeyCode.S) ||
inputs.Keyboard.IsDown(Input.KeyCode.Down)
);
}
else if (buttonType == ButtonType.Right)
{
down = (
(inputs.GamepadExists(0) && inputs.GetGamepad(0).DpadRight.IsDown) ||
inputs.Keyboard.IsDown(Input.KeyCode.D) ||
inputs.Keyboard.IsDown(Input.KeyCode.Right)
);
}
return down;
}
}
}

View File

@ -1,14 +0,0 @@
using MoonWorks.Math.Float;
namespace MoonWorks.Test
{
public struct TransformVertexUniform
{
public Matrix4x4 ViewProjection;
public TransformVertexUniform(Matrix4x4 viewProjection)
{
ViewProjection = viewProjection;
}
}
}

View File

@ -1,75 +0,0 @@
using System.Runtime.InteropServices;
using MoonWorks.Graphics;
using MoonWorks.Math.Float;
namespace MoonWorks.Test
{
[StructLayout(LayoutKind.Sequential)]
public struct PositionVertex : IVertexType
{
public Vector3 Position;
public PositionVertex(Vector3 position)
{
Position = position;
}
public static VertexElementFormat[] Formats { get; } = new VertexElementFormat[1]
{
VertexElementFormat.Vector3
};
public override string ToString()
{
return Position.ToString();
}
}
[StructLayout(LayoutKind.Sequential)]
public struct PositionColorVertex : IVertexType
{
public Vector3 Position;
public Color Color;
public PositionColorVertex(Vector3 position, Color color)
{
Position = position;
Color = color;
}
public static VertexElementFormat[] Formats { get; } = new VertexElementFormat[2]
{
VertexElementFormat.Vector3,
VertexElementFormat.Color
};
public override string ToString()
{
return Position + " | " + Color;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct PositionTextureVertex : IVertexType
{
public Vector3 Position;
public Vector2 TexCoord;
public PositionTextureVertex(Vector3 position, Vector2 texCoord)
{
Position = position;
TexCoord = texCoord;
}
public static VertexElementFormat[] Formats { get; } = new VertexElementFormat[2]
{
VertexElementFormat.Vector3,
VertexElementFormat.Vector2
};
public override string ToString()
{
return Position + " | " + TexCoord;
}
}
}

View File

@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Content Include="Common\Content\**\*.*">
<Link>Content\%(RecursiveDir)%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MoonWorks\MoonWorks.csproj" />
</ItemGroup>
<Import Project=".\CopyMoonlibs.targets" />
</Project>

View File

@ -3,67 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30717.126
MinimumVisualStudioVersion = 15.0.26124.0
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BasicTriangle", "BasicTriangle\BasicTriangle.csproj", "{595FE5AC-8699-494D-816A-89A2DE3786FB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScreen", "ClearScreen\ClearScreen.csproj", "{C9B46D3A-1FA4-426E-BF84-F068FD6E0CC4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClearScreen_MultiWindow", "ClearScreen_MultiWindow\ClearScreen_MultiWindow.csproj", "{3EB54E8A-3C4E-4EE2-9DD2-6D345A92319A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CullFace", "CullFace\CullFace.csproj", "{6567E2AD-189C-4994-9A27-72FB57546B8A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MoonWorks.Test.Common", "MoonWorks.Test.Common\MoonWorks.Test.Common.csproj", "{550D1B95-B475-4EF8-A235-626505D7710F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MSAA", "MSAA\MSAA.csproj", "{970D18B0-0D05-4360-8208-41A2769C647E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TexturedAnimatedQuad", "TexturedAnimatedQuad\TexturedAnimatedQuad.csproj", "{B9DE9133-9C1C-4592-927A-D3485CB493A2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TexturedQuad", "TexturedQuad\TexturedQuad.csproj", "{22173AEA-9E5A-4DA8-B943-DEC1EA67232F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TriangleVertexBuffer", "TriangleVertexBuffer\TriangleVertexBuffer.csproj", "{7EC935B1-DCD1-4ADD-96C8-614B4CA76501}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GetBufferData", "GetBufferData\GetBufferData.csproj", "{37BDB4E6-FCDC-4F04-A9E3-C6B9D6C3AB4E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MoonWorks", "..\MoonWorks\MoonWorks.csproj", "{1695B1D8-4935-490C-A5EC-E2F2AA94B150}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cube", "Cube\Cube.csproj", "{C3808AFD-23DD-4622-BFA7-981A344D0C19}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BasicCompute", "BasicCompute\BasicCompute.csproj", "{68D47057-BBCB-4F86-9C0A-D6D730B18D9E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComputeUniforms", "ComputeUniforms\ComputeUniforms.csproj", "{5F8BBD49-6C39-4186-A4A3-91D6662D3ABD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DrawIndirect", "DrawIndirect\DrawIndirect.csproj", "{CA6E0ACF-3698-452F-B71F-51286EB5E1B2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CompressedTextures", "CompressedTextures\CompressedTextures.csproj", "{E90D236C-BD0F-4420-ADD0-867D21F4DCA5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CopyTexture", "CopyTexture\CopyTexture.csproj", "{CF25A5A2-A0BD-4C9B-BB07-19CCD97C1C4E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VideoPlayer", "VideoPlayer\VideoPlayer.csproj", "{FCD63849-9D3C-4D48-A8BD-39671096F03A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Texture3D", "Texture3D\Texture3D.csproj", "{9D0F0573-7FD4-4480-8F9B-CDD52120A170}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InstancingAndOffsets", "InstancingAndOffsets\InstancingAndOffsets.csproj", "{5CDA8D41-F96C-4DE7-AD53-5A76C4C0CC31}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VertexSampler", "VertexSampler\VertexSampler.csproj", "{C525B6DE-3003-45D5-BB83-89679B108C08}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RenderTexture3D", "RenderTexture3D\RenderTexture3D.csproj", "{6D625A4C-8618-4DFC-A6AD-AA3BE3488D70}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RenderTextureCube", "RenderTextureCube\RenderTextureCube.csproj", "{D7A8452F-123F-4965-8716-9E39F677A831}"
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
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BasicStencil", "BasicStencil\BasicStencil.csproj", "{1B370BAD-966A-49B2-9EA0-2463F6C8F9AD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DepthMSAA", "DepthMSAA\DepthMSAA.csproj", "{B36C9F65-F3F4-4EB4-8EBF-A1EDCD4261F8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WindowResizing", "WindowResizing\WindowResizing.csproj", "{AF5F2804-663D-4C46-BD02-AB178002180B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StoreLoad", "StoreLoad\StoreLoad.csproj", "{CD31F1B5-C76A-428A-A812-8DFD6CAB20A9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RenderTexture2D", "RenderTexture2D\RenderTexture2D.csproj", "{F9C9E15D-1000-46DA-BA39-1D4C0D43F023}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MSAACube", "MSAACube\MSAACube.csproj", "{A1568AAF-DD02-4A6E-9C68-9AE07130A60D}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MoonWorksGraphicsTests", "MoonWorksGraphicsTests.csproj", "{8AA61DD7-07CE-45B7-BD1A-52AA0D4DDC92}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -71,130 +13,14 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{595FE5AC-8699-494D-816A-89A2DE3786FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{595FE5AC-8699-494D-816A-89A2DE3786FB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{595FE5AC-8699-494D-816A-89A2DE3786FB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{595FE5AC-8699-494D-816A-89A2DE3786FB}.Release|Any CPU.Build.0 = Release|Any CPU
{C9B46D3A-1FA4-426E-BF84-F068FD6E0CC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C9B46D3A-1FA4-426E-BF84-F068FD6E0CC4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C9B46D3A-1FA4-426E-BF84-F068FD6E0CC4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C9B46D3A-1FA4-426E-BF84-F068FD6E0CC4}.Release|Any CPU.Build.0 = Release|Any CPU
{3EB54E8A-3C4E-4EE2-9DD2-6D345A92319A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3EB54E8A-3C4E-4EE2-9DD2-6D345A92319A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3EB54E8A-3C4E-4EE2-9DD2-6D345A92319A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3EB54E8A-3C4E-4EE2-9DD2-6D345A92319A}.Release|Any CPU.Build.0 = Release|Any CPU
{6567E2AD-189C-4994-9A27-72FB57546B8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6567E2AD-189C-4994-9A27-72FB57546B8A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6567E2AD-189C-4994-9A27-72FB57546B8A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6567E2AD-189C-4994-9A27-72FB57546B8A}.Release|Any CPU.Build.0 = Release|Any CPU
{550D1B95-B475-4EF8-A235-626505D7710F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{550D1B95-B475-4EF8-A235-626505D7710F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{550D1B95-B475-4EF8-A235-626505D7710F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{550D1B95-B475-4EF8-A235-626505D7710F}.Release|Any CPU.Build.0 = Release|Any CPU
{970D18B0-0D05-4360-8208-41A2769C647E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{970D18B0-0D05-4360-8208-41A2769C647E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{970D18B0-0D05-4360-8208-41A2769C647E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{970D18B0-0D05-4360-8208-41A2769C647E}.Release|Any CPU.Build.0 = Release|Any CPU
{B9DE9133-9C1C-4592-927A-D3485CB493A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B9DE9133-9C1C-4592-927A-D3485CB493A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B9DE9133-9C1C-4592-927A-D3485CB493A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B9DE9133-9C1C-4592-927A-D3485CB493A2}.Release|Any CPU.Build.0 = Release|Any CPU
{22173AEA-9E5A-4DA8-B943-DEC1EA67232F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{22173AEA-9E5A-4DA8-B943-DEC1EA67232F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{22173AEA-9E5A-4DA8-B943-DEC1EA67232F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{22173AEA-9E5A-4DA8-B943-DEC1EA67232F}.Release|Any CPU.Build.0 = Release|Any CPU
{7EC935B1-DCD1-4ADD-96C8-614B4CA76501}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7EC935B1-DCD1-4ADD-96C8-614B4CA76501}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7EC935B1-DCD1-4ADD-96C8-614B4CA76501}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7EC935B1-DCD1-4ADD-96C8-614B4CA76501}.Release|Any CPU.Build.0 = Release|Any CPU
{37BDB4E6-FCDC-4F04-A9E3-C6B9D6C3AB4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{37BDB4E6-FCDC-4F04-A9E3-C6B9D6C3AB4E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{37BDB4E6-FCDC-4F04-A9E3-C6B9D6C3AB4E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{37BDB4E6-FCDC-4F04-A9E3-C6B9D6C3AB4E}.Release|Any CPU.Build.0 = Release|Any CPU
{1695B1D8-4935-490C-A5EC-E2F2AA94B150}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1695B1D8-4935-490C-A5EC-E2F2AA94B150}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1695B1D8-4935-490C-A5EC-E2F2AA94B150}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1695B1D8-4935-490C-A5EC-E2F2AA94B150}.Release|Any CPU.Build.0 = Release|Any CPU
{C3808AFD-23DD-4622-BFA7-981A344D0C19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C3808AFD-23DD-4622-BFA7-981A344D0C19}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C3808AFD-23DD-4622-BFA7-981A344D0C19}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C3808AFD-23DD-4622-BFA7-981A344D0C19}.Release|Any CPU.Build.0 = Release|Any CPU
{68D47057-BBCB-4F86-9C0A-D6D730B18D9E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{68D47057-BBCB-4F86-9C0A-D6D730B18D9E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{68D47057-BBCB-4F86-9C0A-D6D730B18D9E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{68D47057-BBCB-4F86-9C0A-D6D730B18D9E}.Release|Any CPU.Build.0 = Release|Any CPU
{5F8BBD49-6C39-4186-A4A3-91D6662D3ABD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5F8BBD49-6C39-4186-A4A3-91D6662D3ABD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5F8BBD49-6C39-4186-A4A3-91D6662D3ABD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5F8BBD49-6C39-4186-A4A3-91D6662D3ABD}.Release|Any CPU.Build.0 = Release|Any CPU
{CA6E0ACF-3698-452F-B71F-51286EB5E1B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CA6E0ACF-3698-452F-B71F-51286EB5E1B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CA6E0ACF-3698-452F-B71F-51286EB5E1B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CA6E0ACF-3698-452F-B71F-51286EB5E1B2}.Release|Any CPU.Build.0 = Release|Any CPU
{E90D236C-BD0F-4420-ADD0-867D21F4DCA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E90D236C-BD0F-4420-ADD0-867D21F4DCA5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E90D236C-BD0F-4420-ADD0-867D21F4DCA5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E90D236C-BD0F-4420-ADD0-867D21F4DCA5}.Release|Any CPU.Build.0 = Release|Any CPU
{CF25A5A2-A0BD-4C9B-BB07-19CCD97C1C4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CF25A5A2-A0BD-4C9B-BB07-19CCD97C1C4E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CF25A5A2-A0BD-4C9B-BB07-19CCD97C1C4E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CF25A5A2-A0BD-4C9B-BB07-19CCD97C1C4E}.Release|Any CPU.Build.0 = Release|Any CPU
{FCD63849-9D3C-4D48-A8BD-39671096F03A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FCD63849-9D3C-4D48-A8BD-39671096F03A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FCD63849-9D3C-4D48-A8BD-39671096F03A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FCD63849-9D3C-4D48-A8BD-39671096F03A}.Release|Any CPU.Build.0 = Release|Any CPU
{9D0F0573-7FD4-4480-8F9B-CDD52120A170}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9D0F0573-7FD4-4480-8F9B-CDD52120A170}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9D0F0573-7FD4-4480-8F9B-CDD52120A170}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9D0F0573-7FD4-4480-8F9B-CDD52120A170}.Release|Any CPU.Build.0 = Release|Any CPU
{5CDA8D41-F96C-4DE7-AD53-5A76C4C0CC31}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5CDA8D41-F96C-4DE7-AD53-5A76C4C0CC31}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5CDA8D41-F96C-4DE7-AD53-5A76C4C0CC31}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5CDA8D41-F96C-4DE7-AD53-5A76C4C0CC31}.Release|Any CPU.Build.0 = Release|Any CPU
{C525B6DE-3003-45D5-BB83-89679B108C08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C525B6DE-3003-45D5-BB83-89679B108C08}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C525B6DE-3003-45D5-BB83-89679B108C08}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C525B6DE-3003-45D5-BB83-89679B108C08}.Release|Any CPU.Build.0 = Release|Any CPU
{6D625A4C-8618-4DFC-A6AD-AA3BE3488D70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6D625A4C-8618-4DFC-A6AD-AA3BE3488D70}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6D625A4C-8618-4DFC-A6AD-AA3BE3488D70}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6D625A4C-8618-4DFC-A6AD-AA3BE3488D70}.Release|Any CPU.Build.0 = Release|Any CPU
{D7A8452F-123F-4965-8716-9E39F677A831}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D7A8452F-123F-4965-8716-9E39F677A831}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D7A8452F-123F-4965-8716-9E39F677A831}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D7A8452F-123F-4965-8716-9E39F677A831}.Release|Any CPU.Build.0 = Release|Any CPU
{2219C628-5593-4C23-86CB-0E1E96EBD6C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2219C628-5593-4C23-86CB-0E1E96EBD6C5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2219C628-5593-4C23-86CB-0E1E96EBD6C5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2219C628-5593-4C23-86CB-0E1E96EBD6C5}.Release|Any CPU.Build.0 = Release|Any CPU
{5A1AC35B-EF18-426D-A633-D4899E84EAA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5A1AC35B-EF18-426D-A633-D4899E84EAA7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5A1AC35B-EF18-426D-A633-D4899E84EAA7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5A1AC35B-EF18-426D-A633-D4899E84EAA7}.Release|Any CPU.Build.0 = Release|Any CPU
{1B370BAD-966A-49B2-9EA0-2463F6C8F9AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1B370BAD-966A-49B2-9EA0-2463F6C8F9AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1B370BAD-966A-49B2-9EA0-2463F6C8F9AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1B370BAD-966A-49B2-9EA0-2463F6C8F9AD}.Release|Any CPU.Build.0 = Release|Any CPU
{B36C9F65-F3F4-4EB4-8EBF-A1EDCD4261F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B36C9F65-F3F4-4EB4-8EBF-A1EDCD4261F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B36C9F65-F3F4-4EB4-8EBF-A1EDCD4261F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B36C9F65-F3F4-4EB4-8EBF-A1EDCD4261F8}.Release|Any CPU.Build.0 = Release|Any CPU
{AF5F2804-663D-4C46-BD02-AB178002180B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AF5F2804-663D-4C46-BD02-AB178002180B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AF5F2804-663D-4C46-BD02-AB178002180B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AF5F2804-663D-4C46-BD02-AB178002180B}.Release|Any CPU.Build.0 = Release|Any CPU
{CD31F1B5-C76A-428A-A812-8DFD6CAB20A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CD31F1B5-C76A-428A-A812-8DFD6CAB20A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CD31F1B5-C76A-428A-A812-8DFD6CAB20A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CD31F1B5-C76A-428A-A812-8DFD6CAB20A9}.Release|Any CPU.Build.0 = Release|Any CPU
{F9C9E15D-1000-46DA-BA39-1D4C0D43F023}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F9C9E15D-1000-46DA-BA39-1D4C0D43F023}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F9C9E15D-1000-46DA-BA39-1D4C0D43F023}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F9C9E15D-1000-46DA-BA39-1D4C0D43F023}.Release|Any CPU.Build.0 = Release|Any CPU
{A1568AAF-DD02-4A6E-9C68-9AE07130A60D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A1568AAF-DD02-4A6E-9C68-9AE07130A60D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A1568AAF-DD02-4A6E-9C68-9AE07130A60D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A1568AAF-DD02-4A6E-9C68-9AE07130A60D}.Release|Any CPU.Build.0 = Release|Any CPU
{8AA61DD7-07CE-45B7-BD1A-52AA0D4DDC92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8AA61DD7-07CE-45B7-BD1A-52AA0D4DDC92}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8AA61DD7-07CE-45B7-BD1A-52AA0D4DDC92}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8AA61DD7-07CE-45B7-BD1A-52AA0D4DDC92}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

133
Program.cs Normal file
View File

@ -0,0 +1,133 @@
using System;
using MoonWorks;
using MoonWorks.Graphics;
namespace MoonWorksGraphicsTests;
class Program : Game
{
Example[] Examples =
[
new ClearScreenExample(),
new ClearScreen_MultiWindowExample(),
new BasicStencilExample(),
new BasicTriangleExample(),
new CompressedTexturesExample(),
new BasicComputeExample(),
new ComputeUniformsExample(),
new CopyTextureExample(),
new CubeExample(),
new CullFaceExample(),
new DepthMSAAExample(),
new DrawIndirectExample(),
new GetBufferDataExample(),
new InstancingAndOffsetsExample(),
new MSAACubeExample(),
new MSAAExample(),
new RenderTexture2DArrayExample(),
new RenderTexture2DExample(),
new RenderTextureCubeExample(),
new RenderTextureMipmapsExample(),
new StoreLoadExample(),
new Texture3DCopyExample(),
new Texture3DExample(),
new TexturedAnimatedQuadExample(),
new TexturedQuadExample(),
new TextureMipmapsExample(),
new TriangleVertexBufferExample(),
new VertexSamplerExample(),
new VideoPlayerExample(),
new WindowResizingExample(),
new ComputeSpriteBatchExample()
];
int ExampleIndex = 0;
public Program(
WindowCreateInfo windowCreateInfo,
FrameLimiterSettings frameLimiterSettings,
BackendFlags preferredBackends,
int targetTimestep = 60,
bool debugMode = false
) : base(
windowCreateInfo,
SwapchainComposition.SDR,
PresentMode.VSync,
frameLimiterSettings,
preferredBackends,
targetTimestep,
debugMode
) {
Logger.LogInfo("Welcome to the MoonWorks Graphics Tests program! Press Q and E to cycle through examples!");
Examples[ExampleIndex].Init(MainWindow, GraphicsDevice, Inputs);
}
protected override void Update(TimeSpan delta)
{
if (Inputs.Keyboard.IsPressed(MoonWorks.Input.KeyCode.Q))
{
Examples[ExampleIndex].Destroy();
ExampleIndex -= 1;
if (ExampleIndex < 0)
{
ExampleIndex = Examples.Length - 1;
}
Examples[ExampleIndex].Init(MainWindow, GraphicsDevice, Inputs);
}
else if (Inputs.Keyboard.IsPressed(MoonWorks.Input.KeyCode.E))
{
Examples[ExampleIndex].Destroy();
ExampleIndex = (ExampleIndex + 1) % Examples.Length;
Examples[ExampleIndex].Init(MainWindow, GraphicsDevice, Inputs);
}
else
{
Examples[ExampleIndex].Update(delta);
}
}
protected override void Draw(double alpha)
{
Examples[ExampleIndex].Draw(alpha);
}
protected override void Destroy()
{
Examples[ExampleIndex].Destroy();
}
static void Main(string[] args)
{
var debugMode = false;
#if DEBUG
debugMode = true;
#endif
var windowCreateInfo = new WindowCreateInfo(
"MoonWorksGraphicsTests",
640,
480,
ScreenMode.Windowed
);
var frameLimiterSettings = new FrameLimiterSettings(
FrameLimiterMode.Capped,
60
);
var game = new Program(
windowCreateInfo,
frameLimiterSettings,
BackendFlags.Vulkan | BackendFlags.D3D11 | BackendFlags.Metal,
60,
debugMode
);
game.Run();
}
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,131 +0,0 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Math.Float;
namespace MoonWorks.Test
{
class RenderTexture2DGame : Game
{
private GraphicsPipeline pipeline;
private Buffer vertexBuffer;
private Buffer indexBuffer;
private Texture[] textures = new Texture[4];
private Sampler sampler;
public RenderTexture2DGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{
// Load the shaders
ShaderModule vertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuad.vert"));
ShaderModule fragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuad.frag"));
// Create the graphics pipeline
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
MainWindow.SwapchainFormat,
vertShaderModule,
fragShaderModule
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureVertex>();
pipelineCreateInfo.VertexShaderInfo = GraphicsShaderInfo.Create(vertShaderModule, "main", 0);
pipelineCreateInfo.FragmentShaderInfo.SamplerBindingCount = 1;
pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create sampler
SamplerCreateInfo samplerCreateInfo = SamplerCreateInfo.PointClamp;
sampler = new Sampler(GraphicsDevice, samplerCreateInfo);
// Create and populate the GPU resources
vertexBuffer = Buffer.Create<PositionTextureVertex>(GraphicsDevice, BufferUsageFlags.Vertex, 16);
indexBuffer = Buffer.Create<ushort>(GraphicsDevice, BufferUsageFlags.Index, 6);
for (int i = 0; i < textures.Length; i += 1)
{
textures[i] = Texture.CreateTexture2D(
GraphicsDevice,
MainWindow.Width / 4,
MainWindow.Height / 4,
TextureFormat.R8G8B8A8,
TextureUsageFlags.ColorTarget | TextureUsageFlags.Sampler
);
}
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
cmdbuf.SetBufferData(
vertexBuffer,
new PositionTextureVertex[]
{
new PositionTextureVertex(new Vector3(-1, -1, 0), new Vector2(0, 0)),
new PositionTextureVertex(new Vector3(0, -1, 0), new Vector2(1, 0)),
new PositionTextureVertex(new Vector3(0, 0, 0), new Vector2(1, 1)),
new PositionTextureVertex(new Vector3(-1, 0, 0), new Vector2(0, 1)),
new PositionTextureVertex(new Vector3(0, -1, 0), new Vector2(0, 0)),
new PositionTextureVertex(new Vector3(1, -1, 0), new Vector2(1, 0)),
new PositionTextureVertex(new Vector3(1, 0, 0), new Vector2(1, 1)),
new PositionTextureVertex(new Vector3(0, 0, 0), new Vector2(0, 1)),
new PositionTextureVertex(new Vector3(-1, 0, 0), new Vector2(0, 0)),
new PositionTextureVertex(new Vector3(0, 0, 0), new Vector2(1, 0)),
new PositionTextureVertex(new Vector3(0, 1, 0), new Vector2(1, 1)),
new PositionTextureVertex(new Vector3(-1, 1, 0), new Vector2(0, 1)),
new PositionTextureVertex(new Vector3(0, 0, 0), new Vector2(0, 0)),
new PositionTextureVertex(new Vector3(1, 0, 0), new Vector2(1, 0)),
new PositionTextureVertex(new Vector3(1, 1, 0), new Vector2(1, 1)),
new PositionTextureVertex(new Vector3(0, 1, 0), new Vector2(0, 1)),
}
);
cmdbuf.SetBufferData(
indexBuffer,
new ushort[]
{
0, 1, 2,
0, 2, 3,
}
);
GraphicsDevice.Submit(cmdbuf);
}
protected override void Update(System.TimeSpan delta) { }
protected override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture? backbuffer = cmdbuf.AcquireSwapchainTexture(MainWindow);
if (backbuffer != null)
{
cmdbuf.BeginRenderPass(new ColorAttachmentInfo(textures[0], Color.Red));
cmdbuf.EndRenderPass();
cmdbuf.BeginRenderPass(new ColorAttachmentInfo(textures[1], Color.Blue));
cmdbuf.EndRenderPass();
cmdbuf.BeginRenderPass(new ColorAttachmentInfo(textures[2], Color.Green));
cmdbuf.EndRenderPass();
cmdbuf.BeginRenderPass(new ColorAttachmentInfo(textures[3], Color.Yellow));
cmdbuf.EndRenderPass();
cmdbuf.BeginRenderPass(new ColorAttachmentInfo(backbuffer, Color.Black));
cmdbuf.BindGraphicsPipeline(pipeline);
cmdbuf.BindVertexBuffers(vertexBuffer);
cmdbuf.BindIndexBuffer(indexBuffer, IndexElementSize.Sixteen);
for (uint i = 0; i < textures.Length; i += 1)
{
cmdbuf.BindFragmentSamplers(new TextureSamplerBinding(textures[i], sampler));
cmdbuf.DrawIndexedPrimitives(4 * i, 0, 2, 0, 0);
}
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
RenderTexture2DGame game = new RenderTexture2DGame();
game.Run();
}
}
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,134 +0,0 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Math.Float;
using RefreshCS;
namespace MoonWorks.Test
{
class RenderTexture3DGame : Game
{
private GraphicsPipeline pipeline;
private Buffer vertexBuffer;
private Buffer indexBuffer;
private Texture rt;
private Sampler sampler;
private float t;
private Color[] colors = new Color[]
{
Color.Red,
Color.Green,
Color.Blue,
};
struct FragUniform
{
public float Depth;
public FragUniform(float depth)
{
Depth = depth;
}
}
public RenderTexture3DGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{
// Load the shaders
ShaderModule vertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuad.vert"));
ShaderModule fragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuad3D.frag"));
// Create the graphics pipeline
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
MainWindow.SwapchainFormat,
vertShaderModule,
fragShaderModule
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureVertex>();
pipelineCreateInfo.FragmentShaderInfo = GraphicsShaderInfo.Create<FragUniform>(fragShaderModule, "main", 1);
pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create samplers
sampler = new Sampler(GraphicsDevice, SamplerCreateInfo.LinearWrap);
// Create and populate the GPU resources
vertexBuffer = Buffer.Create<PositionTextureVertex>(GraphicsDevice, BufferUsageFlags.Vertex, 4);
indexBuffer = Buffer.Create<ushort>(GraphicsDevice, BufferUsageFlags.Index, 6);
rt = Texture.CreateTexture3D(
GraphicsDevice,
16,
16,
(uint) colors.Length,
TextureFormat.R8G8B8A8,
TextureUsageFlags.ColorTarget | TextureUsageFlags.Sampler
);
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,
}
);
// Clear each depth slice of the RT to a different color
for (uint i = 0; i < colors.Length; i += 1)
{
ColorAttachmentInfo attachmentInfo = new ColorAttachmentInfo
{
Texture = rt,
ClearColor = colors[i],
Depth = i,
Layer = 0,
Level = 0,
LoadOp = LoadOp.Clear,
StoreOp = StoreOp.Store
};
cmdbuf.BeginRenderPass(attachmentInfo);
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
protected override void Update(System.TimeSpan delta) { }
protected override void Draw(double alpha)
{
t += 0.01f;
FragUniform fragUniform = new FragUniform(t);
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(rt, sampler));
uint fragParamOffset = cmdbuf.PushFragmentShaderUniforms(fragUniform);
cmdbuf.DrawIndexedPrimitives(0, 0, 2, 0, fragParamOffset);
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
RenderTexture3DGame game = new RenderTexture3DGame();
game.Run();
}
}
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,176 +0,0 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Math.Float;
using MoonWorks.Math;
using System.Runtime.InteropServices;
namespace MoonWorks.Test
{
class RenderTextureCubeGame : Game
{
private GraphicsPipeline pipeline;
private Buffer vertexBuffer;
private Buffer indexBuffer;
private Texture cubemap;
private Sampler sampler;
private Vector3 camPos = new Vector3(0, 0, 4f);
private Color[] colors = new Color[]
{
Color.Red,
Color.Green,
Color.Blue,
Color.Orange,
Color.Yellow,
Color.Purple,
};
public RenderTextureCubeGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{
Logger.LogInfo("Press Down to view the other side of the cubemap");
// Load the shaders
ShaderModule vertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("Skybox.vert"));
ShaderModule fragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("Skybox.frag"));
// Create the graphics pipeline
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
MainWindow.SwapchainFormat,
vertShaderModule,
fragShaderModule
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionVertex>();
pipelineCreateInfo.VertexShaderInfo.UniformBufferSize = (uint) Marshal.SizeOf<TransformVertexUniform>();
pipelineCreateInfo.FragmentShaderInfo.SamplerBindingCount = 1;
pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create samplers
sampler = new Sampler(GraphicsDevice, SamplerCreateInfo.PointClamp);
// Create and populate the GPU resources
vertexBuffer = Buffer.Create<PositionVertex>(GraphicsDevice, BufferUsageFlags.Vertex, 24);
indexBuffer = Buffer.Create<ushort>(GraphicsDevice, BufferUsageFlags.Index, 36);
cubemap = Texture.CreateTextureCube(
GraphicsDevice,
16,
TextureFormat.R8G8B8A8,
TextureUsageFlags.ColorTarget | TextureUsageFlags.Sampler
);
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
cmdbuf.SetBufferData(
vertexBuffer,
new PositionVertex[]
{
new PositionVertex(new Vector3(-10, -10, -10)),
new PositionVertex(new Vector3(10, -10, -10)),
new PositionVertex(new Vector3(10, 10, -10)),
new PositionVertex(new Vector3(-10, 10, -10)),
new PositionVertex(new Vector3(-10, -10, 10)),
new PositionVertex(new Vector3(10, -10, 10)),
new PositionVertex(new Vector3(10, 10, 10)),
new PositionVertex(new Vector3(-10, 10, 10)),
new PositionVertex(new Vector3(-10, -10, -10)),
new PositionVertex(new Vector3(-10, 10, -10)),
new PositionVertex(new Vector3(-10, 10, 10)),
new PositionVertex(new Vector3(-10, -10, 10)),
new PositionVertex(new Vector3(10, -10, -10)),
new PositionVertex(new Vector3(10, 10, -10)),
new PositionVertex(new Vector3(10, 10, 10)),
new PositionVertex(new Vector3(10, -10, 10)),
new PositionVertex(new Vector3(-10, -10, -10)),
new PositionVertex(new Vector3(-10, -10, 10)),
new PositionVertex(new Vector3(10, -10, 10)),
new PositionVertex(new Vector3(10, -10, -10)),
new PositionVertex(new Vector3(-10, 10, -10)),
new PositionVertex(new Vector3(-10, 10, 10)),
new PositionVertex(new Vector3(10, 10, 10)),
new PositionVertex(new Vector3(10, 10, -10))
}
);
cmdbuf.SetBufferData(
indexBuffer,
new ushort[]
{
0, 1, 2, 0, 2, 3,
6, 5, 4, 7, 6, 4,
8, 9, 10, 8, 10, 11,
14, 13, 12, 15, 14, 12,
16, 17, 18, 16, 18, 19,
22, 21, 20, 23, 22, 20
}
);
// Clear each slice of the cubemap to a different color
for (uint i = 0; i < 6; i += 1)
{
ColorAttachmentInfo attachmentInfo = new ColorAttachmentInfo
{
Texture = cubemap,
ClearColor = colors[i],
Depth = 0,
Layer = i,
Level = 0,
LoadOp = LoadOp.Clear,
StoreOp = StoreOp.Store
};
cmdbuf.BeginRenderPass(attachmentInfo);
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
protected override void Update(System.TimeSpan delta)
{
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Bottom))
{
camPos.Z *= -1;
}
}
protected override void Draw(double alpha)
{
Matrix4x4 proj = Matrix4x4.CreatePerspectiveFieldOfView(
MathHelper.ToRadians(75f),
(float) MainWindow.Width / MainWindow.Height,
0.01f,
100f
);
Matrix4x4 view = Matrix4x4.CreateLookAt(
camPos,
Vector3.Zero,
Vector3.Up
);
TransformVertexUniform vertUniforms = new TransformVertexUniform(view * proj);
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(cubemap, sampler));
uint vertexUniformOffset = cmdbuf.PushVertexShaderUniforms(vertUniforms);
cmdbuf.DrawIndexedPrimitives(0, 0, 12, vertexUniformOffset, 0);
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
RenderTextureCubeGame game = new RenderTextureCubeGame();
game.Run();
}
}
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,182 +0,0 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Math.Float;
namespace MoonWorks.Test
{
class RenderTextureMipmapsGame : Game
{
private GraphicsPipeline pipeline;
private Buffer vertexBuffer;
private Buffer indexBuffer;
private Texture texture;
private Sampler[] samplers = new Sampler[5];
private float scale = 0.5f;
private int currentSamplerIndex = 0;
private Color[] colors = new Color[]
{
Color.Red,
Color.Green,
Color.Blue,
Color.Yellow,
};
private string GetSamplerString(int index)
{
switch (index)
{
case 0:
return "PointClamp";
case 1:
return "LinearClamp";
case 2:
return "PointClamp with Mip LOD Bias = 0.25";
case 3:
return "PointClamp with Min LOD = 1";
case 4:
return "PointClamp with Max LOD = 1";
default:
throw new System.Exception("Unknown sampler!");
}
}
public RenderTextureMipmapsGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{
Logger.LogInfo("Press Left and Right to shrink/expand the scale of the quad");
Logger.LogInfo("Press Down to cycle through sampler states");
Logger.LogInfo(GetSamplerString(currentSamplerIndex));
// Load the shaders
ShaderModule vertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuadWithMatrix.vert"));
ShaderModule fragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuad.frag"));
// Create the graphics pipeline
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
MainWindow.SwapchainFormat,
vertShaderModule,
fragShaderModule
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureVertex>();
pipelineCreateInfo.VertexShaderInfo = GraphicsShaderInfo.Create<TransformVertexUniform>(vertShaderModule, "main", 0);
pipelineCreateInfo.FragmentShaderInfo.SamplerBindingCount = 1;
pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create samplers
SamplerCreateInfo samplerCreateInfo = SamplerCreateInfo.PointClamp;
samplers[0] = new Sampler(GraphicsDevice, samplerCreateInfo);
samplerCreateInfo = SamplerCreateInfo.LinearClamp;
samplers[1] = new Sampler(GraphicsDevice, samplerCreateInfo);
samplerCreateInfo = SamplerCreateInfo.PointClamp;
samplerCreateInfo.MipLodBias = 0.25f;
samplers[2] = new Sampler(GraphicsDevice, samplerCreateInfo);
samplerCreateInfo = SamplerCreateInfo.PointClamp;
samplerCreateInfo.MinLod = 1;
samplers[3] = new Sampler(GraphicsDevice, samplerCreateInfo);
samplerCreateInfo = SamplerCreateInfo.PointClamp;
samplerCreateInfo.MaxLod = 1;
samplers[4] = new Sampler(GraphicsDevice, samplerCreateInfo);
// Create and populate the GPU resources
vertexBuffer = Buffer.Create<PositionTextureVertex>(GraphicsDevice, BufferUsageFlags.Vertex, 4);
indexBuffer = Buffer.Create<ushort>(GraphicsDevice, BufferUsageFlags.Index, 6);
texture = Texture.CreateTexture2D(
GraphicsDevice,
MainWindow.Width,
MainWindow.Height,
TextureFormat.R8G8B8A8,
TextureUsageFlags.ColorTarget | 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,
}
);
// Clear each mip level to a different color
for (uint i = 0; i < texture.LevelCount; i += 1)
{
ColorAttachmentInfo attachmentInfo = new ColorAttachmentInfo
{
Texture = texture,
ClearColor = colors[i],
Depth = 0,
Layer = 0,
Level = i,
LoadOp = LoadOp.Clear,
StoreOp = StoreOp.Store
};
cmdbuf.BeginRenderPass(attachmentInfo);
cmdbuf.EndRenderPass();
}
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);
}
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Bottom))
{
currentSamplerIndex = (currentSamplerIndex + 1) % samplers.Length;
Logger.LogInfo(GetSamplerString(currentSamplerIndex));
}
}
protected override void Draw(double alpha)
{
TransformVertexUniform vertUniforms = new TransformVertexUniform(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, samplers[currentSamplerIndex]));
uint vertParamOffset = cmdbuf.PushVertexShaderUniforms(vertUniforms);
cmdbuf.DrawIndexedPrimitives(0, 0, 2, vertParamOffset, 0);
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
RenderTextureMipmapsGame game = new RenderTextureMipmapsGame();
game.Run();
}
}
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,50 +0,0 @@
using System;
using MoonWorks.Graphics;
namespace MoonWorks.Test
{
class StoreLoadGame : Game
{
private GraphicsPipeline fillPipeline;
public StoreLoadGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{
ShaderModule vertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("RawTriangle.vert"));
ShaderModule fragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("SolidColor.frag"));
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
MainWindow.SwapchainFormat,
vertShaderModule,
fragShaderModule
);
fillPipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
}
protected override void Update(TimeSpan delta)
{
}
protected override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture? swapchain = cmdbuf.AcquireSwapchainTexture(MainWindow);
if (swapchain != null)
{
cmdbuf.BeginRenderPass(new ColorAttachmentInfo(swapchain, Color.Blue));
cmdbuf.BindGraphicsPipeline(fillPipeline);
cmdbuf.DrawPrimitives(0, 1, 0, 0);
cmdbuf.EndRenderPass();
cmdbuf.BeginRenderPass(new ColorAttachmentInfo(swapchain, LoadOp.Load, StoreOp.Store));
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
StoreLoadGame game = new StoreLoadGame();
game.Run();
}
}
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,147 +0,0 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Math.Float;
using RefreshCS;
namespace MoonWorks.Test
{
class Texture3DGame : Game
{
private GraphicsPipeline pipeline;
private Buffer vertexBuffer;
private Buffer indexBuffer;
private Texture texture;
private Sampler sampler;
private int currentDepth = 0;
struct FragUniform
{
public float Depth;
public FragUniform(float depth)
{
Depth = depth;
}
}
public Texture3DGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{
Logger.LogInfo("Press Left and Right to cycle between depth slices");
// Load the shaders
ShaderModule vertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuad.vert"));
ShaderModule fragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuad3D.frag"));
// Create the graphics pipeline
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
MainWindow.SwapchainFormat,
vertShaderModule,
fragShaderModule
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureVertex>();
pipelineCreateInfo.FragmentShaderInfo = GraphicsShaderInfo.Create<FragUniform>(fragShaderModule, "main", 1);
pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create samplers
sampler = new Sampler(GraphicsDevice, SamplerCreateInfo.PointClamp);
// Create and populate the GPU resources
vertexBuffer = Buffer.Create<PositionTextureVertex>(GraphicsDevice, BufferUsageFlags.Vertex, 4);
indexBuffer = Buffer.Create<ushort>(GraphicsDevice, BufferUsageFlags.Index, 6);
texture = Texture.CreateTexture3D(GraphicsDevice, 16, 16, 7, TextureFormat.R8G8B8A8, TextureUsageFlags.Sampler);
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,
}
);
// Load each depth subimage of the 3D texture
for (uint i = 0; i < texture.Depth; i += 1)
{
TextureSlice slice = new TextureSlice(
texture,
new Rect(0, 0, (int) texture.Width, (int) texture.Height),
i
);
Texture.SetDataFromImageFile(
cmdbuf,
slice,
TestUtils.GetTexturePath($"tex3d_{i}.png")
);
}
GraphicsDevice.Submit(cmdbuf);
}
protected override void Update(System.TimeSpan delta)
{
int prevDepth = currentDepth;
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Left))
{
currentDepth -= 1;
if (currentDepth < 0)
{
currentDepth = (int) texture.Depth - 1;
}
}
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Right))
{
currentDepth += 1;
if (currentDepth >= texture.Depth)
{
currentDepth = 0;
}
}
if (prevDepth != currentDepth)
{
Logger.LogInfo("Setting depth to: " + currentDepth);
}
}
protected override void Draw(double alpha)
{
FragUniform fragUniform = new FragUniform((float)currentDepth / texture.Depth + 0.01f);
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 fragParamOffset = cmdbuf.PushFragmentShaderUniforms(fragUniform);
cmdbuf.DrawIndexedPrimitives(0, 0, 2, 0, fragParamOffset);
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
Texture3DGame game = new Texture3DGame();
game.Run();
}
}
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,128 +0,0 @@
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;
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("TexturedQuadWithMatrix.vert"));
ShaderModule fragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuad.frag"));
// Create the graphics pipeline
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
MainWindow.SwapchainFormat,
vertShaderModule,
fragShaderModule
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureVertex>();
pipelineCreateInfo.VertexShaderInfo = GraphicsShaderInfo.Create<TransformVertexUniform>(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<PositionTextureVertex>(GraphicsDevice, BufferUsageFlags.Vertex, 4);
indexBuffer = Buffer.Create<ushort>(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
);
Texture.SetDataFromImageFile(cmdbuf, slice, TestUtils.GetTexturePath($"mip{i}.png"));
}
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)
{
TransformVertexUniform vertUniforms = new TransformVertexUniform(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();
}
}
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,135 +0,0 @@
using System.Runtime.InteropServices;
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Math.Float;
namespace MoonWorks.Test
{
class TexturedAnimatedQuadGame : Game
{
private GraphicsPipeline pipeline;
private Buffer vertexBuffer;
private Buffer indexBuffer;
private Texture texture;
private Sampler sampler;
private float t;
[StructLayout(LayoutKind.Sequential)]
private struct FragmentUniforms
{
public Vector4 MultiplyColor;
public FragmentUniforms(Vector4 multiplyColor)
{
MultiplyColor = multiplyColor;
}
}
public TexturedAnimatedQuadGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{
// Load the shaders
ShaderModule vertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuadWithMatrix.vert"));
ShaderModule fragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuadWithMultiplyColor.frag"));
// Create the graphics pipeline
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
MainWindow.SwapchainFormat,
vertShaderModule,
fragShaderModule
);
pipelineCreateInfo.AttachmentInfo.ColorAttachmentDescriptions[0].BlendState = ColorAttachmentBlendState.AlphaBlend;
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureVertex>();
pipelineCreateInfo.VertexShaderInfo = GraphicsShaderInfo.Create<TransformVertexUniform>(vertShaderModule, "main", 0);
pipelineCreateInfo.FragmentShaderInfo = GraphicsShaderInfo.Create<FragmentUniforms>(fragShaderModule, "main", 1);
pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create and populate the GPU resources
vertexBuffer = Buffer.Create<PositionTextureVertex>(GraphicsDevice, BufferUsageFlags.Vertex, 4);
indexBuffer = Buffer.Create<ushort>(GraphicsDevice, BufferUsageFlags.Index, 6);
sampler = new Sampler(GraphicsDevice, SamplerCreateInfo.PointClamp);
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
cmdbuf.SetBufferData(
vertexBuffer,
new PositionTextureVertex[]
{
new PositionTextureVertex(new Vector3(-0.5f, -0.5f, 0), new Vector2(0, 0)),
new PositionTextureVertex(new Vector3(0.5f, -0.5f, 0), new Vector2(1, 0)),
new PositionTextureVertex(new Vector3(0.5f, 0.5f, 0), new Vector2(1, 1)),
new PositionTextureVertex(new Vector3(-0.5f, 0.5f, 0), new Vector2(0, 1)),
}
);
cmdbuf.SetBufferData(
indexBuffer,
new ushort[]
{
0, 1, 2,
0, 2, 3,
}
);
texture = Texture.FromImageFile(GraphicsDevice, cmdbuf, TestUtils.GetTexturePath("ravioli.png"));
GraphicsDevice.Submit(cmdbuf);
}
protected override void Update(System.TimeSpan delta)
{
t += (float) delta.TotalSeconds;
}
protected override void Draw(double alpha)
{
TransformVertexUniform vertUniforms;
FragmentUniforms fragUniforms;
uint vertParamOffset, fragParamOffset;
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));
// Top-left
vertUniforms = new TransformVertexUniform(Matrix4x4.CreateRotationZ(t) * Matrix4x4.CreateTranslation(new Vector3(-0.5f, -0.5f, 0)));
fragUniforms = new FragmentUniforms(new Vector4(1f, 0.5f + System.MathF.Sin(t) * 0.5f, 1f, 1f));
vertParamOffset = cmdbuf.PushVertexShaderUniforms(vertUniforms);
fragParamOffset = cmdbuf.PushFragmentShaderUniforms(fragUniforms);
cmdbuf.DrawIndexedPrimitives(0, 0, 2, vertParamOffset, fragParamOffset);
// Top-right
vertUniforms = new TransformVertexUniform(Matrix4x4.CreateRotationZ((2 * System.MathF.PI) - t) * Matrix4x4.CreateTranslation(new Vector3(0.5f, -0.5f, 0)));
fragUniforms = new FragmentUniforms(new Vector4(1f, 0.5f + System.MathF.Cos(t) * 0.5f, 1f, 1f));
vertParamOffset = cmdbuf.PushVertexShaderUniforms(vertUniforms);
fragParamOffset = cmdbuf.PushFragmentShaderUniforms(fragUniforms);
cmdbuf.DrawIndexedPrimitives(0, 0, 2, vertParamOffset, fragParamOffset);
// Bottom-left
vertUniforms = new TransformVertexUniform(Matrix4x4.CreateRotationZ(t) * Matrix4x4.CreateTranslation(new Vector3(-0.5f, 0.5f, 0)));
fragUniforms = new FragmentUniforms(new Vector4(1f, 0.5f + System.MathF.Sin(t) * 0.2f, 1f, 1f));
vertParamOffset = cmdbuf.PushVertexShaderUniforms(vertUniforms);
fragParamOffset = cmdbuf.PushFragmentShaderUniforms(fragUniforms);
cmdbuf.DrawIndexedPrimitives(0, 0, 2, vertParamOffset, fragParamOffset);
// Bottom-right
vertUniforms = new TransformVertexUniform(Matrix4x4.CreateRotationZ(t) * Matrix4x4.CreateTranslation(new Vector3(0.5f, 0.5f, 0)));
fragUniforms = new FragmentUniforms(new Vector4(1f, 0.5f + System.MathF.Cos(t) * 1f, 1f, 1f));
vertParamOffset = cmdbuf.PushVertexShaderUniforms(vertUniforms);
fragParamOffset = cmdbuf.PushFragmentShaderUniforms(fragUniforms);
cmdbuf.DrawIndexedPrimitives(0, 0, 2, vertParamOffset, fragParamOffset);
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
TexturedAnimatedQuadGame game = new TexturedAnimatedQuadGame();
game.Run();
}
}
}

View File

@ -1,17 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ErrorOnDuplicatePublishOutputFiles>false</ErrorOnDuplicatePublishOutputFiles>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,167 +0,0 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Math.Float;
namespace MoonWorks.Test
{
class TexturedQuadGame : Game
{
private GraphicsPipeline pipeline;
private Buffer vertexBuffer;
private Buffer indexBuffer;
private Sampler[] samplers = new Sampler[6];
private string[] samplerNames = new string[]
{
"PointClamp",
"PointWrap",
"LinearClamp",
"LinearWrap",
"AnisotropicClamp",
"AnisotropicWrap"
};
private int currentSamplerIndex;
private Texture[] textures = new Texture[4];
private string[] imageLoadFormatNames = new string[]
{
"PNG from file",
"PNG from memory",
"QOI from file",
"QOI from memory"
};
private int currentTextureIndex;
private System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
public TexturedQuadGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{
Logger.LogInfo("Press Left and Right to cycle between sampler states");
Logger.LogInfo("Setting sampler state to: " + samplerNames[0]);
Logger.LogInfo("Press Down to cycle between image load formats");
Logger.LogInfo("Setting image format to: " + imageLoadFormatNames[0]);
var pngBytes = System.IO.File.ReadAllBytes(TestUtils.GetTexturePath("ravioli.png"));
var qoiBytes = System.IO.File.ReadAllBytes(TestUtils.GetTexturePath("ravioli.qoi"));
Logger.LogInfo(pngBytes.Length.ToString());
Logger.LogInfo(qoiBytes.Length.ToString());
// Load the shaders
ShaderModule vertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuad.vert"));
ShaderModule fragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuad.frag"));
// Create the graphics pipeline
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
MainWindow.SwapchainFormat,
vertShaderModule,
fragShaderModule
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureVertex>();
pipelineCreateInfo.FragmentShaderInfo.SamplerBindingCount = 1;
pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create samplers
samplers[0] = new Sampler(GraphicsDevice, SamplerCreateInfo.PointClamp);
samplers[1] = new Sampler(GraphicsDevice, SamplerCreateInfo.PointWrap);
samplers[2] = new Sampler(GraphicsDevice, SamplerCreateInfo.LinearClamp);
samplers[3] = new Sampler(GraphicsDevice, SamplerCreateInfo.LinearWrap);
samplers[4] = new Sampler(GraphicsDevice, SamplerCreateInfo.AnisotropicClamp);
samplers[5] = new Sampler(GraphicsDevice, SamplerCreateInfo.AnisotropicWrap);
// Create and populate the GPU resources
vertexBuffer = Buffer.Create<PositionTextureVertex>(GraphicsDevice, BufferUsageFlags.Vertex, 4);
indexBuffer = Buffer.Create<ushort>(GraphicsDevice, BufferUsageFlags.Index, 6);
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(4, 0)),
new PositionTextureVertex(new Vector3(1, 1, 0), new Vector2(4, 4)),
new PositionTextureVertex(new Vector3(-1, 1, 0), new Vector2(0, 4)),
}
);
cmdbuf.SetBufferData(
indexBuffer,
new ushort[]
{
0, 1, 2,
0, 2, 3,
}
);
textures[0] = Texture.FromImageFile(GraphicsDevice, cmdbuf, TestUtils.GetTexturePath("ravioli.png"));
textures[1] = Texture.FromImageBytes(GraphicsDevice, cmdbuf, pngBytes);
textures[2] = Texture.FromImageFile(GraphicsDevice, cmdbuf, TestUtils.GetTexturePath("ravioli.qoi"));
textures[3] = Texture.FromImageBytes(GraphicsDevice, cmdbuf, qoiBytes);
GraphicsDevice.Submit(cmdbuf);
}
protected override void Update(System.TimeSpan delta)
{
int prevSamplerIndex = currentSamplerIndex;
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Left))
{
currentSamplerIndex -= 1;
if (currentSamplerIndex < 0)
{
currentSamplerIndex = samplers.Length - 1;
}
}
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Right))
{
currentSamplerIndex += 1;
if (currentSamplerIndex >= samplers.Length)
{
currentSamplerIndex = 0;
}
}
if (prevSamplerIndex != currentSamplerIndex)
{
Logger.LogInfo("Setting sampler state to: " + samplerNames[currentSamplerIndex]);
}
int prevTextureIndex = currentTextureIndex;
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Bottom))
{
currentTextureIndex = (currentTextureIndex + 1) % imageLoadFormatNames.Length;
}
if (prevTextureIndex != currentTextureIndex)
{
Logger.LogInfo("Setting texture format to: " + imageLoadFormatNames[currentTextureIndex]);
}
}
protected override void Draw(double alpha)
{
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(textures[currentTextureIndex], samplers[currentSamplerIndex]));
cmdbuf.DrawIndexedPrimitives(0, 0, 2, 0, 0);
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
TexturedQuadGame game = new TexturedQuadGame();
game.Run();
}
}
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,66 +0,0 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Math.Float;
namespace MoonWorks.Test
{
class TriangleVertexBufferGame : Game
{
private GraphicsPipeline pipeline;
private Buffer vertexBuffer;
public TriangleVertexBufferGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{
// Load the shaders
ShaderModule vertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("PositionColor.vert"));
ShaderModule fragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("SolidColor.frag"));
// Create the graphics pipeline
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
MainWindow.SwapchainFormat,
vertShaderModule,
fragShaderModule
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionColorVertex>();
pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create and populate the vertex buffer
vertexBuffer = Buffer.Create<PositionColorVertex>(GraphicsDevice, BufferUsageFlags.Vertex, 3);
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
cmdbuf.SetBufferData(
vertexBuffer,
new PositionColorVertex[]
{
new PositionColorVertex(new Vector3(-1, 1, 0), Color.Red),
new PositionColorVertex(new Vector3(1, 1, 0), Color.Lime),
new PositionColorVertex(new Vector3(0, -1, 0), Color.Blue),
}
);
GraphicsDevice.Submit(cmdbuf);
}
protected override void Update(System.TimeSpan delta) { }
protected override void Draw(double alpha)
{
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.DrawPrimitives(0, 1, 0, 0);
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
TriangleVertexBufferGame p = new TriangleVertexBufferGame();
p.Run();
}
}
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,73 +0,0 @@
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Math.Float;
namespace MoonWorks.Test
{
class VertexSamplerGame : Game
{
private GraphicsPipeline pipeline;
private Buffer vertexBuffer;
private Texture texture;
private Sampler sampler;
public VertexSamplerGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{
// Load the shaders
ShaderModule vertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("PositionSampler.vert"));
ShaderModule fragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("SolidColor.frag"));
// Create the graphics pipeline
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
MainWindow.SwapchainFormat,
vertShaderModule,
fragShaderModule
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureVertex>();
pipelineCreateInfo.VertexShaderInfo.SamplerBindingCount = 1;
pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create and populate the GPU resources
vertexBuffer = Buffer.Create<PositionTextureVertex>(GraphicsDevice, BufferUsageFlags.Vertex, 3);
texture = Texture.CreateTexture2D(GraphicsDevice, 3, 1, TextureFormat.R8G8B8A8, TextureUsageFlags.Sampler);
sampler = new Sampler(GraphicsDevice, SamplerCreateInfo.PointClamp);
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(0.334f, 0)),
new PositionTextureVertex(new Vector3(0, -1, 0), new Vector2(0.667f, 0)),
}
);
cmdbuf.SetTextureData(texture, new Color[] { Color.Yellow, Color.Indigo, Color.HotPink });
GraphicsDevice.Submit(cmdbuf);
}
protected override void Update(System.TimeSpan delta) { }
protected override void Draw(double alpha)
{
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.BindVertexSamplers(new TextureSamplerBinding(texture, sampler));
cmdbuf.DrawPrimitives(0, 1, 0, 0);
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
VertexSamplerGame p = new VertexSamplerGame();
p.Run();
}
}
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,99 +0,0 @@
using MoonWorks.Math.Float;
using MoonWorks.Graphics;
using MoonWorks.Video;
namespace MoonWorks.Test
{
class VideoPlayerGame : Game
{
private GraphicsPipeline pipeline;
private Sampler sampler;
private Buffer vertexBuffer;
private Buffer indexBuffer;
private Video.VideoAV1 video;
private VideoPlayer videoPlayer;
public VideoPlayerGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{
// Load the shaders
ShaderModule vertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuad.vert"));
ShaderModule fragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("TexturedQuad.frag"));
// Create the graphics pipeline
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
MainWindow.SwapchainFormat,
vertShaderModule,
fragShaderModule
);
pipelineCreateInfo.VertexInputState = VertexInputState.CreateSingleBinding<PositionTextureVertex>();
pipelineCreateInfo.FragmentShaderInfo.SamplerBindingCount = 1;
pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
// Create the sampler
sampler = new Sampler(GraphicsDevice, SamplerCreateInfo.LinearClamp);
// Create and populate the GPU resources
vertexBuffer = Buffer.Create<PositionTextureVertex>(GraphicsDevice, BufferUsageFlags.Vertex, 4);
indexBuffer = Buffer.Create<ushort>(GraphicsDevice, BufferUsageFlags.Index, 6);
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,
}
);
GraphicsDevice.Submit(cmdbuf);
// Load the video
video = new VideoAV1(GraphicsDevice, TestUtils.GetVideoPath("hello.obu"), 25);
// Play the video
videoPlayer = new VideoPlayer(GraphicsDevice);
videoPlayer.Load(video);
videoPlayer.Loop = true;
videoPlayer.Play();
}
protected override void Update(System.TimeSpan delta)
{
videoPlayer.Render();
}
protected override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture? backbuffer = cmdbuf.AcquireSwapchainTexture(MainWindow);
if (backbuffer != null)
{
cmdbuf.BeginRenderPass(new ColorAttachmentInfo(backbuffer, Color.CornflowerBlue));
cmdbuf.BindGraphicsPipeline(pipeline);
cmdbuf.BindVertexBuffers(vertexBuffer);
cmdbuf.BindIndexBuffer(indexBuffer, IndexElementSize.Sixteen);
cmdbuf.BindFragmentSamplers(new TextureSamplerBinding(videoPlayer.RenderTexture, sampler));
cmdbuf.DrawIndexedPrimitives(0, 0, 2, 0, 0);
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
VideoPlayerGame game = new VideoPlayerGame();
game.Run();
}
}
}

View File

@ -1,16 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\MoonWorks\MoonWorks.csproj" />
<ProjectReference Include="..\MoonWorks.Test.Common\MoonWorks.Test.Common.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<Import Project="$(SolutionDir)NativeAOT_Console.targets" Condition="Exists('$(SolutionDir)NativeAOT_Console.targets')" />
</Project>

View File

@ -1,85 +0,0 @@
using MoonWorks;
using MoonWorks.Graphics;
namespace MoonWorks.Test
{
class WindowResizingGame : Game
{
private GraphicsPipeline pipeline;
private int currentResolutionIndex;
private record struct Res(uint Width, uint Height);
private Res[] resolutions = new Res[]
{
new Res(640, 480),
new Res(1280, 720),
new Res(1024, 1024),
new Res(1600, 900),
new Res(1920, 1080),
new Res(3200, 1800),
new Res(3840, 2160),
};
public WindowResizingGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{
ShaderModule vertShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("RawTriangle.vert"));
ShaderModule fragShaderModule = new ShaderModule(GraphicsDevice, TestUtils.GetShaderPath("SolidColor.frag"));
GraphicsPipelineCreateInfo pipelineCreateInfo = TestUtils.GetStandardGraphicsPipelineCreateInfo(
MainWindow.SwapchainFormat,
vertShaderModule,
fragShaderModule
);
pipeline = new GraphicsPipeline(GraphicsDevice, pipelineCreateInfo);
}
protected override void Update(System.TimeSpan delta)
{
int prevResolutionIndex = currentResolutionIndex;
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Left))
{
currentResolutionIndex -= 1;
if (currentResolutionIndex < 0)
{
currentResolutionIndex = resolutions.Length - 1;
}
}
if (TestUtils.CheckButtonPressed(Inputs, TestUtils.ButtonType.Right))
{
currentResolutionIndex += 1;
if (currentResolutionIndex >= resolutions.Length)
{
currentResolutionIndex = 0;
}
}
if (prevResolutionIndex != currentResolutionIndex)
{
Logger.LogInfo("Setting resolution to: " + resolutions[currentResolutionIndex]);
MainWindow.SetWindowSize(resolutions[currentResolutionIndex].Width, resolutions[currentResolutionIndex].Height);
}
}
protected override void Draw(double alpha)
{
CommandBuffer cmdbuf = GraphicsDevice.AcquireCommandBuffer();
Texture? backbuffer = cmdbuf.AcquireSwapchainTexture(MainWindow);
if (backbuffer != null)
{
cmdbuf.BeginRenderPass(new ColorAttachmentInfo(backbuffer, Color.Black));
cmdbuf.BindGraphicsPipeline(pipeline);
cmdbuf.DrawPrimitives(0, 1, 0, 0);
cmdbuf.EndRenderPass();
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
WindowResizingGame game = new WindowResizingGame();
game.Run();
}
}
}