MoonWorksTest/src/TestGame.cs

321 lines
10 KiB
C#

using MoonWorks;
using MoonWorks.Audio;
using MoonWorks.Graphics;
using MoonWorks.Input;
using MoonWorks.Window;
using System.IO;
using System.Threading;
namespace MoonWorksTest
{
public class TestGame : Game
{
ShaderModule passthroughVertexShaderModule;
ShaderModule raymarchFragmentShaderModule;
RaymarchUniforms raymarchUniforms;
Texture woodTexture;
Texture noiseTexture;
Sampler sampler;
Buffer vertexBuffer;
Rect renderArea;
Rect flip;
Color clearColor;
Texture mainColorTargetTexture;
TextureSlice mainColorTargetTextureSlice;
RenderTarget mainColorTarget;
RenderPass mainRenderPass;
Framebuffer mainFramebuffer;
GraphicsPipeline mainGraphicsPipeline;
byte[] screenshotPixels;
Buffer screenshotBuffer;
uint screenShotBufferSize;
Thread screenshotThread;
StaticSound music;
StaticSoundInstance musicInstance;
StreamingSoundOgg musicStream;
public TestGame(WindowCreateInfo windowCreateInfo, PresentMode presentMode, int targetTimestep = 60, bool debugMode = false) : base(windowCreateInfo, presentMode, targetTimestep, debugMode)
{
var windowWidth = windowCreateInfo.WindowWidth;
var windowHeight = windowCreateInfo.WindowHeight;
passthroughVertexShaderModule = new ShaderModule(GraphicsDevice, Path.Combine("Content", "passthrough_vert.spv"));
raymarchFragmentShaderModule = new ShaderModule(GraphicsDevice, Path.Combine("Content", "hexagon_grid.spv"));
raymarchUniforms.time = 0;
raymarchUniforms.padding = 0;
raymarchUniforms.resolutionX = windowWidth;
raymarchUniforms.resolutionY = windowHeight;
woodTexture = Texture.LoadPNG(GraphicsDevice, "Content/woodgrain.png");
noiseTexture = Texture.LoadPNG(GraphicsDevice, "Content/noise.png");
sampler = new Sampler(GraphicsDevice, SamplerCreateInfo.LinearWrap);
/* Load Vertex Data */
var vertices = new Vertex[3];
vertices[0].x = -1;
vertices[0].y = -1;
vertices[0].z = 0;
vertices[0].u = 0;
vertices[0].v = 1;
vertices[1].x = 3;
vertices[1].y = -1;
vertices[1].z = 0;
vertices[1].u = 1;
vertices[1].v = 1;
vertices[2].x = -1;
vertices[2].y = 3;
vertices[2].z = 0;
vertices[2].u = 0;
vertices[2].v = 0;
vertexBuffer = new Buffer(GraphicsDevice, BufferUsageFlags.Vertex, 4 * 5 * 3);
vertexBuffer.SetData(vertices);
/* Render Pass */
renderArea.X = 0;
renderArea.Y = 0;
renderArea.W = (int) windowWidth;
renderArea.H = (int) windowHeight;
flip.X = 0;
flip.Y = (int) windowHeight;
flip.W = (int) windowWidth;
flip.H = -(int) windowHeight;
clearColor.R = 237;
clearColor.G = 41;
clearColor.B = 57;
clearColor.A = byte.MaxValue;
ColorTargetDescription colorTargetDescription = new ColorTargetDescription
{
Format = TextureFormat.R8G8B8A8,
MultisampleCount = SampleCount.One,
LoadOp = LoadOp.Clear,
StoreOp = StoreOp.Store
};
mainRenderPass = new RenderPass(GraphicsDevice, colorTargetDescription);
mainColorTargetTexture = Texture.CreateTexture2D(
GraphicsDevice,
windowWidth,
windowHeight,
TextureFormat.R8G8B8A8,
TextureUsageFlags.ColorTarget
);
mainColorTargetTextureSlice = new TextureSlice(mainColorTargetTexture);
mainColorTarget = new RenderTarget(GraphicsDevice, mainColorTargetTextureSlice);
mainFramebuffer = new Framebuffer(
GraphicsDevice,
windowWidth,
windowHeight,
mainRenderPass,
null,
mainColorTarget
);
/* 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 = passthroughVertexShaderModule,
EntryPointName = "main",
UniformBufferSize = 0
};
ShaderStageState fragmentShaderState = new ShaderStageState
{
ShaderModule = raymarchFragmentShaderModule,
EntryPointName = "main",
UniformBufferSize = 16
};
MultisampleState multisampleState = MultisampleState.None;
GraphicsPipelineLayoutInfo pipelineLayoutInfo = new GraphicsPipelineLayoutInfo
{
VertexSamplerBindingCount = 0,
FragmentSamplerBindingCount = 2
};
RasterizerState rasterizerState = RasterizerState.CW_CullBack;
var vertexBindings = new VertexBinding[1]
{
new VertexBinding
{
Binding = 0,
InputRate = VertexInputRate.Vertex,
Stride = 4 * 5
}
};
var vertexAttributes = new VertexAttribute[2]
{
new VertexAttribute
{
Binding = 0,
Location = 0,
Format = VertexElementFormat.Vector3,
Offset = 0
},
new VertexAttribute
{
Binding = 0,
Location = 1,
Format = VertexElementFormat.Vector2,
Offset = 4 * 3
}
};
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 graphicsPipelineCreateInfo = new GraphicsPipelineCreateInfo
{
ColorBlendState = colorBlendState,
DepthStencilState = depthStencilState,
VertexShaderState = vertexShaderState,
FragmentShaderState = fragmentShaderState,
MultisampleState = multisampleState,
PipelineLayoutInfo = pipelineLayoutInfo,
RasterizerState = rasterizerState,
PrimitiveType = PrimitiveType.TriangleList,
VertexInputState = vertexInputState,
ViewportState = viewportState,
RenderPass = mainRenderPass
};
mainGraphicsPipeline = new GraphicsPipeline(
GraphicsDevice,
graphicsPipelineCreateInfo
);
screenShotBufferSize = windowWidth * windowHeight * 4;
screenshotPixels = new byte[screenShotBufferSize];
screenshotBuffer = new Buffer(GraphicsDevice, 0, screenShotBufferSize);
screenshotThread = new Thread(new ThreadStart(SaveScreenshot));
music = StaticSound.LoadOgg(AudioDevice, Path.Combine("Content", "title_screen.ogg"));
musicInstance = music.CreateInstance();
// musicInstance.Play();
musicStream = StreamingSoundOgg.Load(AudioDevice, Path.Combine("Content", "title_screen.ogg"), false, true);
musicStream.Play();
}
protected override void Update(double dt)
{
raymarchUniforms.time += (float) dt;
}
protected override void Draw(double dt, double alpha)
{
var screenshotPressed = Inputs.Keyboard.IsPressed(Keycode.S);
var commandBuffer = GraphicsDevice.AcquireCommandBuffer();
commandBuffer.BeginRenderPass(
mainRenderPass,
mainFramebuffer,
renderArea,
clearColor
);
commandBuffer.BindGraphicsPipeline(mainGraphicsPipeline);
var fragmentParamOffset = commandBuffer.PushFragmentShaderParams(raymarchUniforms);
commandBuffer.BindVertexBuffers(0, new BufferBinding(vertexBuffer, 0));
commandBuffer.BindFragmentSamplers(
new TextureSamplerBinding(woodTexture, sampler),
new TextureSamplerBinding(noiseTexture, sampler)
);
commandBuffer.DrawPrimitives(0, 1, 0, fragmentParamOffset);
commandBuffer.EndRenderPass();
if (screenshotPressed)
{
commandBuffer.CopyTextureToBuffer(mainColorTargetTextureSlice, screenshotBuffer);
}
commandBuffer.QueuePresent(mainColorTargetTextureSlice, flip, Filter.Nearest);
GraphicsDevice.Submit(commandBuffer);
if (screenshotPressed)
{
screenshotThread.Start();
}
}
private void SaveScreenshot()
{
GraphicsDevice.Wait();
screenshotBuffer.GetData(screenshotPixels, screenShotBufferSize);
Texture.SavePNG("screenshot.png", 1280, 720, screenshotPixels);
}
}
}