MoonWorksComputeSpriteBatch/src/TestGame.cs

247 lines
6.7 KiB
C#

using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using MoonWorks;
using MoonWorks.Graphics;
using MoonWorks.Math;
using MoonWorks.Window;
namespace MoonWorksComputeSpriteBatch
{
public class TestGame : Game
{
private RenderTarget mainColorTarget;
private GraphicsPipeline spritePipeline;
private SpriteBatch spriteBatch;
private Texture whitePixel;
private Sampler sampler;
private const int SPRITECOUNT = SpriteBatch.MAX_SPRITES;
private Vector3[] positions = new Vector3[SPRITECOUNT];
private uint windowWidth;
private uint windowHeight;
private Random random = new Random();
public TestGame(WindowCreateInfo windowCreateInfo, PresentMode presentMode, int targetTimestep = 60, bool debugMode = false) : base(windowCreateInfo, presentMode, targetTimestep, debugMode)
{
windowWidth = windowCreateInfo.WindowWidth;
windowHeight = windowCreateInfo.WindowHeight;
var vertexShaderModule = new ShaderModule(GraphicsDevice, Path.Combine(Environment.CurrentDirectory, "Content", "sprite.vert.spv"));
var fragmentShaderModule = new ShaderModule(GraphicsDevice, Path.Combine(Environment.CurrentDirectory, "Content", "sprite.frag.spv"));
mainColorTarget = RenderTarget.CreateBackedRenderTarget(
GraphicsDevice,
windowWidth,
windowHeight,
TextureFormat.R8G8B8A8,
false
);
/* Pipeline */
ColorTargetBlendState[] colorTargetBlendStates = new ColorTargetBlendState[1]
{
ColorTargetBlendState.None
};
ColorBlendState colorBlendState = new ColorBlendState
{
LogicOpEnable = false,
LogicOp = LogicOp.NoOp,
BlendConstants = new BlendConstants(),
ColorTargetBlendStates = colorTargetBlendStates
};
DepthStencilState depthStencilState = DepthStencilState.Disable;
ShaderStageState vertexShaderState = new ShaderStageState
{
ShaderModule = vertexShaderModule,
EntryPointName = "main",
UniformBufferSize = (uint)Marshal.SizeOf<CameraUniforms>()
};
ShaderStageState fragmentShaderState = new ShaderStageState
{
ShaderModule = fragmentShaderModule,
EntryPointName = "main",
UniformBufferSize = 0
};
MultisampleState multisampleState = MultisampleState.None;
GraphicsPipelineLayoutInfo pipelineLayoutInfo = new GraphicsPipelineLayoutInfo
{
VertexSamplerBindingCount = 0,
FragmentSamplerBindingCount = 1
};
RasterizerState rasterizerState = RasterizerState.CCW_CullNone;
var vertexBindings = new VertexBinding[1]
{
new VertexBinding
{
Binding = 0,
InputRate = VertexInputRate.Vertex,
Stride = (uint) Marshal.SizeOf<VertexPositionTexcoord>()
}
};
var vertexAttributes = new VertexAttribute[3]
{
new VertexAttribute
{
Binding = 0,
Location = 0,
Format = VertexElementFormat.Vector3,
Offset = 0
},
new VertexAttribute
{
Binding = 0,
Location = 1,
Format = VertexElementFormat.Vector2,
Offset = (uint) Marshal.OffsetOf<VertexPositionTexcoord>("texcoord")
},
new VertexAttribute
{
Binding = 0,
Location = 2,
Format = VertexElementFormat.Vector4,
Offset = (uint) Marshal.OffsetOf<VertexPositionTexcoord>("color")
}
};
VertexInputState vertexInputState = new VertexInputState
{
VertexBindings = vertexBindings,
VertexAttributes = vertexAttributes
};
var viewports = new Viewport[1]
{
new Viewport
{
X = 0,
Y = 0,
W = windowWidth,
H = windowHeight,
MinDepth = 0,
MaxDepth = 1
}
};
var scissors = new Rect[1]
{
new Rect
{
X = 0,
Y = 0,
W = (int) windowWidth,
H = (int) windowHeight
}
};
ViewportState viewportState = new ViewportState
{
Viewports = viewports,
Scissors = scissors
};
var colorAttachmentDescriptions = new ColorAttachmentDescription[1]
{
new ColorAttachmentDescription
{
format = TextureFormat.R8G8B8A8,
sampleCount = SampleCount.One
}
};
GraphicsPipelineAttachmentInfo graphicsPipelineAttachmentInfo = new GraphicsPipelineAttachmentInfo
{
colorAttachmentDescriptions = colorAttachmentDescriptions,
colorAttachmentCount = 1,
hasDepthStencilAttachment = false,
depthStencilFormat = 0
};
var graphicsPipelineCreateInfo = new GraphicsPipelineCreateInfo
{
ColorBlendState = colorBlendState,
DepthStencilState = depthStencilState,
VertexShaderState = vertexShaderState,
FragmentShaderState = fragmentShaderState,
MultisampleState = multisampleState,
PipelineLayoutInfo = pipelineLayoutInfo,
RasterizerState = rasterizerState,
PrimitiveType = PrimitiveType.TriangleList,
VertexInputState = vertexInputState,
ViewportState = viewportState,
AttachmentInfo = graphicsPipelineAttachmentInfo
};
spritePipeline = new GraphicsPipeline(GraphicsDevice, graphicsPipelineCreateInfo);
spriteBatch = new SpriteBatch(GraphicsDevice);
whitePixel = Texture.CreateTexture2D(GraphicsDevice, 1, 1, TextureFormat.R8G8B8A8, TextureUsageFlags.Sampler);
var commandBuffer = GraphicsDevice.AcquireCommandBuffer();
commandBuffer.SetTextureData(whitePixel, new Color[] { Color.White });
GraphicsDevice.Submit(commandBuffer);
sampler = new Sampler(GraphicsDevice, SamplerCreateInfo.PointWrap);
}
protected override void Update(TimeSpan dt)
{
for (var i = 0; i < SPRITECOUNT; i += 1)
{
positions[i].X = (float)(random.NextDouble() * windowWidth) - 64;
positions[i].Y = (float)(random.NextDouble() * windowHeight) - 64;
}
}
protected override void Draw(TimeSpan dt, double alpha)
{
var commandBuffer = GraphicsDevice.AcquireCommandBuffer();
var viewProjection = Matrix4x4.CreateLookAt(new Vector3(windowWidth / 2, windowHeight / 2, 1), new Vector3(windowWidth / 2, windowHeight / 2, 0), Vector3.Up) * Matrix4x4.CreateOrthographic(windowWidth, windowHeight, 0.1f, 1000);
spriteBatch.Start(whitePixel, sampler);
for (var i = 0; i < SPRITECOUNT; i += 1)
{
var transform = Matrix4x4.CreateTranslation(positions[i]);
var color = new Color((float)random.NextDouble(), (float)random.NextDouble(), (float)random.NextDouble(), 255f);
spriteBatch.Add(new Sprite(new Rect { X = 0, Y = 0, W = 0, H = 0 }, 128, 128), transform, color);
}
var colorAttachmentInfo = new ColorAttachmentInfo
{
renderTarget = mainColorTarget,
clearColor = Color.Black,
loadOp = LoadOp.Clear,
storeOp = StoreOp.DontCare
};
spriteBatch.Flush(commandBuffer, colorAttachmentInfo, spritePipeline, new CameraUniforms { viewProjectionMatrix = viewProjection });
commandBuffer.QueuePresent(mainColorTarget.TextureSlice, Filter.Nearest, Window);
GraphicsDevice.Submit(commandBuffer);
}
protected override void OnDestroy()
{
}
}
}