Last active
March 30, 2018 13:19
-
-
Save axefrog/6972449 to your computer and use it in GitHub Desktop.
Game Dev Samples
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Windows.Forms; | |
using SharpDX; | |
using SharpDX.D3DCompiler; | |
using SharpDX.Direct3D; | |
using SharpDX.Direct3D11; | |
using SharpDX.DXGI; | |
using SharpDX.Windows; | |
using Buffer = SharpDX.Direct3D11.Buffer; | |
using Device = SharpDX.Direct3D11.Device; | |
namespace SharpDx2 | |
{ | |
class Game : IDisposable | |
{ | |
private RenderForm _form; | |
private Device _device; | |
private SwapChain _swapChain; | |
private Viewport _viewport; | |
private DeviceContext _context; | |
private RenderTargetView _renderTarget; | |
private VertexShader _vertexShader; | |
private PixelShader _pixelShader; | |
private ShaderSignature _inputSignature; | |
private DataStream _vertices; | |
private Buffer _vertexBuffer; | |
private InputLayout _layout; | |
[STAThread] | |
public static void Main() | |
{ | |
using (var game = new Game()) | |
{ | |
game.Initialize(); | |
game.Run(); | |
} | |
} | |
public void Initialize() | |
{ | |
_form = new RenderForm("SharpDX : Hello, Triangle"); | |
_form.Width = 800; | |
_form.Height = 600; | |
_form.AllowUserResizing = true; | |
_form.KeyDown += (sender, e) => | |
{ | |
// handle the transition between full-screen and windowed mode | |
if (_swapChain != null && e.Alt && e.KeyCode == Keys.Enter) | |
_swapChain.IsFullScreen = !_swapChain.IsFullScreen; | |
}; | |
var description = new SwapChainDescription | |
{ | |
BufferCount = 1, // because the desktop window is an implicit front buffer, we only need one buffer here | |
IsWindowed = true, // always start in windowed mode (can change later) | |
SwapEffect = SwapEffect.Discard, // discard because I don't need to preserve the buffer contents after presentation | |
OutputHandle = _form.Handle, // the window on which we'll be doing our rendering | |
Usage = Usage.RenderTargetOutput, // the buffer is to be rendered to the render target (as opposed to using it for shader input) | |
Flags = SwapChainFlags.AllowModeSwitch, // allows me to resize and switch between windowed and full-screen mode | |
ModeDescription = new ModeDescription(0, 0, new Rational(60, 1), Format.R8G8B8A8_UNorm), // display mode for the swap chain (dimensions, refresh rate, pixel format) | |
SampleDescription = new SampleDescription(1, 0) // specifies antialiasing preferences: samples per pixel, anti aliasing quality level | |
}; | |
Device.CreateWithSwapChain( | |
DriverType.Hardware, // we explicitly want to use only a hardware device, not a software device | |
DeviceCreationFlags.BgraSupport, // force the the device creation to fail if BGRA support is missing | |
description, out _device, out _swapChain | |
); | |
// The context is like a GDI graphics context, but specific to the types of things you render using Direct3D. | |
// It is possible to render to different contexts in different threads. We don't care about that right now, so this is all we need. | |
_context = _device.ImmediateContext; | |
// Apparently DXGI doesn't play nicely with WinForms when switching between windowed and full-screen mode, so we handle that case manually | |
using(var factory = _swapChain.GetParent<Factory>()) | |
factory.MakeWindowAssociation(_form.Handle, WindowAssociationFlags.IgnoreAltEnter); | |
// The viewport specifies the bounds of our rendering. What's rendered here will be projected onto the render target (the back buffer, in this case). | |
_viewport = new Viewport(0, 0, _form.ClientSize.Width, _form.ClientSize.Height); | |
// The rasterizer is one of the the stages in the pipeline - we have to set the viewport for that stage so it knows the bounds inside which to render | |
_context.Rasterizer.SetViewport(_viewport); | |
// We have to get a reference to the back buffer from the swap chain, because that's where we'll be rendering onto. What we get back though is just | |
// a reference though, and though RenderTargetView constructs itself using information from the resource, we dispose the resource when done because | |
// the RenderTargetView constructor doesn't need it anymore. | |
using(var resource = SharpDX.Direct3D11.Resource.FromSwapChain<Texture2D>(_swapChain, 0)) | |
_renderTarget = new RenderTargetView(_device, resource); | |
// The output merger combines all the pixel data and sends it to the render target(s) | |
_context.OutputMerger.SetTargets(_renderTarget); | |
// This is our conduit into video memory for building up a mesh | |
_vertices = new DataStream(12*3, true, true); | |
// Prepare the three vertices of our triangle | |
_vertices.Write(new Vector3(0.0f, 0.5f, 0.5f)); | |
_vertices.Write(new Vector3(0.5f, -0.5f, 0.5f)); | |
_vertices.Write(new Vector3(-0.5f, -0.5f, 0.5f)); | |
// We have to seek back to position 0, ready for Direct3D to read from the stream | |
_vertices.Position = 0; | |
// Prepares a buffer specifically to contain vertex data, ready to be loaded into the pipeline | |
_vertexBuffer = new Buffer(_device, _vertices, 12*3, ResourceUsage.Default, | |
BindFlags.VertexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0); | |
// Compile our shaders, which will get the vertices into the correct screen coordinates and display the pixels with the correct colours | |
var shaders = Resources.shaders; // I have stored the shader program in a resx file, to make loading it easier | |
using(var bytecode = ShaderBytecode.Compile(shaders, "VShader", "vs_4_0")) | |
{ | |
_inputSignature = ShaderSignature.GetInputSignature(bytecode); | |
_vertexShader = new VertexShader(_device, bytecode); | |
} | |
using(var bytecode = ShaderBytecode.Compile(shaders, "PShader", "ps_4_0")) | |
_pixelShader = new PixelShader(_device, bytecode); | |
// Get the inputs to provide to the vertex shader | |
var elements = new[] { new InputElement("POSITION", 0, Format.R32G32B32_Float, 0) }; | |
_layout = new InputLayout(_device, _inputSignature, elements); | |
_context.InputAssembler.InputLayout = _layout; | |
_context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; | |
_context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(_vertexBuffer, 12, 0)); | |
_context.VertexShader.Set(_vertexShader); | |
_context.PixelShader.Set(_pixelShader); | |
} | |
public void Run() | |
{ | |
RenderLoop.Run(_form, MainLoop); | |
} | |
private void MainLoop() | |
{ | |
_context.ClearRenderTargetView(_renderTarget, new Color4(Color3.White)); | |
_context.Draw(3, 0); | |
_swapChain.Present(0, PresentFlags.None); | |
} | |
public void Dispose() | |
{ | |
_vertices.Close(); | |
_vertexBuffer.Dispose(); | |
_layout.Dispose(); | |
_inputSignature.Dispose(); | |
_vertexShader.Dispose(); | |
_pixelShader.Dispose(); | |
_renderTarget.Dispose(); | |
_swapChain.Dispose(); | |
_device.Dispose(); | |
_form.Dispose(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
float4 VShader(float4 position : POSITION) : SV_POSITION | |
{ | |
return position; | |
} | |
float4 PShader(float4 position : SV_POSITION) : SV_Target | |
{ | |
return float4(1.0f, 1.0f, 0.0f, 1.0f); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you 😄