/// <summary> /// Function to create a new vertex buffer and fill it with the vertices that represent our triangle. /// </summary> private static void CreateVertexBuffer() { // Define the points that make up our triangle. // We'll push it back half a unit along the Z-Axis so that we can see it. MiniTriVertex[] vertices = { // Note that we're assigning the texture coordinates in pixel space. The ToTexel function on the texture will convert these into // texel space for us. new MiniTriVertex(new DX.Vector3(0, 0.5f, 1.0f), _texture.ToTexel(new DX.Point(128, 3))), new MiniTriVertex(new DX.Vector3(0.5f, -0.5f, 1.0f), _texture.ToTexel(new DX.Point(230, 252))), new MiniTriVertex(new DX.Vector3(-0.5f, -0.5f, 1.0f), _texture.ToTexel(new DX.Point(23, 252))) }; // Create the vertex buffer. // // This will be responsible for sending vertex data to the GPU. The buffer size is specified in bytes, so we need to ensure it has enough room to hold all // 3 vertices. _vertexBuffer = GorgonVertexBufferBinding.CreateVertexBuffer <MiniTriVertex>(_graphics, new GorgonVertexBufferInfo("MiniTri Vertex Buffer") { Usage = ResourceUsage.Default, SizeInBytes = MiniTriVertex.SizeInBytes * vertices.Length }); // Send the vertex data into the buffer. _vertexBuffer.VertexBuffer.SetData(vertices); }
/// <summary> /// Function to create a new vertex buffer and fill it with the vertices that represent our triangle. /// </summary> private static void CreateVertexBuffer() { // Define the points that make up our triangle. // We'll push it back half a unit along the Z-Axis so that we can see it. MiniTriVertex[] vertices = { new MiniTriVertex(new DX.Vector3(0, 0.5f, 1.0f), new GorgonColor(1, 0, 0)), new MiniTriVertex(new DX.Vector3(0.5f, -0.5f, 1.0f), new GorgonColor(0, 1, 0)), new MiniTriVertex(new DX.Vector3(-0.5f, -0.5f, 1.0f), new GorgonColor(0, 0, 1)) }; // Create the vertex buffer. // // This will be responsible for sending vertex data to the GPU. The buffer size is specified in bytes, so we need to ensure it has enough room to hold all // 3 vertices. _vertexBuffer = GorgonVertexBufferBinding.CreateVertexBuffer <MiniTriVertex>(_graphics, new GorgonVertexBufferInfo("MiniTri Vertex Buffer") { Usage = ResourceUsage.Default, SizeInBytes = MiniTriVertex.SizeInBytes * vertices.Length }); // Send the vertex data into the buffer. _vertexBuffer.VertexBuffer.SetData(vertices); }
/// <summary> /// Initializes a new instance of the <see cref="Cube"/> class. /// </summary> /// <param name="graphics">The graphics object used to create the buffers needed by this object.</param> /// <param name="inputLayout">The input layout describing how a vertex is laid out.</param> public Cube(GorgonGraphics graphics, GorgonInputLayout inputLayout) { CubeVertex[] vertices = { new CubeVertex(new DX.Vector3(-0.5f, 0.5f, -0.5f), new DX.Vector3(0, 0, 0)), new CubeVertex(new DX.Vector3(0.5f, 0.5f, -0.5f), new DX.Vector3(1.0f, 1.0f, 0)), new CubeVertex(new DX.Vector3(0.5f, -0.5f, -0.5f), new DX.Vector3(0.0f, 1.0f, 0)), new CubeVertex(new DX.Vector3(-0.5f, -0.5f, -0.5f), new DX.Vector3(1.0f, 0.0f, 0)), new CubeVertex(new DX.Vector3(-0.5f, 0.5f, 0.5f), new DX.Vector3(0, 0, 0)), new CubeVertex(new DX.Vector3(0.5f, 0.5f, 0.5f), new DX.Vector3(1.0f, 1.0f, 0)), new CubeVertex(new DX.Vector3(0.5f, -0.5f, 0.5f), new DX.Vector3(0.0f, 1.0f, 0)), new CubeVertex(new DX.Vector3(-0.5f, -0.5f, 0.5f), new DX.Vector3(1.0f, 0.0f, 0)), }; ushort[] indices = { // Front face. 0, 1, 2, 2, 3, 0, // Back face. 5, 4, 6, 4, 7, 6, // Left face. 4, 0, 3, 3, 7, 4, // Right face. 1, 5, 6, 6, 2, 1, // Top face 4, 5, 1, 1, 0, 4, // Bottom face 2, 6, 7, 7, 3, 2 }; // Create our index buffer and vertex buffer and populate with our cube data. using (var indexPtr = GorgonNativeBuffer <ushort> .Pin(indices)) using (var vertexPtr = GorgonNativeBuffer <CubeVertex> .Pin(vertices)) { IndexBuffer = new GorgonIndexBuffer(graphics, new GorgonIndexBufferInfo("Volume Index Buffer") { Usage = ResourceUsage.Immutable, IndexCount = indices.Length, Use16BitIndices = true }, indexPtr); VertexBuffer = new GorgonVertexBufferBindings(inputLayout) { [0] = GorgonVertexBufferBinding.CreateVertexBuffer(graphics, vertices.Length, ResourceUsage.Immutable, initialData: vertexPtr, bufferName: "Volume Vertex Buffer") }; } }
/// <summary> /// Function to return the object. /// </summary> /// <returns>The object created or updated by this builder.</returns> /// <exception cref="GorgonException">Thrown if the polygonal sprite has less than 3 vertices.</exception> /// <remarks> /// <para> /// This will return a <see cref="GorgonPolySprite"/> for use with the <see cref="Gorgon2D.DrawPolygonSprite"/> method. The object returned implements <see cref="IDisposable"/>, so it is the /// responsibility of the user to dispose of the object when they are done with it. /// </para> /// <para> /// <note type="warning"> /// <para> /// A polygon sprite must have a minimum of 3 vertices. If it does not, then this method will throw an exception. /// </para> /// </note> /// </para> /// </remarks> /// <seealso cref="GorgonPolySprite"/> /// <seealso cref="Gorgon2D"/> public GorgonPolySprite Build() { if (_workingSprite.RwVertices.Count < 3) { throw new GorgonException(GorgonResult.CannotCreate, Resources.GOR2D_ERR_POLY_SPRITE_NOT_ENOUGH_VERTS); } var newSprite = new GorgonPolySprite(); CopySprite(newSprite, _workingSprite); newSprite.Renderable.ActualVertexCount = newSprite.RwVertices.Count; if ((newSprite.Renderable.Vertices == null) || (newSprite.Renderable.Vertices.Length < newSprite.RwVertices.Count)) { newSprite.Renderable.Vertices = new Gorgon2DVertex[newSprite.RwVertices.Count]; } for (int i = 0; i < newSprite.RwVertices.Count; ++i) { newSprite.Renderable.Vertices[i] = newSprite.RwVertices[i].Vertex; } // Enforce clockwise ordering. _triangulator.EnsureWindingOrder(newSprite.Renderable.Vertices, WindingOrder.CounterClockwise); // Split the polygon hull into triangles. (GorgonNativeBuffer <int> indices, DX.RectangleF bounds) = _triangulator.Triangulate(newSprite.Renderable.Vertices, WindingOrder.CounterClockwise); GorgonNativeBuffer <Gorgon2DVertex> vertexData = newSprite.Renderable.Vertices.ToNativeBuffer(); try { newSprite.Renderable.IndexBuffer = new GorgonIndexBuffer(Graphics, new GorgonIndexBufferInfo { Binding = VertexIndexBufferBinding.None, Use16BitIndices = false, IndexCount = indices.Length, Usage = ResourceUsage.Immutable }, indices); newSprite.Renderable.VertexBuffer = GorgonVertexBufferBinding.CreateVertexBuffer(Graphics, new GorgonVertexBufferInfo { Usage = ResourceUsage.Immutable, Binding = VertexIndexBufferBinding.None, SizeInBytes = Gorgon2DVertex.SizeInBytes * newSprite.RwVertices.Count }, vertexData); newSprite.Renderable.ActualVertexCount = newSprite.RwVertices.Count; newSprite.Renderable.IndexCount = indices.Length; newSprite.Bounds = new DX.RectangleF(newSprite.Position.X, newSprite.Position.Y, bounds.Width, bounds.Height); } finally { vertexData?.Dispose(); indices?.Dispose(); } return(newSprite); }
/// <summary> /// Initializes a new instance of the <see cref="Plane" /> class. /// </summary> /// <param name="graphics">The graphics interface used to create the buffers for this object.</param> /// <param name="inputLayout">The input layout for the vertices in this mesh.</param> /// <param name="size">The width and height of the plane.</param> /// <param name="textureCoordinates">Texture coordinates.</param> public Plane(GorgonGraphics graphics, GorgonInputLayout inputLayout, DX.Vector2 size, DX.RectangleF textureCoordinates) : base(inputLayout) { Size = size; // Create our vertices. Vertices = new[] { new BoingerVertex(new DX.Vector3(-size.X, size.Y, 0.0f), textureCoordinates.Location), new BoingerVertex(new DX.Vector3(size.X, size.Y, 0.0f), new DX.Vector2(textureCoordinates.Right, textureCoordinates.Top)), new BoingerVertex(new DX.Vector3(-size.X, -size.Y, 0.0f), new DX.Vector2(textureCoordinates.Left, textureCoordinates.Bottom)), new BoingerVertex(new DX.Vector3(size.X, -size.Y, 0.0f), new DX.Vector2(textureCoordinates.Right, textureCoordinates.Bottom)) }; // Create our indices. Indices = new ushort[] { 0, 1, 2, 2, 1, 3 }; // Copy the above vertex/index data into a vertex and index buffer so we can render our plane. using (var vertexPtr = GorgonNativeBuffer <BoingerVertex> .Pin(Vertices)) using (var indexPtr = GorgonNativeBuffer <ushort> .Pin(Indices)) { VertexBufferBindings[0] = GorgonVertexBufferBinding.CreateVertexBuffer(graphics, new GorgonVertexBufferInfo("Plane Vertex Buffer") { SizeInBytes = Vertices.Length * BoingerVertex.Size, Usage = ResourceUsage.Immutable }, vertexPtr); IndexBuffer = new GorgonIndexBuffer(graphics, new GorgonIndexBufferInfo("Plane Index Buffer") { Usage = ResourceUsage.Immutable, IndexCount = Indices.Length, Use16BitIndices = true }, indexPtr); } }
/// <summary> /// Function to create the vertex/index buffers for the renderer. /// </summary> private void CreateBuffers() { // We don't need to update the index buffer ever. So we can set up the indices right now. using (var indices = new GorgonNativeBuffer <ushort>(MaxSpriteCount * 6)) { int indexOffset = 0; ushort index = 0; for (int i = 0; i < MaxSpriteCount; ++i) { indices[indexOffset++] = index; indices[indexOffset++] = (ushort)(index + 1); indices[indexOffset++] = (ushort)(index + 2); indices[indexOffset++] = (ushort)(index + 1); indices[indexOffset++] = (ushort)(index + 3); indices[indexOffset++] = (ushort)(index + 2); index += 4; } VertexBuffer = GorgonVertexBufferBinding.CreateVertexBuffer <Gorgon2DVertex>(Graphics, new GorgonVertexBufferInfo { Usage = ResourceUsage.Dynamic, Binding = VertexIndexBufferBinding.None, SizeInBytes = Gorgon2DVertex.SizeInBytes * (MaxSpriteCount * 4) }); IndexBuffer = new GorgonIndexBuffer(Graphics, new GorgonIndexBufferInfo { Usage = ResourceUsage.Immutable, Binding = VertexIndexBufferBinding.None, IndexCount = indices.Length }, indices); } }
/// <summary> /// Function to initialize the blitter. /// </summary> public void Initialize() { try { // We've been initialized, so leave. if ((_vertexShader != null) || (Interlocked.Increment(ref _initializedFlag) > 1)) { // Trap other threads until we're done initializing and then release them. while ((_vertexShader == null) && (_initializedFlag > 0)) { var wait = new SpinWait(); wait.SpinOnce(); } return; } _vertexShader = GorgonShaderFactory.Compile <GorgonVertexShader>(_graphics, Resources.GraphicsShaders, "GorgonBltVertexShader", GorgonGraphics.IsDebugEnabled); _pixelShader = GorgonShaderFactory.Compile <GorgonPixelShader>(_graphics, Resources.GraphicsShaders, "GorgonBltPixelShader", GorgonGraphics.IsDebugEnabled); _inputLayout = GorgonInputLayout.CreateUsingType <BltVertex>(_graphics, _vertexShader); _vertexBufferBindings = new GorgonVertexBufferBindings(_inputLayout) { [0] = GorgonVertexBufferBinding.CreateVertexBuffer <BltVertex>(_graphics, 4, ResourceUsage.Dynamic, bufferName: "Gorgon Blitter Vertex Buffer") }; _wvpBuffer = GorgonConstantBufferView.CreateConstantBuffer(_graphics, new GorgonConstantBufferInfo("Gorgon Blitter WVP Buffer") { Usage = ResourceUsage.Dynamic, SizeInBytes = DX.Matrix.SizeInBytes }); // Finish initalizing the draw call. _pipelineState = _pipeStateBuilder.VertexShader(_vertexShader) .BlendState(GorgonBlendState.NoBlending) .DepthStencilState(GorgonDepthStencilState.Default) .PrimitiveType(PrimitiveType.TriangleStrip) .RasterState(GorgonRasterState.Default) .PixelShader(_pixelShader) .Build(); _drawCallBuilder.VertexBuffers(_inputLayout, _vertexBufferBindings) .VertexRange(0, 4) .SamplerState(ShaderType.Pixel, GorgonSamplerState.Default) .PipelineState(_pipelineState) .ConstantBuffer(ShaderType.Vertex, _wvpBuffer); _defaultTexture = Resources.White_2x2.ToTexture2D(_graphics, new GorgonTexture2DLoadOptions { Name = "Gorgon_Default_White_Texture", Usage = ResourceUsage.Immutable, Binding = TextureBinding.ShaderResource }).GetShaderResourceView(); } finally { Interlocked.Decrement(ref _initializedFlag); } }
/// <summary> /// Initializes a new instance of the <see cref="Sphere" /> class. /// </summary> /// <param name="graphics">The graphics interface used to create the buffers for this object.</param> /// <param name="inputLayout">The input layout for the vertices in this mesh.</param> /// <param name="radius">Radius of the sphere</param> /// <param name="textureOffset">Offset of the texture.</param> /// <param name="textureScale">Scale of the texture.</param> /// <param name="ringCount">Number of rings in the sphere.</param> /// <param name="segmentCount">Number of segments in the sphere.</param> public Sphere(GorgonGraphics graphics, GorgonInputLayout inputLayout, float radius, DX.Vector2 textureOffset, DX.Size2F textureScale, int ringCount = 8, int segmentCount = 16) : base(inputLayout) { ushort index = 0; // Current index. int vertexIndex = 0; // Current vertex index. int indexIndex = 0; // Current index array index. float deltaRingAngle = ((float)System.Math.PI) / ringCount; float deltaSegAngle = (((float)System.Math.PI) * 2.0f) / segmentCount; // Calculate number of vertices and indices required for our sphere. int vertexCount = (ringCount + 1) * (segmentCount + 1); int indexCount = 6 * ringCount * (segmentCount + 1); Vertices = new BoingerVertex[vertexCount]; Indices = new ushort[indexCount]; Radius = radius; // Build our sphere. for (int ring = 0; ring <= ringCount; ring++) { float angle = deltaRingAngle * ring; float ringSin = angle.Sin(); var position = new DX.Vector3(0, angle.Cos() * radius, 0); for (int segment = 0; segment <= segmentCount; segment++) { var textureDelta = new DX.Vector2(1.0f - (segment / (float)segmentCount), 1.0f - (ring / (float)ringCount)); float segmentAngle = deltaSegAngle * segment; position.X = ringSin * segmentAngle.Sin() * radius; position.Z = ringSin * segmentAngle.Cos() * radius; // Create the vertex. textureDelta.X *= textureScale.Width; textureDelta.Y *= textureScale.Height; textureDelta.X += textureOffset.X; textureDelta.Y += textureOffset.Y; Vertices[vertexIndex++] = new BoingerVertex( position, textureDelta ); // Add the indices and skip the last ring. if (ring == ringCount) { continue; } Indices[indexIndex++] = (ushort)(index + segmentCount + 1); Indices[indexIndex++] = index; Indices[indexIndex++] = (ushort)(index + segmentCount); Indices[indexIndex++] = (ushort)(index + segmentCount + 1); Indices[indexIndex++] = (ushort)(index + 1); Indices[indexIndex++] = index; index++; } } // Copy the above vertex/index data into a vertex and index buffer so we can render our sphere. using (var indexPtr = GorgonNativeBuffer <ushort> .Pin(Indices)) using (var vertexPtr = GorgonNativeBuffer <BoingerVertex> .Pin(Vertices)) { VertexBufferBindings[0] = GorgonVertexBufferBinding.CreateVertexBuffer(graphics, new GorgonVertexBufferInfo("Sphere Vertex Buffer") { SizeInBytes = Vertices.Length * BoingerVertex.Size, Usage = ResourceUsage.Immutable }, vertexPtr); IndexBuffer = new GorgonIndexBuffer(graphics, new GorgonIndexBufferInfo("Sphere Index Buffer") { Usage = ResourceUsage.Immutable, IndexCount = Indices.Length }, indexPtr); } }
/// <summary> /// Initializes a new instance of the <see cref="Cube"/> class. /// </summary> /// <param name="graphics">The graphics object used to create the buffers needed by this object.</param> /// <param name="inputLayout">The input layout describing how a vertex is laid out.</param> public Cube(GorgonGraphics graphics, GorgonInputLayout inputLayout) { GlassCubeVertex[] vertices = { // Front face. new GlassCubeVertex(new DX.Vector3(-0.5f, 0.5f, -0.5f), new DX.Vector2(0, 0)), new GlassCubeVertex(new DX.Vector3(0.5f, -0.5f, -0.5f), new DX.Vector2(1.0f, 1.0f)), new GlassCubeVertex(new DX.Vector3(-0.5f, -0.5f, -0.5f), new DX.Vector2(0.0f, 1.0f)), new GlassCubeVertex(new DX.Vector3(0.5f, 0.5f, -0.5f), new DX.Vector2(1.0f, 0.0f)), // Right face. new GlassCubeVertex(new DX.Vector3(0.5f, 0.5f, -0.5f), new DX.Vector2(0, 0)), new GlassCubeVertex(new DX.Vector3(0.5f, -0.5f, 0.5f), new DX.Vector2(1.0f, 1.0f)), new GlassCubeVertex(new DX.Vector3(0.5f, -0.5f, -0.5f), new DX.Vector2(0.0f, 1.0f)), new GlassCubeVertex(new DX.Vector3(0.5f, 0.5f, 0.5f), new DX.Vector2(1.0f, 0.0f)), // Back face. new GlassCubeVertex(new DX.Vector3(0.5f, 0.5f, 0.5f), new DX.Vector2(0, 0)), new GlassCubeVertex(new DX.Vector3(-0.5f, -0.5f, 0.5f), new DX.Vector2(1.0f, 1.0f)), new GlassCubeVertex(new DX.Vector3(0.5f, -0.5f, 0.5f), new DX.Vector2(0.0f, 1.0f)), new GlassCubeVertex(new DX.Vector3(-0.5f, 0.5f, 0.5f), new DX.Vector2(1.0f, 0.0f)), // Left face. new GlassCubeVertex(new DX.Vector3(-0.5f, 0.5f, 0.5f), new DX.Vector2(0, 0)), new GlassCubeVertex(new DX.Vector3(-0.5f, -0.5f, -0.5f), new DX.Vector2(1.0f, 1.0f)), new GlassCubeVertex(new DX.Vector3(-0.5f, -0.5f, 0.5f), new DX.Vector2(0.0f, 1.0f)), new GlassCubeVertex(new DX.Vector3(-0.5f, 0.5f, -0.5f), new DX.Vector2(1.0f, 0.0f)), // Top face. new GlassCubeVertex(new DX.Vector3(-0.5f, 0.5f, 0.5f), new DX.Vector2(0, 0)), new GlassCubeVertex(new DX.Vector3(0.5f, 0.5f, -0.5f), new DX.Vector2(1.0f, 1.0f)), new GlassCubeVertex(new DX.Vector3(-0.5f, 0.5f, -0.5f), new DX.Vector2(0.0f, 1.0f)), new GlassCubeVertex(new DX.Vector3(0.5f, 0.5f, 0.5f), new DX.Vector2(1.0f, 0.0f)), // Bottom face. new GlassCubeVertex(new DX.Vector3(-0.5f, -0.5f, -0.5f), new DX.Vector2(0, 0)), new GlassCubeVertex(new DX.Vector3(0.5f, -0.5f, 0.5f), new DX.Vector2(1.0f, 1.0f)), new GlassCubeVertex(new DX.Vector3(-0.5f, -0.5f, 0.5f), new DX.Vector2(0.0f, 1.0f)), new GlassCubeVertex(new DX.Vector3(0.5f, -0.5f, -0.5f), new DX.Vector2(1.0f, 0.0f)) }; ushort[] indices = { 8, 9, 10, 8, 11, 9, 12, 13, 14, 12, 15, 13, 4, 5, 6, 4, 7, 5, 16, 17, 18, 16, 19, 17, 20, 21, 22, 20, 23, 21, 0, 1, 2, 0, 3, 1 }; // Create our index buffer and vertex buffer and populate with our cube data. using (var indexPtr = GorgonNativeBuffer <ushort> .Pin(indices)) using (var vertexPtr = GorgonNativeBuffer <GlassCubeVertex> .Pin(vertices)) { IndexBuffer = new GorgonIndexBuffer(graphics, new GorgonIndexBufferInfo("GlassCube Index Buffer") { Usage = ResourceUsage.Immutable, IndexCount = indices.Length, Use16BitIndices = true }, indexPtr); VertexBuffer = new GorgonVertexBufferBindings(inputLayout) { [0] = GorgonVertexBufferBinding.CreateVertexBuffer(graphics, vertices.Length, ResourceUsage.Immutable, initialData: vertexPtr, bufferName: "GlassCube Vertex Buffer") }; } }