/// <summary> /// Initializes a new instance of the <see cref="Cube" /> class. /// </summary> /// <param name="graphics">The graphics interface.</param> /// <param name="size">The width, height and depth of the cube.</param> /// <param name="textureCoordinates">The texture coordinates for the faces of the cube.</param> /// <param name="angle">The initial orientation of the cube, in degrees.</param> /// <param name="columnsPerFace">The number of columns per face.</param> /// <param name="rowsPerFace">The number of rows per face.</param> public Cube(GorgonGraphics graphics, DX.Vector3 size, RectangleF textureCoordinates, DX.Vector3 angle, int columnsPerFace = 1, int rowsPerFace = 1) : base(graphics) { PrimitiveType = PrimitiveType.TriangleList; int faceVertexCount = (columnsPerFace + 1) * (rowsPerFace + 1); int faceIndexCount = (columnsPerFace * rowsPerFace) * 6; VertexCount = faceVertexCount * 6; IndexCount = faceIndexCount * 6; TriangleCount = IndexCount / 3; DX.Quaternion.RotationYawPitchRoll(angle.Y.ToRadians(), angle.X.ToRadians(), angle.Z.ToRadians(), out DX.Quaternion orientation); DX.Matrix.RotationQuaternion(ref orientation, out _orientation); using (var vertexData = new GorgonNativeBuffer <Vertex3D>(VertexCount)) using (var indexData = new GorgonNativeBuffer <int>(IndexCount)) { // Front. GetVertices(vertexData, 0, DX.Vector3.UnitY, -DX.Vector3.UnitZ, size, textureCoordinates, columnsPerFace, rowsPerFace); // Bottom. GetVertices(vertexData, faceVertexCount, -DX.Vector3.UnitZ, -DX.Vector3.UnitY, size, textureCoordinates, columnsPerFace, rowsPerFace); // Back. GetVertices(vertexData, faceVertexCount * 2, DX.Vector3.UnitY, DX.Vector3.UnitZ, size, textureCoordinates, columnsPerFace, rowsPerFace); // Top. GetVertices(vertexData, faceVertexCount * 3, DX.Vector3.UnitZ, DX.Vector3.UnitY, size, textureCoordinates, columnsPerFace, rowsPerFace); // Left. GetVertices(vertexData, faceVertexCount * 4, DX.Vector3.UnitY, -DX.Vector3.UnitX, size, textureCoordinates, columnsPerFace, rowsPerFace); // Right GetVertices(vertexData, faceVertexCount * 5, DX.Vector3.UnitY, DX.Vector3.UnitX, size, textureCoordinates, columnsPerFace, rowsPerFace); GetIndices(indexData, 0, 0, columnsPerFace, rowsPerFace); GetIndices(indexData, faceIndexCount, faceVertexCount, columnsPerFace, rowsPerFace); GetIndices(indexData, faceIndexCount * 2, faceVertexCount * 2, columnsPerFace, rowsPerFace); GetIndices(indexData, faceIndexCount * 3, faceVertexCount * 3, columnsPerFace, rowsPerFace); GetIndices(indexData, faceIndexCount * 4, faceVertexCount * 4, columnsPerFace, rowsPerFace); GetIndices(indexData, faceIndexCount * 5, faceVertexCount * 5, columnsPerFace, rowsPerFace); CalculateTangents(vertexData, indexData); VertexBuffer = new GorgonVertexBuffer(graphics, new GorgonVertexBufferInfo("CubeVB") { Usage = ResourceUsage.Immutable, SizeInBytes = vertexData.SizeInBytes }, vertexData.Cast <byte>()); IndexBuffer = new GorgonIndexBuffer(graphics, new GorgonIndexBufferInfo("CubeIB") { Usage = ResourceUsage.Immutable, Use16BitIndices = false, IndexCount = IndexCount }, indexData); } }
/// <summary> /// Initializes a new instance of the <see cref="Sphere" /> class. /// </summary> /// <param name="graphics">Graphics interface to use.</param> /// <param name="radius">Radius of the sphere</param> /// <param name="textureCoordinates">The texture coordinates to apply to the sphere.</param> /// <param name="angle">The angle of rotation, in degrees.</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, float radius, RectangleF textureCoordinates, Vector3 angle, int ringCount = 8, int segmentCount = 16) { Quaternion orientation; // Calculate number of vertices and indices required for our sphere. PrimitiveType = PrimitiveType.TriangleList; VertexCount = (ringCount + 1) * (segmentCount + 1); IndexCount = 6 * ringCount * (segmentCount + 1); TriangleCount = IndexCount / 3; Quaternion.RotationYawPitchRoll(angle.Y.Radians(), angle.X.Radians(), angle.Z.Radians(), out orientation); Matrix.RotationQuaternion(ref orientation, out _orientation); unsafe { using (var vertexData = new GorgonDataStream(VertexCount * Vertex3D.Size)) using (var normalData = new GorgonDataStream(VertexCount * 2 * Vector4.SizeInBytes)) using (var indexData = new GorgonDataStream(IndexCount * DirectAccess.SizeOf <int>())) { GetVertices((Vertex3D *)vertexData.UnsafePointer, (int *)indexData.UnsafePointer, normalData.UnsafePointer, radius, textureCoordinates, ringCount, segmentCount); VertexBuffer = graphics.Buffers.CreateVertexBuffer("SphereVertexBuffer", new GorgonBufferSettings { Usage = BufferUsage.Immutable, SizeInBytes = (int)vertexData.Length }, vertexData); IndexBuffer = graphics.Buffers.CreateIndexBuffer("SphereIndexBuffer", new GorgonIndexBufferSettings { Usage = BufferUsage.Immutable, Use32BitIndices = true, SizeInBytes = (int)indexData.Length }, indexData); Normals = graphics.Buffers.CreateVertexBuffer("NormalsBuffer", new GorgonBufferSettings { Usage = BufferUsage.Immutable, SizeInBytes = (int)normalData.Length }, normalData); } } }
/// <summary> /// Function to flush the cache data into the buffers and render the renderables. /// </summary> /// <param name="drawCall">The draw call that will be used to render the renderables.</param> public void RenderBatches(GorgonDrawIndexCall drawCall) { GorgonVertexBuffer vertexBuffer = VertexBuffer.VertexBuffer; int cacheIndex = _currentVertexIndex - _allocatedVertexCount; while (_allocatedVertexCount > 0) { int vertexCount = _allocatedVertexCount.Min(MaxVertexCount); int indexCount = _indexCount.Min(MaxIndexCount); int byteCount = Gorgon2DVertex.SizeInBytes * vertexCount; // If we've exceeded our vertex or index buffer size, we need to reset from the beginning. if (((_vertexBufferByteOffset + byteCount) >= vertexBuffer.SizeInBytes) || ((_indexStart + _indexCount) >= MaxIndexCount)) { _indexStart = 0; _vertexBufferByteOffset = 0; _vertexBufferIndex = 0; _indexBufferBaseVertexIndex = 0; } CopyMode copyMode = _vertexBufferByteOffset == 0 ? CopyMode.Discard : CopyMode.NoOverwrite; // Copy a chunk of the cache. vertexBuffer.SetData(_vertexCache, cacheIndex, vertexCount, _vertexBufferByteOffset, copyMode); drawCall.BaseVertexIndex = _indexBufferBaseVertexIndex; drawCall.IndexStart = _indexStart; drawCall.IndexCount = indexCount; Graphics.Submit(drawCall); // Move to the next block of bytes to render. _vertexBufferByteOffset += byteCount; _vertexBufferIndex += vertexCount; _allocatedVertexCount -= vertexCount; cacheIndex += vertexCount; _indexStart += indexCount; _indexCount -= indexCount; } // Invalidate the cache. _currentVertexIndex = 0; _allocatedVertexCount = 0; _indexCount = 0; }
/// <summary> /// Initializes a new instance of the <see cref="Sphere" /> class. /// </summary> /// <param name="graphics">Graphics interface to use.</param> /// <param name="radius">Radius of the sphere</param> /// <param name="textureCoordinates">The texture coordinates to apply to the sphere.</param> /// <param name="angle">The angle of rotation, in degrees.</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, float radius, RectangleF textureCoordinates, DX.Vector3 angle, int ringCount = 8, int segmentCount = 16) : base(graphics) { // Calculate number of vertices and indices required for our sphere. PrimitiveType = PrimitiveType.TriangleList; VertexCount = (ringCount + 1) * (segmentCount + 1); IndexCount = 6 * ringCount * (segmentCount + 1); TriangleCount = IndexCount / 3; DX.Quaternion.RotationYawPitchRoll(angle.Y.ToRadians(), angle.X.ToRadians(), angle.Z.ToRadians(), out DX.Quaternion orientation); DX.Matrix.RotationQuaternion(ref orientation, out _orientation); using (var vertexData = new GorgonNativeBuffer <Vertex3D>(VertexCount)) using (var indexData = new GorgonNativeBuffer <int>(IndexCount)) { GetVertices(vertexData, indexData, radius, textureCoordinates, ringCount, segmentCount); VertexBuffer = new GorgonVertexBuffer(graphics, new GorgonVertexBufferInfo("SphereVertexBuffer") { Usage = ResourceUsage.Immutable, SizeInBytes = vertexData.SizeInBytes }, vertexData.Cast <byte>()); IndexBuffer = new GorgonIndexBuffer(graphics, new GorgonIndexBufferInfo("SphereIndexBuffer") { Usage = ResourceUsage.Immutable, Use16BitIndices = false, IndexCount = IndexCount }, indexData); } }
/// <summary> /// Initializes a new instance of the <see cref="Triangle" /> class. /// </summary> /// <param name="graphics">The graphics interface.</param> /// <param name="point1">The 1st point in the triangle.</param> /// <param name="point2">The 2nd point in the triangle.</param> /// <param name="point3">The 3rd point in the triangle.</param> public Triangle(GorgonGraphics graphics, Vertex3D point1, Vertex3D point2, Vertex3D point3) : base(graphics) { PrimitiveType = PrimitiveType.TriangleList; VertexCount = 3; IndexCount = 3; TriangleCount = 1; point1.Tangent = new DX.Vector4(1.0f, 0, 0, 1.0f); point2.Tangent = new DX.Vector4(1.0f, 0, 0, 1.0f); point3.Tangent = new DX.Vector4(1.0f, 0, 0, 1.0f); using (var points = new GorgonNativeBuffer <Vertex3D>(3)) using (var indices = new GorgonNativeBuffer <int>(3)) { points[0] = point1; points[1] = point2; points[2] = point3; indices[0] = 0; indices[1] = 1; indices[2] = 2; VertexBuffer = new GorgonVertexBuffer(graphics, new GorgonVertexBufferInfo("TriVB") { Usage = ResourceUsage.Immutable, SizeInBytes = Vertex3D.Size * 3 }, points.Cast <byte>()); IndexBuffer = new GorgonIndexBuffer(graphics, new GorgonIndexBufferInfo("TriIB") { Usage = ResourceUsage.Dynamic, Use16BitIndices = false, IndexCount = 3 }, indices); } }
/// <summary> /// Initializes a new instance of the <see cref="Plane" /> class. /// </summary> /// <param name="graphics">The graphics interface to use.</param> /// <param name="size">The width and height of the plane.</param> /// <param name="textureCoordinates">The texture coordinates to apply to the plane.</param> /// <param name="angle">The initial orientation, in degrees.</param> /// <param name="columns">The number of columns to subdivide by.</param> /// <param name="rows">The number of rows to subdivide by.</param> public Plane(GorgonGraphics graphics, DX.Vector2 size, RectangleF textureCoordinates, DX.Vector3 angle, int columns = 1, int rows = 1) : base(graphics) { PrimitiveType = PrimitiveType.TriangleStrip; VertexCount = (columns + 1) * (rows + 1); IndexCount = ((columns * rows) * 6) + (rows - 1); TriangleCount = (IndexCount - (rows - 1)) / 3; DX.Quaternion.RotationYawPitchRoll(angle.Y.ToRadians(), angle.X.ToRadians(), angle.Z.ToRadians(), out DX.Quaternion orientation); DX.Matrix.RotationQuaternion(ref orientation, out _orientation); using (var vertexData = new GorgonNativeBuffer <Vertex3D>(VertexCount)) using (var indexData = new GorgonNativeBuffer <int>(IndexCount)) { GetVertices(vertexData, size, textureCoordinates, columns, rows); GetIndices(indexData, columns, rows); CalculateTangents(vertexData, indexData); VertexBuffer = new GorgonVertexBuffer(graphics, new GorgonVertexBufferInfo("PlaneVB") { Usage = ResourceUsage.Immutable, SizeInBytes = vertexData.SizeInBytes }, vertexData.Cast <byte>()); IndexBuffer = new GorgonIndexBuffer(graphics, new GorgonIndexBufferInfo { Usage = ResourceUsage.Immutable, Use16BitIndices = false, IndexCount = IndexCount }, indexData); } }
/// <summary> /// Function to build the Icosphere. /// </summary> /// <param name="graphics">Graphics interface to use.</param> /// <param name="radius">Radius of the sphere.</param> /// <param name="tesselation">Tessellation factor for the sphere.</param> /// <param name="textureCoordinates">Texture coordinate offset and scale.</param> private void BuildSphere(GorgonGraphics graphics, float radius, int tesselation, DX.RectangleF textureCoordinates) { GetBaseVertices(); List <int[]> indices = GetBaseIndices(); for (int i = 0; i < tesselation; ++i) { var subIndices = new List <int[]>(); foreach (int[] index in indices) { int index0 = GetMiddlePoint(index[0], index[1]); int index1 = GetMiddlePoint(index[1], index[2]); int index2 = GetMiddlePoint(index[2], index[0]); subIndices.Add(new [] { index[0], index0, index2 }); subIndices.Add(new[] { index[1], index1, index0 }); subIndices.Add(new[] { index[2], index2, index1 }); subIndices.Add(new[] { index0, index1, index2 }); } indices = subIndices; _cachedSplits.Clear(); } // Perform texture coordinate calculations and vertex/normal transformations. const float piRecip = 1.0f / (float)System.Math.PI; const float pi2Recip = 1.0f / (2.0f * (float)System.Math.PI); // Final list. var vertexList = new List <Vertex3D>(); var indexList = new List <int>(); foreach (DX.Vector3 vector in _vertices) { DX.Vector3 position = vector; DX.Vector3 normal = position; DX.Vector2 uv = DX.Vector2.Zero; uv.X = ((0.5f - (position.X.ATan(position.Z) * pi2Recip)) * textureCoordinates.Width) + textureCoordinates.X; uv.Y = ((0.5f - (position.Y.ASin() * piRecip)) * textureCoordinates.Height) + textureCoordinates.Y; DX.Vector3.Multiply(ref position, radius, out position); DX.Vector3.TransformCoordinate(ref position, ref _orientation, out position); DX.Vector3.TransformCoordinate(ref normal, ref _orientation, out normal); normal.Normalize(); vertexList.Add(new Vertex3D { Position = new DX.Vector4(position, 1.0f), Normal = normal, UV = uv }); } foreach (int[] index in indices) { for (int j = 0; j < 3; ++j) { indexList.Add(index[j]); } } FixSeam(vertexList, indexList); using (var vertexData = GorgonNativeBuffer <Vertex3D> .Pin(vertexList.ToArray())) using (var indexData = GorgonNativeBuffer <int> .Pin(indexList.ToArray())) { VertexCount = vertexList.Count; IndexCount = indexList.Count; TriangleCount = IndexCount / 3; CalculateTangents(vertexData, indexData); VertexBuffer = new GorgonVertexBuffer(graphics, new GorgonVertexBufferInfo("IcoSphereVertexBuffer") { SizeInBytes = vertexData.SizeInBytes, Usage = ResourceUsage.Immutable }, vertexData.Cast <byte>()); IndexBuffer = new GorgonIndexBuffer(graphics, new GorgonIndexBufferInfo { Usage = ResourceUsage.Immutable, Use16BitIndices = false, IndexCount = IndexCount }, indexData); } }
public void Init() { _form = new TestForm { ShowTestPanel = true, ClientSize = new Size(1280, 800) }; _form.WindowState = FormWindowState.Minimized; _form.Show(); _form.WindowState = FormWindowState.Normal; _graphics = new GorgonGraphics(); _swap = _graphics.Output.CreateSwapChain("Screen", new GorgonSwapChainSettings() { Window = _form.panelDisplay, DepthStencilFormat = BufferFormat.D24_UIntNormal_S8_UInt }); _swap.AfterSwapChainResized += (sender, args) => { var currentMatrix = new MatrixBuffer(); _graphics.Rasterizer.SetViewport(_swap.Viewport); _aspect = (_swap.Settings.VideoMode.Width) / (float)(_swap.Settings.VideoMode.Height); currentMatrix.Projection = Matrix.PerspectiveFovLH(100.39f.Radians(), _aspect, 0.1f, 1000.0f); currentMatrix.View = Matrix.LookAtLH(new Vector3(0, 0, -0.75f), new Vector3(0, 0, 1.0f), Vector3.UnitY); _graphics.Output.SetRenderTarget(_swap, _swap.DepthStencilBuffer); pvw = currentMatrix.View * currentMatrix.Projection; }; _swap.AfterStateTransition += (sender, args) => { var currentMatrix = new MatrixBuffer(); _graphics.Rasterizer.SetViewport(_swap.Viewport); _aspect = (_swap.Settings.VideoMode.Width) / (float)(_swap.Settings.VideoMode.Height); currentMatrix.Projection = Matrix.PerspectiveFovLH(100.39f.Radians(), _aspect, 0.1f, 1000.0f); currentMatrix.View = Matrix.LookAtLH(new Vector3(0, 0, -0.75f), new Vector3(0, 0, 1.0f), Vector3.UnitY); _graphics.Output.SetRenderTarget(_swap, _swap.DepthStencilBuffer); pvw = currentMatrix.View * currentMatrix.Projection; }; var button = new Button() { Text = "3D", Location = new Point(90, 3) }; button.Click += (sender, args) => { _3d = !_3d; Matrix currentMatrix = Matrix.LookAtLH(new Vector3(0, 0, _camPos), new Vector3(0, 0, 1.0f), Vector3.UnitY); Matrix projection = Matrix.PerspectiveFovLH(100.39f.Radians(), _aspect, 0.1f, 1000.0f); pvw = currentMatrix * projection; }; _form.panelInput.Controls.Add(button); _sprite = new vertex[Count * 4]; for (int i = 0; i < Count; i++) { _balls[i].Scale = 1.0f; _balls[i].ScaleDelta = (GorgonRandom.RandomSingle() * 1.5f) + 0.25f; _balls[i].AlphaBounce = _balls[i].ScaleBouce = false; _balls[i].XBounce = GorgonRandom.RandomInt32(0, 100) > 50; _balls[i].YBounce = GorgonRandom.RandomInt32(0, 100) > 50; _balls[i].ZBounce = GorgonRandom.RandomInt32(0, 100) > 50; _balls[i].Velocity = new Vector3((GorgonRandom.RandomSingle() * 0.5f), (GorgonRandom.RandomSingle() * 0.5f), (GorgonRandom.RandomSingle() * 0.5f)); _balls[i].Angle = 0.0f; _balls[i].AngleDelta = 1.0f; _balls[i].Color = new Vector4(1.0f); _balls[i].AlphaDelta = GorgonRandom.RandomSingle() * 0.5f; _balls[i].Checkered = true; // GorgonRandom.RandomInt32(0, 100) > 50; _balls[i].Position = new Vector3((GorgonRandom.RandomSingle() * 2.0f) - 1.0f, (GorgonRandom.RandomSingle() * 2.0f) - 1.0f, GorgonRandom.RandomSingle()); } _vs = _graphics.Shaders.CreateShader <GorgonVertexShader>("TestVShader", "VS", _shader, null, true); _ps = _graphics.Shaders.CreateShader <GorgonPixelShader>("TestPShader", "PS", _shader, null, true); _layout = _graphics.Input.CreateInputLayout("Input", typeof(vertex), _vs); int vertexSize = _layout.Size; int index = 0; var indices = new int[Count * 6 * sizeof(int)]; for (int i = 0; i < indices.Length; i += 6) { indices[i] = index; indices[i + 1] = index + 1; indices[i + 2] = index + 2; indices[i + 3] = index + 1; indices[i + 4] = index + 3; indices[i + 5] = index + 2; index += 4; } _vertices = _graphics.Buffers.CreateVertexBuffer("Vertex", new GorgonBufferSettings() { SizeInBytes = 4 * vertexSize * Count, Usage = BufferUsage.Dynamic }); _index = _graphics.Buffers.CreateIndexBuffer("Index", indices, BufferUsage.Immutable); _texture = _graphics.Textures.FromFile <GorgonTexture2D>("Balls", @"..\..\..\..\Resources\BallDemo\BallDemo.png", new GorgonCodecPNG()); _texture2 = _graphics.Textures.FromFile <GorgonTexture2D>("VBBack", @"..\..\..\..\Resources\Images\VBback.jpg", new GorgonCodecJPEG()); var matrix = new MatrixBuffer(); _aspect = _swap.Settings.VideoMode.Width / (float)(_swap.Settings.VideoMode.Height); matrix.Projection = Matrix.PerspectiveFovLH(100.39f.Radians(), _aspect, 0.1f, 1000.0f); matrix.View = Matrix.LookAtLH(new Vector3(0, 0, _camPos), new Vector3(0, 0, 1.0f), Vector3.UnitY); matrix.Array = new Vector4[3]; matrix.Array[0] = new Vector4(1.0f, 1.0f, 1.0f, 1.0f); matrix.Array[1] = new Vector4(1.0f, 1.0f, 1.0f, 1.0f); matrix.Array[2] = new Vector4(1.0f, 1.0f, 1.0f, 1.0f); matrix.valueType = new TEMPGUY { value2 = matrix.View, tempArray = new Vector4[3] }; _depthStateAlpha.IsDepthEnabled = false; _depthStateAlpha.IsDepthWriteEnabled = false; _graphics.Input.Layout = _layout; _graphics.Shaders.VertexShader.Current = _vs; _graphics.Shaders.PixelShader.Current = _ps; _graphics.Shaders.PixelShader.TextureSamplers.SetRange(0, new[] { GorgonTextureSamplerStates.LinearFilter, GorgonTextureSamplerStates.LinearFilter }); _graphics.Rasterizer.SetViewport(_swap.Viewport); _graphics.Output.DepthStencilState.States = _depthStateAlpha; _graphics.Output.SetRenderTarget(_swap, _swap.DepthStencilBuffer); _graphics.Input.VertexBuffers[0] = new GorgonVertexBufferBinding(_vertices, vertexSize); _graphics.Input.IndexBuffer = _index; _graphics.Shaders.PixelShader.Resources.SetRange(0, new GorgonShaderView[] { _texture, _texture2 }); _graphics.Output.BlendingState.States = GorgonBlendStates.ModulatedBlending; pvw = matrix.valueType.value2 * matrix.Projection; _tempStream = new GorgonDataStream(_sprite.Length * vertexSize); }