public static IndexedMesh createIndexed <TVertex, TIndex>(IRenderDevice device, TVertex[] vertices, TIndex[] indices, string name) where TVertex : unmanaged where TIndex : unmanaged { // Find index type GpuValueType indexType; switch (Type.GetTypeCode(typeof(TIndex))) { // https://stackoverflow.com/a/4902207/126995 case TypeCode.Int32: case TypeCode.UInt32: indexType = GpuValueType.Uint32; break; case TypeCode.Int16: case TypeCode.UInt16: indexType = GpuValueType.Uint16; break; case TypeCode.Byte: case TypeCode.SByte: indexType = GpuValueType.Uint8; break; default: throw new ArgumentException($"IndexedMesh.create: index type must be an integer, not { typeof( TIndex ).GetType().Name }"); } // Create vertex buffer BufferDesc VertBuffDesc = new BufferDesc(false) { Usage = Usage.Static, BindFlags = BindFlags.VertexBuffer, }; string vbName = nameVb(name); var vb = device.CreateBuffer(VertBuffDesc, vertices, vbName); // Create index buffer BufferDesc IndBuffDesc = new BufferDesc(false) { Usage = Usage.Static, BindFlags = BindFlags.IndexBuffer }; string ibName = nameIb(name); var ib = device.CreateBuffer(IndBuffDesc, indices, ibName); // Wrap both into the object return(new IndexedMesh(vb, ib, indices.Length, indexType)); }
/// <summary>Create buffer with initial content from a span</summary> public static IBuffer CreateBuffer <T>(this IRenderDevice device, BufferDesc desc, ReadOnlySpan <T> data, string name = null) where T : unmanaged { if (null == data || data.Length <= 0) { return(device.CreateBuffer(ref desc, name, IntPtr.Zero, 0)); } unsafe { int cb = Marshal.SizeOf <T>() * data.Length; fixed(T *pointer = data) return(device.CreateBuffer(ref desc, name, (IntPtr)pointer, cb)); } }
void createVertexBuffer(IRenderDevice device) { // Cube vertices // (-1,+1,+1)________________(+1,+1,+1) // /| /| // / | / | // / | / | // / | / | //(-1,-1,+1) /____|__________/(+1,-1,+1) // | |__________|____| // | /(-1,+1,-1) | /(+1,+1,-1) // | / | / // | / | / // |/ | / // /_______________|/ // (-1,-1,-1) (+1,-1,-1) // Vertex[] CubeVerts = new Vertex[] { vert(float3(-1, -1, -1), float2(0, 1)), vert(float3(-1, +1, -1), float2(0, 0)), vert(float3(+1, +1, -1), float2(1, 0)), vert(float3(+1, -1, -1), float2(1, 1)), vert(float3(-1, -1, -1), float2(0, 1)), vert(float3(-1, -1, +1), float2(0, 0)), vert(float3(+1, -1, +1), float2(1, 0)), vert(float3(+1, -1, -1), float2(1, 1)), vert(float3(+1, -1, -1), float2(0, 1)), vert(float3(+1, -1, +1), float2(1, 1)), vert(float3(+1, +1, +1), float2(1, 0)), vert(float3(+1, +1, -1), float2(0, 0)), vert(float3(+1, +1, -1), float2(0, 1)), vert(float3(+1, +1, +1), float2(0, 0)), vert(float3(-1, +1, +1), float2(1, 0)), vert(float3(-1, +1, -1), float2(1, 1)), vert(float3(-1, +1, -1), float2(1, 0)), vert(float3(-1, +1, +1), float2(0, 0)), vert(float3(-1, -1, +1), float2(0, 1)), vert(float3(-1, -1, -1), float2(1, 1)), vert(float3(-1, -1, +1), float2(1, 1)), vert(float3(+1, -1, +1), float2(0, 1)), vert(float3(+1, +1, +1), float2(0, 0)), vert(float3(-1, +1, +1), float2(1, 0)), }; BufferDesc VertBuffDesc = new BufferDesc(false) { Usage = Usage.Static, BindFlags = BindFlags.VertexBuffer, }; cubeVertexBuffer = device.CreateBuffer(VertBuffDesc, CubeVerts, "Cube vertex buffer"); }
/// <summary>Create buffer with initial content from the specified structure</summary> public static IBuffer CreateBuffer <T>(this IRenderDevice device, BufferDesc desc, ref T data, string name = null) where T : unmanaged { unsafe { fixed(T *pointer = &data) return(device.CreateBuffer(ref desc, name, (IntPtr)pointer, Marshal.SizeOf <T>())); } }
/// <summary>Create dynamic buffer for shader constants</summary> public static IBuffer CreateDynamicUniformBuffer(this IRenderDevice device, int cb, string name = null) { BufferDesc CBDesc = new BufferDesc(false); CBDesc.uiSizeInBytes = cb; CBDesc.Usage = Usage.Dynamic; CBDesc.BindFlags = BindFlags.UniformBuffer; CBDesc.CPUAccessFlags = CpuAccessFlags.Write; return(device.CreateBuffer(CBDesc, name)); }
static IBuffer createVertexBuffer(IRenderDevice device) { Vector2[] vertices = new Vector2[4] { new Vector2(1, 0), new Vector2(0, 0), new Vector2(1, 1), new Vector2(0, 1), }; BufferDesc VertBuffDesc = new BufferDesc(false) { Usage = Usage.Static, BindFlags = BindFlags.VertexBuffer, }; return(device.CreateBuffer(VertBuffDesc, vertices, "Cursor vertex buffer")); }
/// <summary>Create immutable VB with the full-screen triangle with cropping-included texture coordinates</summary> public static IBuffer createVideoVertexBuffer(IRenderDevice device, CSize renderTargetSize, ref sDecodedVideoSize videoSize) { Span <sVideoVertex> data = stackalloc sVideoVertex[3]; produceVertices(data, renderTargetSize, ref videoSize); BufferDesc desc = new BufferDesc(false) { uiSizeInBytes = 16 * 3, BindFlags = BindFlags.VertexBuffer, Usage = Usage.Static, }; ReadOnlySpan <sVideoVertex> readOnly = data; return(device.CreateBuffer(desc, readOnly, "Video VB")); }
/// <summary>Create immutable buffer for shader constants.</summary> public static IBuffer CreateImmutableUniformBuffer <T>(this IRenderDevice device, ref T data, string name = null) where T : unmanaged { int cb = Marshal.SizeOf <T>(); if (0 != cb % 16) { throw new ArgumentException($"Constant buffer size must be a multiple of 16 bytes, yet sizeof( { typeof( T ).FullName } ) = { cb }"); } BufferDesc desc = new BufferDesc(false) { uiSizeInBytes = cb, BindFlags = BindFlags.UniformBuffer, Usage = Usage.Static, }; return(device.CreateBuffer(desc, ref data, name)); }
void createIndexBuffer(IRenderDevice device) { ushort[] Indices = new ushort[] { 2, 0, 1, 2, 3, 0, 4, 6, 5, 4, 7, 6, 8, 10, 9, 8, 11, 10, 12, 14, 13, 12, 15, 14, 16, 18, 17, 16, 19, 18, 20, 21, 22, 20, 22, 23 }; BufferDesc IndBuffDesc = new BufferDesc(false) { Usage = Usage.Static, BindFlags = BindFlags.IndexBuffer }; cubeIndexBuffer = device.CreateBuffer(IndBuffDesc, Indices, "Cube index buffer"); }
void createVertexBuffer(IRenderDevice device) { // Cube vertices // (-1,+1,+1)________________(+1,+1,+1) // /| /| // / | / | // / | / | // / | / | //(-1,-1,+1) /____|__________/(+1,-1,+1) // | |__________|____| // | /(-1,+1,-1) | /(+1,+1,-1) // | / | / // | / | / // |/ | / // /_______________|/ // (-1,-1,-1) (+1,-1,-1) // // clang-format off Vertex[] CubeVerts = new Vertex[8] { vert(v3(-1, -1, -1), v4(1, 0, 0, 1)), vert(v3(-1, +1, -1), v4(0, 1, 0, 1)), vert(v3(+1, +1, -1), v4(0, 0, 1, 1)), vert(v3(+1, -1, -1), v4(1, 1, 1, 1)), vert(v3(-1, -1, +1), v4(1, 1, 0, 1)), vert(v3(-1, +1, +1), v4(0, 1, 1, 1)), vert(v3(+1, +1, +1), v4(1, 0, 1, 1)), vert(v3(+1, -1, +1), v4(0.2f, 0.2f, 0.2f, 1)), }; BufferDesc VertBuffDesc = new BufferDesc(false) { Usage = Usage.Static, BindFlags = BindFlags.VertexBuffer, }; cubeVertexBuffer = device.CreateBuffer(VertBuffDesc, CubeVerts, "Cube vertex buffer"); }
void createIndexBuffer(IRenderDevice device) { // clang-format off uint[] Indices = new uint[] { 2, 0, 1, 2, 3, 0, 4, 6, 5, 4, 7, 6, 0, 7, 4, 0, 3, 7, 1, 0, 4, 1, 4, 5, 1, 5, 2, 5, 6, 2, 3, 6, 7, 3, 2, 6 }; // clang-format on BufferDesc IndBuffDesc = new BufferDesc(false) { Usage = Usage.Static, BindFlags = BindFlags.IndexBuffer }; cubeIndexBuffer = device.CreateBuffer(IndBuffDesc, Indices, "Cube index buffer"); }
void createPipelineState(IRenderDevice device, iStorageFolder assets) { PipelineStateDesc PSODesc = new PipelineStateDesc(false); PSODesc.setBufferFormats(context); // Primitive topology defines what kind of primitives will be rendered by this pipeline state PSODesc.GraphicsPipeline.PrimitiveTopology = PrimitiveTopology.TriangleList; // Cull back faces PSODesc.GraphicsPipeline.RasterizerDesc.CullMode = CullMode.Back; // Enable depth testing PSODesc.GraphicsPipeline.DepthStencilDesc.DepthEnable = true; iShaderFactory shaderFactory = device.GetShaderFactory(); // We won't be using the factory object after this, `using` to release the COM interface once finished using (iPipelineStateFactory stateFactory = device.CreatePipelineStateFactory()) { stateFactory.setName("Cube PSO"); // Compile the two shaders ShaderSourceInfo sourceInfo = new ShaderSourceInfo(ShaderType.Vertex, ShaderSourceLanguage.Hlsl); sourceInfo.combinedTextureSamplers = true; // This appears to be the requirement of OpenGL backend. // In this tutorial, we will load shaders from resources embedded into this .NET DLL. var vs = shaderFactory.compileFromFile(assets, "cube.vsh", sourceInfo, "Cube VS"); stateFactory.graphicsVertexShader(vs); // Create dynamic uniform buffer that will store our transformation matrix. Dynamic buffers can be frequently updated by the CPU. BufferDesc CBDesc = new BufferDesc(false); CBDesc.uiSizeInBytes = Marshal.SizeOf <Matrix4x4>(); CBDesc.Usage = Usage.Dynamic; CBDesc.BindFlags = BindFlags.UniformBuffer; CBDesc.CPUAccessFlags = CpuAccessFlags.Write; vsConstants = device.CreateBuffer(CBDesc, "VS constants CB"); // Create a pixel shader sourceInfo.shaderType = ShaderType.Pixel; var ps = shaderFactory.compileFromFile(assets, "cube.psh", sourceInfo, "Cube PS"); stateFactory.graphicsPixelShader(ps); // Define vertex shader input layout // Attribute 0 - vertex position LayoutElement elt = new LayoutElement(false) { InputIndex = 0, BufferSlot = 0, NumComponents = 3, ValueType = GpuValueType.Float32, IsNormalized = false }; stateFactory.graphicsLayoutElement(elt); // Attribute 1 - texture coordinates elt.InputIndex = 1; elt.NumComponents = 2; stateFactory.graphicsLayoutElement(elt); // Define variable type that will be used by default PSODesc.ResourceLayout.DefaultVariableType = ShaderResourceVariableType.Static; // Shader variables should typically be mutable, which means they are expected to change on a per-instance basis stateFactory.layoutVariable(ShaderType.Pixel, ShaderResourceVariableType.Mutable, "g_Texture"); // Define static sampler for g_Texture. Static samplers should be used whenever possible. // The default constructor is good enough, it sets FilterType.Linear and TextureAddressMode.Clamp for all 3 coordinates. SamplerDesc samplerDesc = new SamplerDesc(false); stateFactory.layoutStaticSampler(ShaderType.Pixel, ref samplerDesc, "g_Texture"); stateFactory.apply(ref PSODesc); pipelineState = device.CreatePipelineState(ref PSODesc); } // Since we did not explicitly specify the type for 'Constants' variable, default // type (SHADER_RESOURCE_VARIABLE_TYPE_STATIC) will be used. Static variables never // change and are bound directly through the pipeline state object. pipelineState.GetStaticVariableByName(ShaderType.Vertex, "Constants").Set(vsConstants); // Since we are using mutable variable, we must create a shader resource binding object // http://diligentgraphics.com/2016/03/23/resource-binding-model-in-diligent-engine-2-0/ resourceBinding = pipelineState.CreateShaderResourceBinding(true); }
/// <summary>Create a buffer without initial data</summary> public static IBuffer CreateBuffer(this IRenderDevice device, BufferDesc desc, string name = null) { return(device.CreateBuffer(ref desc, name, IntPtr.Zero, 0)); }
void createPipelineState(IRenderDevice device) { PipelineStateDesc PSODesc = new PipelineStateDesc(false); PSODesc.setBufferFormats(context); // Primitive topology defines what kind of primitives will be rendered by this pipeline state PSODesc.GraphicsPipeline.PrimitiveTopology = PrimitiveTopology.TriangleList; // Cull back faces PSODesc.GraphicsPipeline.RasterizerDesc.CullMode = CullMode.Back; // Enable depth testing PSODesc.GraphicsPipeline.DepthStencilDesc.DepthEnable = true; iShaderFactory shaderFactory = device.GetShaderFactory(); // We won't be using the device object after this, `using` is to release the COM interface once finished using (iPipelineStateFactory stateFactory = device.CreatePipelineStateFactory()) { stateFactory.setName("Cube PSO"); // Compile the two shaders ShaderSourceInfo sourceInfo = new ShaderSourceInfo(ShaderType.Vertex, ShaderSourceLanguage.Hlsl); sourceInfo.combinedTextureSamplers = true; // This appears to be the requirement of OpenGL backend. // In this tutorial, we will load shaders from resources embedded into this .NET DLL. iStorageFolder resources = StorageFolder.embeddedResources(Assembly.GetExecutingAssembly(), "RenderSamples/02-Cube"); var vs = shaderFactory.compileFromFile(resources, "cube.vsh", sourceInfo, "Cube VS"); stateFactory.graphicsVertexShader(vs); // Create dynamic uniform buffer that will store our transformation matrix. Dynamic buffers can be frequently updated by the CPU. BufferDesc CBDesc = new BufferDesc(false); CBDesc.uiSizeInBytes = Marshal.SizeOf <Matrix4x4>(); CBDesc.Usage = Usage.Dynamic; CBDesc.BindFlags = BindFlags.UniformBuffer; CBDesc.CPUAccessFlags = CpuAccessFlags.Write; vsConstants = device.CreateBuffer(CBDesc, "VS constants CB"); // Create a pixel shader sourceInfo.shaderType = ShaderType.Pixel; var ps = shaderFactory.compileFromFile(resources, "cube.psh", sourceInfo, "Cube PS"); stateFactory.graphicsPixelShader(ps); // Define vertex shader input layout // Attribute 0 - vertex position LayoutElement elt = new LayoutElement(false) { InputIndex = 0, BufferSlot = 0, NumComponents = 3, ValueType = GpuValueType.Float32, IsNormalized = false }; stateFactory.graphicsLayoutElement(elt); // Attribute 1 - vertex color elt.InputIndex = 1; elt.NumComponents = 4; stateFactory.graphicsLayoutElement(elt); // Define variable type that will be used by default PSODesc.ResourceLayout.DefaultVariableType = ShaderResourceVariableType.Static; stateFactory.apply(ref PSODesc); pipelineState = device.CreatePipelineState(ref PSODesc); } // Since we did not explicitly specify the type for 'Constants' variable, default // type (SHADER_RESOURCE_VARIABLE_TYPE_STATIC) will be used. Static variables never // change and are bound directly through the pipeline state object. pipelineState.GetStaticVariableByName(ShaderType.Vertex, "Constants").Set(vsConstants); // Create a shader resource binding object and bind all static resources in it resourceBinding = pipelineState.CreateShaderResourceBinding(true); }