Compare commits

..

No commits in common. "compute_sprite_batch" and "main" have entirely different histories.

182 changed files with 4966 additions and 5828 deletions

7
.vscode/launch.json vendored
View File

@ -1,7 +0,0 @@
{
// 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

@ -0,0 +1,16 @@
<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

@ -0,0 +1,142 @@
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

@ -0,0 +1,16 @@
<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

@ -0,0 +1,110 @@
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

@ -0,0 +1,16 @@
<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

@ -0,0 +1,87 @@
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

@ -0,0 +1,16 @@
<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

@ -0,0 +1,30 @@
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

@ -0,0 +1,16 @@
<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

@ -0,0 +1,51 @@
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();
}
}
}

View File

@ -1,19 +0,0 @@
#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

@ -1,79 +0,0 @@
#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,17 +0,0 @@
#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

@ -1,13 +0,0 @@
#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

@ -1,20 +0,0 @@
#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

@ -1,116 +0,0 @@
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;
}
}

View File

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

View File

@ -1,115 +0,0 @@
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

@ -0,0 +1,16 @@
<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

@ -0,0 +1,133 @@
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

@ -0,0 +1,16 @@
<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

@ -0,0 +1,129 @@
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

@ -0,0 +1,17 @@
<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

@ -0,0 +1,183 @@
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();
}
}
}

16
Cube/Cube.csproj Normal file
View File

@ -0,0 +1,16 @@
<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>

467
Cube/CubeGame.cs Normal file
View File

@ -0,0 +1,467 @@
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();
}
}
}

16
CullFace/CullFace.csproj Normal file
View File

@ -0,0 +1,16 @@
<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>

142
CullFace/CullFaceGame.cs Normal file
View File

@ -0,0 +1,142 @@
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

@ -0,0 +1,16 @@
<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>

295
DepthMSAA/DepthMSAAGame.cs Normal file
View File

@ -0,0 +1,295 @@
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

@ -0,0 +1,16 @@
<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

@ -0,0 +1,81 @@
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

@ -1,196 +0,0 @@
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

@ -1,137 +0,0 @@
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

@ -1,117 +0,0 @@
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

@ -1,36 +0,0 @@
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

@ -1,75 +0,0 @@
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

@ -1,166 +0,0 @@
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

@ -1,244 +0,0 @@
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

@ -1,80 +0,0 @@
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

@ -1,184 +0,0 @@
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();
}
}
}

View File

@ -1,597 +0,0 @@
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();
}
}
}

View File

@ -1,179 +0,0 @@
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

@ -1,282 +0,0 @@
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

@ -1,111 +0,0 @@
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();
}
}

View File

@ -1,18 +0,0 @@
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

@ -1,143 +0,0 @@
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

@ -1,137 +0,0 @@
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();
}
}

View File

@ -1,284 +0,0 @@
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();
}
}

View File

@ -1,156 +0,0 @@
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

@ -1,94 +0,0 @@
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

@ -1,118 +0,0 @@
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

@ -1,210 +0,0 @@
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

@ -1,228 +0,0 @@
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

@ -1,89 +0,0 @@
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

@ -1,227 +0,0 @@
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

@ -1,198 +0,0 @@
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

@ -1,174 +0,0 @@
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

@ -1,165 +0,0 @@
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

@ -1,210 +0,0 @@
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

@ -1,96 +0,0 @@
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

@ -1,113 +0,0 @@
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

@ -1,53 +0,0 @@
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

@ -1,118 +0,0 @@
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

@ -0,0 +1,16 @@
<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

@ -0,0 +1,113 @@
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

@ -0,0 +1,16 @@
<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

@ -0,0 +1,106 @@
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();
}
}
}

16
MSAA/MSAA.csproj Normal file
View File

@ -0,0 +1,16 @@
<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>

152
MSAA/MSAAGame.cs Normal file
View File

@ -0,0 +1,152 @@
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();
}
}
}

16
MSAACube/MSAACube.csproj Normal file
View File

@ -0,0 +1,16 @@
<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>

223
MSAACube/MSAACubeGame.cs Normal file
View File

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

View File

@ -0,0 +1,23 @@
#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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -4,9 +4,9 @@ layout (location = 0) in vec2 TexCoord;
layout (location = 0) out vec4 FragColor; layout (location = 0) out vec4 FragColor;
layout(set = 2, binding = 0) uniform sampler2D Sampler; layout(binding = 0, set = 1) uniform sampler2D Sampler;
layout (set = 3, binding = 0) uniform UniformBlock layout (binding = 0, set = 3) uniform UniformBlock
{ {
vec4 MultiplyColor; 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

View File

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

View File

@ -0,0 +1,22 @@
<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

@ -0,0 +1,135 @@
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

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

View File

@ -0,0 +1,75 @@
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

@ -1,22 +0,0 @@
<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,9 +3,67 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16 # Visual Studio Version 16
VisualStudioVersion = 16.0.30717.126 VisualStudioVersion = 16.0.30717.126
MinimumVisualStudioVersion = 15.0.26124.0 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}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MoonWorks", "..\MoonWorks\MoonWorks.csproj", "{1695B1D8-4935-490C-A5EC-E2F2AA94B150}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MoonWorksGraphicsTests", "MoonWorksGraphicsTests.csproj", "{8AA61DD7-07CE-45B7-BD1A-52AA0D4DDC92}" 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}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -13,14 +71,130 @@ Global
Release|Any CPU = Release|Any CPU Release|Any CPU = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution 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.ActiveCfg = Debug|Any CPU
{1695B1D8-4935-490C-A5EC-E2F2AA94B150}.Debug|Any CPU.Build.0 = 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.ActiveCfg = Release|Any CPU
{1695B1D8-4935-490C-A5EC-E2F2AA94B150}.Release|Any CPU.Build.0 = Release|Any CPU {1695B1D8-4935-490C-A5EC-E2F2AA94B150}.Release|Any CPU.Build.0 = Release|Any CPU
{8AA61DD7-07CE-45B7-BD1A-52AA0D4DDC92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C3808AFD-23DD-4622-BFA7-981A344D0C19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8AA61DD7-07CE-45B7-BD1A-52AA0D4DDC92}.Debug|Any CPU.Build.0 = Debug|Any CPU {C3808AFD-23DD-4622-BFA7-981A344D0C19}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8AA61DD7-07CE-45B7-BD1A-52AA0D4DDC92}.Release|Any CPU.ActiveCfg = Release|Any CPU {C3808AFD-23DD-4622-BFA7-981A344D0C19}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8AA61DD7-07CE-45B7-BD1A-52AA0D4DDC92}.Release|Any CPU.Build.0 = 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
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -1,133 +0,0 @@
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

@ -0,0 +1,16 @@
<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

@ -0,0 +1,131 @@
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

@ -0,0 +1,16 @@
<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

@ -0,0 +1,134 @@
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

@ -0,0 +1,16 @@
<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

@ -0,0 +1,176 @@
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

@ -0,0 +1,16 @@
<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

@ -0,0 +1,182 @@
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

@ -0,0 +1,16 @@
<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

@ -0,0 +1,50 @@
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

@ -0,0 +1,16 @@
<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>

147
Texture3D/Texture3DGame.cs Normal file
View File

@ -0,0 +1,147 @@
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

@ -0,0 +1,16 @@
<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

@ -0,0 +1,128 @@
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

@ -0,0 +1,16 @@
<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

@ -0,0 +1,135 @@
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

@ -0,0 +1,17 @@
<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

@ -0,0 +1,167 @@
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

@ -0,0 +1,16 @@
<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

@ -0,0 +1,66 @@
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

@ -0,0 +1,16 @@
<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

@ -0,0 +1,73 @@
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

@ -0,0 +1,16 @@
<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

@ -0,0 +1,99 @@
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

@ -0,0 +1,16 @@
<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

@ -0,0 +1,85 @@
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();
}
}
}