add Cube test and related infrastructure, and fixed API misuse in TexturedAnimatedQuad

pull/1/head
Caleb Cornett 2022-11-12 12:51:22 -05:00
parent a60858f7d1
commit 5c95f23c63
26 changed files with 454 additions and 7 deletions

15
Cube/Cube.csproj Normal file
View File

@ -0,0 +1,15 @@
<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>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<Platforms>x64</Platforms>
</PropertyGroup>
</Project>

358
Cube/CubeGame.cs Normal file
View File

@ -0,0 +1,358 @@
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 skyboxPipeline;
private Texture depthTexture;
private Buffer cubeVertexBuffer;
private Buffer skyboxVertexBuffer;
private Buffer indexBuffer;
private Texture skyboxTexture;
private Sampler skyboxSampler;
private bool finishedLoading;
private float cubeTimer = 0f;
private Quaternion cubeRotation = Quaternion.Identity;
private Quaternion previousCubeRotation = Quaternion.Identity;
struct Uniforms
{
public Matrix4x4 ViewProjection;
public Uniforms(Matrix4x4 viewProjection)
{
ViewProjection = viewProjection;
}
}
void LoadCubemap(CommandBuffer cmdbuf, string[] imagePaths)
{
System.IntPtr textureData;
int w, h, numChannels;
for (uint i = 0; i < imagePaths.Length; i++)
{
textureData = RefreshCS.Refresh.Refresh_Image_Load(
imagePaths[i],
out w,
out h,
out numChannels
);
cmdbuf.SetTextureData(
new TextureSlice(
skyboxTexture,
new Rect(0, 0, w, h),
0,
i
),
textureData,
(uint) (w * h * 4) // w * h * numChannels does not work
);
RefreshCS.Refresh.Refresh_Image_Free(textureData);
}
}
public CubeGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{
ShaderModule cubeVertShaderModule = new ShaderModule(
GraphicsDevice,
TestUtils.GetShaderPath("PositionColorVertWithMatrix.spv")
);
ShaderModule cubeFragShaderModule = new ShaderModule(
GraphicsDevice,
TestUtils.GetShaderPath("SolidColor.spv")
);
ShaderModule skyboxVertShaderModule = new ShaderModule(
GraphicsDevice,
TestUtils.GetShaderPath("SkyboxVert.spv")
);
ShaderModule skyboxFragShaderModule = new ShaderModule(
GraphicsDevice,
TestUtils.GetShaderPath("SkyboxFrag.spv")
);
depthTexture = Texture.CreateTexture2D(
GraphicsDevice,
MainWindow.Width,
MainWindow.Height,
TextureFormat.D16,
TextureUsageFlags.DepthStencilTarget
);
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
Task loadingTask = Task.Run(() => UploadGPUAssets());
cubePipeline = new GraphicsPipeline(
GraphicsDevice,
new GraphicsPipelineCreateInfo
{
AttachmentInfo = new GraphicsPipelineAttachmentInfo(
TextureFormat.D16,
new ColorAttachmentDescription(
MainWindow.SwapchainFormat,
ColorAttachmentBlendState.Opaque
)
),
DepthStencilState = DepthStencilState.DepthReadWrite,
VertexShaderInfo = GraphicsShaderInfo.Create<Uniforms>(cubeVertShaderModule, "main", 0),
VertexInputState = new VertexInputState(
VertexBinding.Create<PositionColorVertex>(),
VertexAttribute.Create<PositionColorVertex>("Position", 0),
VertexAttribute.Create<PositionColorVertex>("Color", 1)
),
PrimitiveType = PrimitiveType.TriangleList,
FragmentShaderInfo = GraphicsShaderInfo.Create(cubeFragShaderModule, "main", 0),
RasterizerState = RasterizerState.CW_CullBack,
MultisampleState = MultisampleState.None
}
);
skyboxPipeline = new GraphicsPipeline(
GraphicsDevice,
new GraphicsPipelineCreateInfo
{
AttachmentInfo = new GraphicsPipelineAttachmentInfo(
TextureFormat.D16,
new ColorAttachmentDescription(
MainWindow.SwapchainFormat,
ColorAttachmentBlendState.Opaque
)
),
DepthStencilState = DepthStencilState.DepthReadWrite,
VertexShaderInfo = GraphicsShaderInfo.Create<Uniforms>(skyboxVertShaderModule, "main", 0),
VertexInputState = new VertexInputState(
VertexBinding.Create<PositionVertex>(),
VertexAttribute.Create<PositionVertex>("Position", 0)
),
PrimitiveType = PrimitiveType.TriangleList,
FragmentShaderInfo = GraphicsShaderInfo.Create(skyboxFragShaderModule, "main", 1),
RasterizerState = RasterizerState.CW_CullNone,
MultisampleState = MultisampleState.None,
}
);
}
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
}
);
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!");
}
protected override void Update(System.TimeSpan delta)
{
cubeTimer += (float) delta.TotalSeconds;
previousCubeRotation = cubeRotation;
cubeRotation = Quaternion.CreateFromYawPitchRoll(
cubeTimer * 2f,
0,
cubeTimer * 2f
);
}
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(
new Vector3(0, 1.5f, 4f),
Vector3.Zero,
Vector3.Up
);
Uniforms skyboxUniforms = new Uniforms(view * proj);
Matrix4x4 model = Matrix4x4.CreateFromQuaternion(
Quaternion.Slerp(
previousCubeRotation,
cubeRotation,
(float) alpha
)
);
Uniforms cubeUniforms = new Uniforms(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
{
cmdbuf.BeginRenderPass(
new DepthStencilAttachmentInfo(depthTexture, new DepthStencilValue(1f, 0)),
new ColorAttachmentInfo(swapchainTexture, Color.CornflowerBlue)
);
// Draw cube
cmdbuf.BindGraphicsPipeline(cubePipeline);
cmdbuf.BindVertexBuffers(cubeVertexBuffer);
cmdbuf.BindIndexBuffer(indexBuffer, IndexElementSize.ThirtyTwo);
uint vertexParamOffset = cmdbuf.PushVertexShaderUniforms(cubeUniforms);
cmdbuf.DrawIndexedPrimitives(0, 0, 12, vertexParamOffset, 0);
// Draw skybox
cmdbuf.BindGraphicsPipeline(skyboxPipeline);
cmdbuf.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();
}
}
GraphicsDevice.Submit(cmdbuf);
}
public static void Main(string[] args)
{
CubeGame game = new CubeGame();
game.Run();
}
}
}

View File

@ -4,7 +4,7 @@ using MoonWorks.Math.Float;
namespace MoonWorks.Test namespace MoonWorks.Test
{ {
internal class CullFaceGame : Game class CullFaceGame : Game
{ {
private GraphicsPipeline CW_CullNonePipeline; private GraphicsPipeline CW_CullNonePipeline;
private GraphicsPipeline CW_CullFrontPipeline; private GraphicsPipeline CW_CullFrontPipeline;

View File

@ -5,7 +5,7 @@ using System.Runtime.InteropServices;
namespace MoonWorks.Test namespace MoonWorks.Test
{ {
internal class GetBufferDataGame : Game class GetBufferDataGame : Game
{ {
public GetBufferDataGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true) public GetBufferDataGame() : base(TestUtils.GetStandardWindowCreateInfo(), TestUtils.GetStandardFrameLimiterSettings(), 60, true)
{ {

View File

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

View File

@ -0,0 +1,11 @@
#version 450
layout(location = 0) in vec3 TexCoord;
layout(location = 0) out vec4 FragColor;
layout(binding = 0, set = 1) uniform samplerCube SkyboxSampler;
void main()
{
FragColor = texture(SkyboxSampler, TexCoord);
}

View File

@ -0,0 +1,15 @@
#version 450
layout(location = 0) in vec3 inPos;
layout(location = 0) out vec3 vPos;
layout(set = 2, binding = 0) uniform UBO
{
mat4 ViewProjection;
} ubo;
void main()
{
vPos = inPos;
gl_Position = ubo.ViewProjection * vec4(inPos, 1.0);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 954 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

@ -49,5 +49,10 @@ namespace MoonWorks.Test
{ {
return SDL2.SDL.SDL_GetBasePath() + "Content/Shaders/Compiled/" + shaderName; return SDL2.SDL.SDL_GetBasePath() + "Content/Shaders/Compiled/" + shaderName;
} }
public static string GetTexturePath(string textureName)
{
return SDL2.SDL.SDL_GetBasePath() + "Content/Textures/" + textureName;
}
} }
} }

View File

@ -5,6 +5,22 @@ using MoonWorks.Math.Float;
namespace MoonWorks.Test namespace MoonWorks.Test
{ {
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct PositionVertex
{
public Vector3 Position;
public PositionVertex(Vector3 position)
{
Position = position;
}
public override string ToString()
{
return Position.ToString();
}
}
[StructLayout(LayoutKind.Sequential)]
public struct PositionColorVertex public struct PositionColorVertex
{ {
public Vector3 Position; public Vector3 Position;

View File

@ -25,6 +25,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GetBufferData", "GetBufferD
EndProject 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("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cube", "Cube\Cube.csproj", "{C3808AFD-23DD-4622-BFA7-981A344D0C19}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64 Debug|x64 = Debug|x64
@ -75,6 +77,10 @@ Global
{1695B1D8-4935-490C-A5EC-E2F2AA94B150}.Debug|x64.Build.0 = Debug|x64 {1695B1D8-4935-490C-A5EC-E2F2AA94B150}.Debug|x64.Build.0 = Debug|x64
{1695B1D8-4935-490C-A5EC-E2F2AA94B150}.Release|x64.ActiveCfg = Release|x64 {1695B1D8-4935-490C-A5EC-E2F2AA94B150}.Release|x64.ActiveCfg = Release|x64
{1695B1D8-4935-490C-A5EC-E2F2AA94B150}.Release|x64.Build.0 = Release|x64 {1695B1D8-4935-490C-A5EC-E2F2AA94B150}.Release|x64.Build.0 = Release|x64
{C3808AFD-23DD-4622-BFA7-981A344D0C19}.Debug|x64.ActiveCfg = Debug|x64
{C3808AFD-23DD-4622-BFA7-981A344D0C19}.Debug|x64.Build.0 = Debug|x64
{C3808AFD-23DD-4622-BFA7-981A344D0C19}.Release|x64.ActiveCfg = Release|Any CPU
{C3808AFD-23DD-4622-BFA7-981A344D0C19}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -35,3 +35,7 @@ Draws several triangles with various culling modes and winding orders.
**GetBufferData** **GetBufferData**
Sets buffer data, gets the data back from the GPU, and prints the results to the console. Sets buffer data, gets the data back from the GPU, and prints the results to the console.
**Cube**
Renders a cubemap skybox and a spinning cube. Tests depth texture, cube texture, and 32-bit index buffers.

View File

@ -81,7 +81,7 @@ namespace MoonWorks.Test
0, 2, 3, 0, 2, 3,
} }
); );
texture = Texture.LoadPNG(GraphicsDevice, cmdbuf, "Content/Textures/ravioli.png"); texture = Texture.LoadPNG(GraphicsDevice, cmdbuf, TestUtils.GetTexturePath("ravioli.png"));
GraphicsDevice.Submit(cmdbuf); GraphicsDevice.Submit(cmdbuf);
GraphicsDevice.Wait(); GraphicsDevice.Wait();
} }
@ -104,10 +104,10 @@ namespace MoonWorks.Test
cmdbuf.BindGraphicsPipeline(pipeline); cmdbuf.BindGraphicsPipeline(pipeline);
cmdbuf.BindVertexBuffers(vertexBuffer); cmdbuf.BindVertexBuffers(vertexBuffer);
cmdbuf.BindIndexBuffer(indexBuffer, IndexElementSize.Sixteen); cmdbuf.BindIndexBuffer(indexBuffer, IndexElementSize.Sixteen);
cmdbuf.PushVertexShaderUniforms(vertUniforms);
cmdbuf.BindFragmentSamplers(new TextureSamplerBinding(texture, sampler)); cmdbuf.BindFragmentSamplers(new TextureSamplerBinding(texture, sampler));
cmdbuf.PushFragmentShaderUniforms(fragUniforms); uint vertParamOffset = cmdbuf.PushVertexShaderUniforms(vertUniforms);
cmdbuf.DrawIndexedPrimitives(0, 0, 2, 0, 0); uint fragParamOffset = cmdbuf.PushFragmentShaderUniforms(fragUniforms);
cmdbuf.DrawIndexedPrimitives(0, 0, 2, vertParamOffset, fragParamOffset);
cmdbuf.EndRenderPass(); cmdbuf.EndRenderPass();
} }
GraphicsDevice.Submit(cmdbuf); GraphicsDevice.Submit(cmdbuf);

View File

@ -76,7 +76,7 @@ namespace MoonWorks.Test
0, 2, 3, 0, 2, 3,
} }
); );
texture = Texture.LoadPNG(GraphicsDevice, cmdbuf, "Content/Textures/ravioli.png"); texture = Texture.LoadPNG(GraphicsDevice, cmdbuf, TestUtils.GetTexturePath("ravioli.png"));
GraphicsDevice.Submit(cmdbuf); GraphicsDevice.Submit(cmdbuf);
GraphicsDevice.Wait(); GraphicsDevice.Wait();
} }