Skip to content

Instantly share code, notes, and snippets.

@TinkerWorX
Created June 4, 2020 13:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TinkerWorX/d4c06aadd16aff9b29bd0cd8a601eaf1 to your computer and use it in GitHub Desktop.
Save TinkerWorX/d4c06aadd16aff9b29bd0cd8a601eaf1 to your computer and use it in GitHub Desktop.
using System;
using System.Numerics;
using System.Text;
using Veldrid;
using Veldrid.SPIRV;
namespace Desolation.Graphics
{
public unsafe class QuadRenderer : IDisposable
{
private const string VertexCode = @"
#version 450
layout (location = 0) in vec3 Position;
layout (location = 1) in vec4 Color;
layout (location = 2) in vec2 TexCoords;
layout(set = 0, binding = 0) uniform vTransformBuffer
{
mat4x4 transform;
};
layout (location = 0) out vec4 fColor;
layout (location = 1) out vec2 fTexCoords;
void main()
{
gl_Position = transform * vec4(Position, 1.00);
fColor = Color;
fTexCoords = TexCoords;
}";
private const string FragmentCode = @"
#version 450
layout (location = 0) in vec4 fColor;
layout (location = 1) in vec2 fTexCoords;
layout(set = 1, binding = 0) uniform texture2D fTexture;
layout(set = 1, binding = 1) uniform sampler fTextureSampler;
layout (location = 0) out vec4 fOutColor;
void main()
{
fOutColor = texture(sampler2D(fTexture, fTextureSampler), fTexCoords) * fColor;
}";
private readonly DeviceBuffer vertexBuffer;
private readonly DeviceBuffer indexBuffer;
private readonly DeviceBuffer transformBuffer;
private readonly Shader[] shaders;
private readonly Pipeline pipeline;
private readonly ResourceSet transformSet;
private readonly ResourceSet textureSet;
public QuadRenderer(GraphicsDevice graphicsDevice, Texture texture, TextureView textureView)
{
var factory = graphicsDevice.ResourceFactory;
this.transformBuffer = factory.CreateBuffer(new BufferDescription((uint)sizeof(Matrix4x4), BufferUsage.UniformBuffer));
var quadVertices = new[]
{
new VertexPositionColorTexCoords(new Vector3(-0.75f, -0.75f, 0.00f), RgbaByte.Blue, new Vector2(0.00f, 0.00f)),
new VertexPositionColorTexCoords(new Vector3(+0.75f, -0.75f, 0.00f), RgbaByte.Yellow, new Vector2(1.00f, 0.00f)),
new VertexPositionColorTexCoords(new Vector3(-0.75f, +0.75f, 0.00f), RgbaByte.Red, new Vector2(0.00f, 1.00f)),
new VertexPositionColorTexCoords(new Vector3(+0.75f, +0.75f, 0.00f), RgbaByte.Green, new Vector2(1.00f, 1.00f)),
};
this.vertexBuffer = factory.CreateBuffer(new BufferDescription((uint)(quadVertices.Length * sizeof(VertexPositionColorTexCoords)), BufferUsage.VertexBuffer));
graphicsDevice.UpdateBuffer(this.vertexBuffer, 0, quadVertices);
ushort[] quadIndices = { 0, 1, 2, 1, 3, 2 };
this.indexBuffer = factory.CreateBuffer(new BufferDescription((uint)(quadIndices.Length * sizeof(ushort)), BufferUsage.IndexBuffer));
graphicsDevice.UpdateBuffer(this.indexBuffer, 0, quadIndices);
var vertexShaderDesc = new ShaderDescription(ShaderStages.Vertex, Encoding.UTF8.GetBytes(VertexCode), "main");
var fragmentShaderDesc = new ShaderDescription(ShaderStages.Fragment, Encoding.UTF8.GetBytes(FragmentCode), "main");
this.shaders = factory.CreateFromSpirv(vertexShaderDesc, fragmentShaderDesc, new CrossCompileOptions(false, true));
var transformLayout = factory.CreateResourceLayout(
new ResourceLayoutDescription(
new ResourceLayoutElementDescription("vTransformBuffer", ResourceKind.UniformBuffer, ShaderStages.Vertex)));
this.transformSet = factory.CreateResourceSet(new ResourceSetDescription(transformLayout, this.transformBuffer));
var textureLayout = factory.CreateResourceLayout(
new ResourceLayoutDescription(
new ResourceLayoutElementDescription("fTexture", ResourceKind.TextureReadOnly, ShaderStages.Fragment),
new ResourceLayoutElementDescription("fTextureSampler", ResourceKind.Sampler, ShaderStages.Fragment)));
this.textureSet = factory.CreateResourceSet(new ResourceSetDescription(textureLayout, textureView, graphicsDevice.Aniso4xSampler));
// Create pipeline
var pipelineDescription = new GraphicsPipelineDescription
{
BlendState = BlendStateDescription.SingleOverrideBlend,
DepthStencilState = new DepthStencilStateDescription(depthTestEnabled: true, depthWriteEnabled: true, comparisonKind: ComparisonKind.LessEqual),
RasterizerState = new RasterizerStateDescription(cullMode: FaceCullMode.None, fillMode: PolygonFillMode.Solid, frontFace: FrontFace.Clockwise, depthClipEnabled: true, scissorTestEnabled: false),
PrimitiveTopology = PrimitiveTopology.TriangleStrip,
ShaderSet = new ShaderSetDescription(vertexLayouts: new[] { VertexPositionColorTexCoords.VertexLayoutDescription }, shaders: this.shaders),
ResourceLayouts = new[] { transformLayout, textureLayout },
Outputs = graphicsDevice.SwapchainFramebuffer.OutputDescription,
};
this.pipeline = factory.CreateGraphicsPipeline(pipelineDescription);
}
public void Render(CommandList commandList)
{
commandList.UpdateBuffer(this.transformBuffer, 0, Matrix4x4.Identity);
// Set all relevant state to draw our quad.
commandList.SetVertexBuffer(0, this.vertexBuffer);
commandList.SetIndexBuffer(this.indexBuffer, IndexFormat.UInt16);
commandList.SetPipeline(this.pipeline);
commandList.SetGraphicsResourceSet(0, this.transformSet);
commandList.SetGraphicsResourceSet(1, this.textureSet);
// Issue a Draw command for a single instance with 6 indices.
commandList.DrawIndexed(indexCount: 6, instanceCount: 1, indexStart: 0, vertexOffset: 0, instanceStart: 0);
}
public void Dispose()
{
this.pipeline.Dispose();
foreach (var shader in this.shaders)
{
shader.Dispose();
}
this.indexBuffer.Dispose();
this.vertexBuffer.Dispose();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment