using MoonWorks; using MoonWorks.Audio; using MoonWorks.Graphics; using RefreshCS; 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; RefreshCS.Refresh.Rect renderArea; RefreshCS.Refresh.Rect flip; RefreshCS.Refresh.Color clearColor; Texture mainColorTargetTexture; TextureSlice mainColorTargetTextureSlice; ColorTarget mainColorTarget; RenderPass mainRenderPass; Framebuffer mainFramebuffer; GraphicsPipeline mainGraphicsPipeline; byte[] screenshotPixels; Buffer screenshotBuffer; uint screenShotBufferSize; Thread screenshotThread; StaticSound music; StaticSoundInstance musicInstance; 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, new System.IO.FileInfo("Content/passthrough_vert.spv")); raymarchFragmentShaderModule = new ShaderModule(GraphicsDevice, new System.IO.FileInfo("Content/hexagon_grid.spv")); raymarchUniforms.time = 0; raymarchUniforms.padding = 0; raymarchUniforms.resolutionX = windowWidth; raymarchUniforms.resolutionY = windowHeight; woodTexture = Texture.LoadPNG(GraphicsDevice, new System.IO.FileInfo("Content/woodgrain.png")); noiseTexture = Texture.LoadPNG(GraphicsDevice, new System.IO.FileInfo("Content/noise.png")); SamplerState samplerState = SamplerState.LinearWrap; sampler = new Sampler(GraphicsDevice, ref samplerState); /* 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, Refresh.BufferUsageFlags.Vertex, 4 * 5 * 3); vertexBuffer.SetData(0, vertices, 4 * 5 * 3); /* 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; Refresh.ColorTargetDescription colorTargetDescription = new Refresh.ColorTargetDescription { format = Refresh.ColorFormat.R8G8B8A8, multisampleCount = Refresh.SampleCount.One, loadOp = Refresh.LoadOp.Clear, storeOp = Refresh.StoreOp.Store }; mainRenderPass = new RenderPass(GraphicsDevice, colorTargetDescription); mainColorTargetTexture = Texture.CreateTexture2D( GraphicsDevice, windowWidth, windowHeight, Refresh.ColorFormat.R8G8B8A8, Refresh.TextureUsageFlags.ColorTargetBit ); mainColorTargetTextureSlice = new TextureSlice(mainColorTargetTexture); mainColorTarget = new ColorTarget(GraphicsDevice, Refresh.SampleCount.One, ref 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 = Refresh.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 = 4 }; MultisampleState multisampleState = MultisampleState.None; GraphicsPipelineLayoutCreateInfo pipelineLayoutCreateInfo = new GraphicsPipelineLayoutCreateInfo { VertexSamplerBindingCount = 0, FragmentSamplerBindingCount = 2 }; RasterizerState rasterizerState = RasterizerState.CullCounterClockwise; var vertexBindings = new Refresh.VertexBinding[1] { new Refresh.VertexBinding { binding = 0, inputRate = Refresh.VertexInputRate.Vertex, stride = 4 * 5 } }; var vertexAttributes = new Refresh.VertexAttribute[2] { new Refresh.VertexAttribute { binding = 0, location = 0, format = Refresh.VertexElementFormat.Vector3, offset = 0 }, new Refresh.VertexAttribute { binding = 0, location = 1, format = Refresh.VertexElementFormat.Vector2, offset = 4 * 3 } }; VertexInputState vertexInputState = new VertexInputState { VertexBindings = vertexBindings, VertexAttributes = vertexAttributes }; var viewports = new Refresh.Viewport[1] { new Refresh.Viewport { x = 0, y = 0, w = windowWidth, h = windowHeight, minDepth = 0, maxDepth = 1 } }; var scissors = new Refresh.Rect[1] { new Refresh.Rect { x = 0, y = 0, w = (int) windowWidth, h = (int) windowHeight } }; ViewportState viewportState = new ViewportState { Viewports = viewports, Scissors = scissors }; mainGraphicsPipeline = new GraphicsPipeline( GraphicsDevice, colorBlendState, depthStencilState, vertexShaderState, fragmentShaderState, multisampleState, pipelineLayoutCreateInfo, rasterizerState, Refresh.PrimitiveType.TriangleList, vertexInputState, viewportState, mainRenderPass ); screenShotBufferSize = windowWidth * windowHeight * 4; screenshotPixels = new byte[screenShotBufferSize]; screenshotBuffer = new Buffer(GraphicsDevice, 0, screenShotBufferSize); screenshotThread = new Thread(new ThreadStart(SaveScreenshot)); music = StaticSound.LoadOgg(AudioDevice, new FileInfo(Path.Combine("Content", "title_screen.ogg"))); musicInstance = music.CreateInstance(); musicInstance.Play(); //music = new DynamicSound(AudioDevice, new FileInfo(Path.Combine("Content", "title_screen.ogg"))); //musicInstance = music.CreateInstance(); //musicInstance.Play(); } protected override void Update(double dt) { raymarchUniforms.time += (float) dt; } protected override void Draw() { var screenshotPressed = Input.Keyboard.IsPressed(Keycode.S); var commandBuffer = GraphicsDevice.AcquireCommandBuffer(); commandBuffer.BeginRenderPass( mainRenderPass, mainFramebuffer, ref 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(ref mainColorTargetTextureSlice, screenshotBuffer); } commandBuffer.QueuePresent(ref mainColorTargetTextureSlice, ref flip, Refresh.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); } } }