public override void Start() { base.Start(); float size = Main.instance.RandomMinMax(0.003666f, 0.00666f); // VertexPositionNormalTexture is the layout that the engine uses in the shaders var vBuffer = Stride.Graphics.Buffer.Vertex.New(GraphicsDevice, new VertexPositionNormalTexture[] { new VertexPositionNormalTexture(new Vector3(0, -size, 0), new Vector3(0, 1, 1), new Vector2(0, 0)), //Top Left. new VertexPositionNormalTexture(new Vector3(0, size, 0), new Vector3(0, 1, 1), new Vector2(0, 0)) //Bottom right. }); MeshDraw meshDraw = new MeshDraw { PrimitiveType = PrimitiveType.LineStrip, // Tell the GPU that this is a line. VertexBuffers = new[] { new VertexBufferBinding(vBuffer, VertexPositionNormalTexture.Layout, vBuffer.ElementCount) }, DrawCount = vBuffer.ElementCount }; Mesh mesh = new Mesh(); mesh.Draw = meshDraw; Model model = new Model(); model.Add(mesh); lineMesh = new ModelComponent(model); line = new Entity(); line.Add(lineMesh); Entity.AddChild(line); Destroy(); }
public static Mesh LoadMesh(SharpGLTF.Schema2.MeshPrimitive mesh, GraphicsDevice device) { var draw = new MeshDraw { PrimitiveType = ConvertPrimitiveType(mesh.DrawPrimitiveType), IndexBuffer = ConvertIndexBufferBinding(mesh, device), VertexBuffers = ConvertVertexBufferBinding(mesh, device), DrawCount = GetDrawCount(mesh) }; var result = new Mesh(draw, new ParameterCollection()) { Skinning = ConvertInverseBindMatrices(mesh.LogicalParent.LogicalParent), Name = mesh.LogicalParent.Name, MaterialIndex = mesh.LogicalParent.LogicalParent.LogicalMaterials.ToList().IndexOf(mesh.Material) }; //TODO : Add parameter collection only after checking if it has result.Parameters.Set(MaterialKeys.HasSkinningPosition, true); result.Parameters.Set(MaterialKeys.HasSkinningNormal, true); return(result); }
public void Build(RenderDrawContext context) { if (Mesh == null && TryGetHeightMapImageData(context.CommandList, out var data)) { Data = new GeometryBuilder(data).BuildTerrainData(Size, MaxHeight, UvScale); MeshBoundingBox = Utils.FromPoints(Data.Vertices); MeshBoundingSphere = BoundingSphere.FromBox(MeshBoundingBox); BoundingBox = new BoundingBoxExt(MeshBoundingBox); var vertexBuffer = Buffer.Vertex.New(context.GraphicsDevice, Data.Vertices, GraphicsResourceUsage.Dynamic); var indexBuffer = Buffer.Index.New(context.GraphicsDevice, Data.Indices); var vertexBufferBinding = new VertexBufferBinding(vertexBuffer, VertexPositionNormalTexture.Layout, vertexBuffer.ElementCount); var indexBufferBinding = new IndexBufferBinding(indexBuffer, true, indexBuffer.ElementCount); MeshDraw = new MeshDraw { StartLocation = 0, PrimitiveType = PrimitiveType.TriangleList, VertexBuffers = new[] { vertexBufferBinding }, IndexBuffer = indexBufferBinding, DrawCount = indexBuffer.ElementCount }; Mesh = new Mesh(MeshDraw, new ParameterCollection()); } }
public void Build(CommandList commandList, CameraParameters parameters) { var indices = new [] { 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 }; vertexBuffer = Buffer.Vertex.New(graphicsDevice, new VertexPositionNormalTexture[8], GraphicsResourceUsage.Dynamic); RebuildVertexBuffer(commandList, parameters); MeshDraw = new MeshDraw { PrimitiveType = PrimitiveType.LineList, DrawCount = indices.Length, IndexBuffer = new IndexBufferBinding(Buffer.Index.New(graphicsDevice, indices), true, indices.Length), VertexBuffers = new[] { new VertexBufferBinding(vertexBuffer, VertexPositionNormalTexture.Layout, vertexBuffer.ElementCount) }, }; }
/// <summary> /// Generates the index buffer with dominant edge and vertex information. /// Each triangle gets its indices expanded to 12 control points, with 0 to 2 being original triangle, /// 3 to 8 being dominant edges and 9 to 11 being dominant vertices. /// </summary> /// <param name="meshData">The mesh data.</param> public unsafe static void GenerateIndexBufferAEN(this MeshDraw meshData) { // For now, require a MeshData with only one vertex buffer and one index buffer if (meshData.VertexBuffers.Length != 1 || meshData.IndexBuffer == null) { throw new NotImplementedException(); } // Generate the new indices var newIndices = GenerateIndexBufferAEN(meshData.IndexBuffer, meshData.VertexBuffers[0]); // copy them into a byte[] var triangleCount = meshData.IndexBuffer.Count / 3; var indexBufferData = new byte[triangleCount * 12 * Utilities.SizeOf <int>()]; fixed(int *indexDataStart = &newIndices[0]) fixed(byte *indexBufferDataStart = &indexBufferData[0]) { Utilities.CopyMemory((IntPtr)indexBufferDataStart, (IntPtr)indexDataStart, indexBufferData.Length); } meshData.IndexBuffer = new IndexBufferBinding(new BufferData(BufferFlags.IndexBuffer, indexBufferData).ToSerializableVersion(), true, triangleCount * 12); meshData.DrawCount = meshData.IndexBuffer.Count; meshData.PrimitiveType = PrimitiveType.PatchList.ControlPointCount(12); }
/// <summary> /// Generates the tangents and binormals for this mesh data. /// Tangents and bitangents will be encoded as float4: /// float3 for tangent and an additional float for handedness (1 or -1), /// so that bitangent can be reconstructed. /// More info at http://www.terathon.com/code/tangent.html /// </summary> /// <param name="meshData">The mesh data.</param> public static unsafe void GenerateTangentBinormal(this MeshDraw meshData) { if (!meshData.IsSimple()) { throw new ArgumentException("meshData is not simple."); } if (meshData.PrimitiveType != PrimitiveType.TriangleList && meshData.PrimitiveType != PrimitiveType.TriangleListWithAdjacency) { throw new NotImplementedException(); } var oldVertexBufferBinding = meshData.VertexBuffers[0]; var indexBufferBinding = meshData.IndexBuffer; var indexData = indexBufferBinding != null?indexBufferBinding.Buffer.GetSerializationData().Content : null; var oldVertexStride = oldVertexBufferBinding.Declaration.VertexStride; var bufferData = oldVertexBufferBinding.Buffer.GetSerializationData().Content; fixed(byte *indexBufferStart = indexData) fixed(byte *oldBuffer = bufferData) { var result = VertexHelper.GenerateTangentBinormal(oldVertexBufferBinding.Declaration, (IntPtr)oldBuffer, oldVertexBufferBinding.Count, oldVertexBufferBinding.Offset, oldVertexBufferBinding.Stride, (IntPtr)indexBufferStart, indexBufferBinding != null && indexBufferBinding.Is32Bit, indexBufferBinding != null ? indexBufferBinding.Count : 0); // Replace new vertex buffer binding meshData.VertexBuffers[0] = new VertexBufferBinding(new BufferData(BufferFlags.VertexBuffer, result.VertexBuffer).ToSerializableVersion(), result.Layout, oldVertexBufferBinding.Count); } }
/// <summary> /// Expand vertices using index buffer (if existing), and remove it. /// </summary> /// <param name="meshData">The mesh data.</param> public static unsafe void RemoveIndexBuffer(this MeshDraw meshData) { if (meshData.IndexBuffer == null) { return; } // For now, require a MeshData with only one vertex buffer and a 32 bit full index buffer if (meshData.VertexBuffers.Length != 1 || !meshData.IndexBuffer.Is32Bit || meshData.StartLocation != 0 || meshData.DrawCount != meshData.IndexBuffer.Count) { throw new NotImplementedException(); } var vertexBuffer = meshData.VertexBuffers[0]; var indexBuffer = meshData.IndexBuffer; var stride = vertexBuffer.Stride; var newVertices = new byte[stride * indexBuffer.Count]; fixed(byte *newVerticesStart = newVertices) fixed(byte *indexBufferStart = &indexBuffer.Buffer.GetDataSafe()[indexBuffer.Offset]) fixed(byte *vertexBufferStart = &vertexBuffer.Buffer.GetDataSafe()[indexBuffer.Offset]) { for (int i = 0; i < indexBuffer.Count; ++i) { var index = ((int *)indexBufferStart)[i]; Utilities.CopyMemory((IntPtr)newVerticesStart + i * stride, (IntPtr)vertexBufferStart + index * stride, stride); } } meshData.VertexBuffers[0] = new VertexBufferBinding(new BufferData(BufferFlags.VertexBuffer, newVertices).ToSerializableVersion(), vertexBuffer.Declaration, indexBuffer.Count); meshData.IndexBuffer = null; }
public void Build(CommandList commandList, LightSpot lightSpot) { int[] indices; if (lightSpot.ProjectiveTexture != null) // If no projection texture has been supplied, we render the regular cone: { indices = BuildRectangleIndexBuffer(); vertexBuffer = Buffer.Vertex.New(graphicsDevice, new VertexPositionNormalTexture[9], GraphicsResourceUsage.Dynamic); RebuildRectangleVertexBuffer(commandList, lightSpot); } else // If a projection texture has been supplied, we render a rectangular frustum instead: { indices = BuildConeIndexBuffer(); vertexBuffer = Buffer.Vertex.New(graphicsDevice, new VertexPositionNormalTexture[4 * Tesselation + 1], GraphicsResourceUsage.Dynamic); RebuildConeVertexBuffer(commandList, lightSpot); } MeshDraw = new MeshDraw { PrimitiveType = PrimitiveType.LineList, DrawCount = indices.Length, IndexBuffer = new IndexBufferBinding(Buffer.Index.New(graphicsDevice, indices), true, indices.Length), VertexBuffers = new[] { new VertexBufferBinding(vertexBuffer, VertexPositionNormalTexture.Layout, vertexBuffer.ElementCount) }, }; }
private void m_RockTwo() { // VertexPositionNormalTexture is the layout that the engine uses in the shaders var vBuffer = Xenko.Graphics.Buffer.Vertex.New(GraphicsDevice, new VertexPositionNormalTexture[] { new VertexPositionNormalTexture(new Vector3(2.9f, 1.5f, 0), new Vector3(0, 1, 1), new Vector2(0, 0)), new VertexPositionNormalTexture(new Vector3(1.4f, 2.9f, 0), new Vector3(0, 1, 1), new Vector2(0, 0)), new VertexPositionNormalTexture(new Vector3(0.0f, 1.5f, 0), new Vector3(0, 1, 1), new Vector2(0, 0)), new VertexPositionNormalTexture(new Vector3(-1.5f, 2.9f, 0), new Vector3(0, 1, 1), new Vector2(0, 0)), new VertexPositionNormalTexture(new Vector3(-2.9f, 1.5f, 0), new Vector3(0, 1, 1), new Vector2(0, 0)), new VertexPositionNormalTexture(new Vector3(-2.2f, 0.0f, 0), new Vector3(0, 1, 1), new Vector2(0, 0)), new VertexPositionNormalTexture(new Vector3(-2.9f, -1.5f, 0), new Vector3(0, 1, 1), new Vector2(0, 0)), new VertexPositionNormalTexture(new Vector3(-0.7f, -2.9f, 0), new Vector3(0, 1, 1), new Vector2(0, 0)), new VertexPositionNormalTexture(new Vector3(1.4f, -2.9f, 0), new Vector3(0, 1, 1), new Vector2(0, 0)), new VertexPositionNormalTexture(new Vector3(2.9f, -1.4f, 0), new Vector3(0, 1, 1), new Vector2(0, 0)), new VertexPositionNormalTexture(new Vector3(2.9f, 1.5f, 0), new Vector3(0, 1, 1), new Vector2(0, 0)) }); MeshDraw meshDraw = new MeshDraw { PrimitiveType = PrimitiveType.LineStrip, // Tell the GPU that this is a line. VertexBuffers = new[] { new VertexBufferBinding(vBuffer, VertexPositionNormalTexture.Layout, vBuffer.ElementCount) }, DrawCount = vBuffer.ElementCount }; Mesh mesh = new Mesh(); mesh.Draw = meshDraw; Model model = new Model(); model.Add(mesh); m_RockMesh = new ModelComponent(model); }
public override void Start() { // VertexPositionNormalTexture is the layout that the engine uses in the shaders var vBuffer = Xenko.Graphics.Buffer.Vertex.New(GraphicsDevice, new VertexPositionNormalTexture[] { new VertexPositionNormalTexture(new Vector3(0.015f, 0.015f, 0), new Vector3(0, 1, 1), new Vector2(0, 0)), //Top Left. new VertexPositionNormalTexture(new Vector3(-0.015f, -0.015f, 0), new Vector3(0, 1, 1), new Vector2(0, 0)) //Bottom right. }); MeshDraw meshDraw = new MeshDraw { PrimitiveType = PrimitiveType.LineStrip, // Tell the GPU that this is a line. VertexBuffers = new[] { new VertexBufferBinding(vBuffer, VertexPositionNormalTexture.Layout, vBuffer.ElementCount) }, DrawCount = vBuffer.ElementCount }; Mesh mesh = new Mesh(); mesh.Draw = meshDraw; Model model = new Model(); model.Add(mesh); m_DotMesh = new ModelComponent(model); m_Dot = new Entity(); m_Dot.Add(m_DotMesh); this.Entity.AddChild(m_Dot); Destroy(); }
/// <summary> /// Reverses the winding order of an index buffer. Assumes it is stored in <see cref="PrimitiveType.TriangleList"/> format. /// Works on both 32 and 16 bit indices. /// </summary> /// <param name="outBytes">Output of the operation, the indices matching the reversed winding order</param> public static unsafe bool GetReversedWindingOrder(this MeshDraw meshData, out byte[] outBytes) { // Initially set output to null outBytes = null; // For now, require a MeshData with only one vertex buffer and no index buffer if (meshData.VertexBuffers.Length != 1 || meshData.IndexBuffer == null) { return(false); } // Need to be triangle list format if (meshData.PrimitiveType != PrimitiveType.TriangleList) { return(false); } // Create new index buffer var indexCount = meshData.IndexBuffer.Count; outBytes = new byte[indexCount * (meshData.IndexBuffer.Is32Bit ? sizeof(uint) : sizeof(ushort))]; fixed(byte *oldIndexBufferDataStart = &meshData.IndexBuffer.Buffer.GetDataSafe()[0]) fixed(byte *indexBufferDataStart = &outBytes[0]) { if (meshData.IndexBuffer.Is32Bit) { var oldIndexBufferDataPtr = (uint *)oldIndexBufferDataStart; var indexBufferDataPtr = (uint *)indexBufferDataStart; for (int i = 0; i < indexCount; i += 3) { // Swap second and third indices *indexBufferDataPtr++ = oldIndexBufferDataPtr[0]; *indexBufferDataPtr++ = oldIndexBufferDataPtr[2]; *indexBufferDataPtr++ = oldIndexBufferDataPtr[1]; oldIndexBufferDataPtr += 3; } } else { var oldIndexBufferDataPtr = (ushort *)oldIndexBufferDataStart; var indexBufferDataPtr = (ushort *)indexBufferDataStart; for (int i = 0; i < indexCount; i += 3) { // Swap second and third indices *indexBufferDataPtr++ = oldIndexBufferDataPtr[0]; *indexBufferDataPtr++ = oldIndexBufferDataPtr[2]; *indexBufferDataPtr++ = oldIndexBufferDataPtr[1]; oldIndexBufferDataPtr += 3; } } } return(true); }
/// <summary> /// Reverses the winding order of an index buffer. Assumes it is stored in <see cref="PrimitiveType.TriangleList"/> format. /// Works on both 32 and 16 bit indices. /// </summary> /// <param name="vertexBufferBinding">The vertex buffer binding.</param> /// <exception cref="System.NotImplementedException"></exception> public unsafe static bool ReverseWindingOrder(this MeshDraw meshData) { // For now, require a MeshData with only one vertex buffer and no index buffer if (meshData.VertexBuffers.Length != 1 || meshData.IndexBuffer == null) { return(false); } // Need to be triangle list format if (meshData.PrimitiveType != PrimitiveType.TriangleList) { return(false); } // Create new index buffer var indexCount = meshData.IndexBuffer.Count; var indexBufferData = new byte[indexCount * (meshData.IndexBuffer.Is32Bit ? sizeof(uint) : sizeof(ushort))]; fixed(byte *oldIndexBufferDataStart = &meshData.IndexBuffer.Buffer.GetDataSafe()[0]) fixed(byte *indexBufferDataStart = &indexBufferData[0]) { if (meshData.IndexBuffer.Is32Bit) { var oldIndexBufferDataPtr = (uint *)oldIndexBufferDataStart; var indexBufferDataPtr = (uint *)indexBufferDataStart; for (int i = 0; i < indexCount; i += 3) { // Swap second and third indices *indexBufferDataPtr++ = oldIndexBufferDataPtr[0]; *indexBufferDataPtr++ = oldIndexBufferDataPtr[2]; *indexBufferDataPtr++ = oldIndexBufferDataPtr[1]; oldIndexBufferDataPtr += 3; } } else { var oldIndexBufferDataPtr = (ushort *)oldIndexBufferDataStart; var indexBufferDataPtr = (ushort *)indexBufferDataStart; for (int i = 0; i < indexCount; i += 3) { // Swap second and third indices *indexBufferDataPtr++ = oldIndexBufferDataPtr[0]; *indexBufferDataPtr++ = oldIndexBufferDataPtr[2]; *indexBufferDataPtr++ = oldIndexBufferDataPtr[1]; oldIndexBufferDataPtr += 3; } } meshData.IndexBuffer = new IndexBufferBinding(new BufferData(BufferFlags.IndexBuffer, indexBufferData).ToSerializableVersion(), meshData.IndexBuffer.Is32Bit, indexCount); } return(true); }
/// <summary> /// Reverses the winding order of an index buffer. Assumes it is stored in <see cref="PrimitiveType.TriangleList"/> format. /// Works on both 32 and 16 bit indices. /// </summary> public static bool ReverseWindingOrder(this MeshDraw meshData) { byte[] newIndexBuffer; if (!GetReversedWindingOrder(meshData, out newIndexBuffer)) { return(false); } meshData.IndexBuffer = new IndexBufferBinding(new BufferData(BufferFlags.IndexBuffer, newIndexBuffer).ToSerializableVersion(), meshData.IndexBuffer.Is32Bit, meshData.IndexBuffer.Count); return(true); }
public void Build() { var indices = new int[2 * Tesselation * 3]; var vertices = new VertexPositionNormalTexture[(Tesselation + 1) * 3]; int indexCount = 0; int vertexCount = 0; // the two rings for (int j = 0; j < 3; j++) { var rotation = Matrix.Identity; if (j == 1) { rotation = Matrix.RotationX(MathF.PI / 2); } else if (j == 2) { rotation = Matrix.RotationY(MathF.PI / 2); } for (int i = 0; i <= Tesselation; i++) { var longitude = (float)(i * 2.0 * Math.PI / Tesselation); var dx = MathF.Cos(longitude); var dy = MathF.Sin(longitude); var normal = new Vector3(dx, dy, 0); Vector3.TransformNormal(ref normal, ref rotation, out normal); if (i < Tesselation) { indices[indexCount++] = vertexCount; indices[indexCount++] = vertexCount + 1; } vertices[vertexCount++] = new VertexPositionNormalTexture(normal, normal, new Vector2(0)); } } vertexBuffer = Buffer.Vertex.New(graphicsDevice, vertices); MeshDraw = new MeshDraw { PrimitiveType = PrimitiveType.LineList, DrawCount = indices.Length, IndexBuffer = new IndexBufferBinding(Buffer.Index.New(graphicsDevice, indices), true, indices.Length), VertexBuffers = new[] { new VertexBufferBinding(vertexBuffer, VertexPositionNormalTexture.Layout, vertexBuffer.ElementCount) }, }; }
/// <summary> /// Disposes all GPU buffers of a <see cref="MeshDraw"/>. Make sure it isn't used by the engine before calling this method. /// </summary> /// <param name="meshDraw">The mesh draw.</param> private static void DisposeBuffers(this MeshDraw meshDraw) { if (meshDraw != null) { meshDraw.IndexBuffer?.Buffer?.Dispose(); if (meshDraw.VertexBuffers != null) { foreach (var vb in meshDraw.VertexBuffers) { vb.Buffer?.Dispose(); } } } }
public static MeshDraw ToMeshDraw(this MeshDraw primitive) { var vertexBufferBinding = new VertexBufferBinding(primitive.VertexBuffers[0].Buffer, new VertexPositionNormalTexture().GetLayout(), primitive.VertexBuffers[0].Count); var indexBufferBinding = new IndexBufferBinding(primitive.IndexBuffer.Buffer, primitive.IndexBuffer.Is32Bit, primitive.IndexBuffer.Buffer.ElementCount); var data = new MeshDraw { StartLocation = 0, PrimitiveType = PrimitiveType.TriangleList, VertexBuffers = new[] { vertexBufferBinding }, IndexBuffer = indexBufferBinding, DrawCount = primitive.IndexBuffer.Buffer.ElementCount, }; return(data); }
public static MeshDraw ToMeshDraw <T>(this GeometricPrimitive <T> primitive) where T : struct, IVertex { var vertexBufferBinding = new VertexBufferBinding(primitive.VertexBuffer, new T().GetLayout(), primitive.VertexBuffer.ElementCount); var indexBufferBinding = new IndexBufferBinding(primitive.IndexBuffer, primitive.IsIndex32Bits, primitive.IndexBuffer.ElementCount); var data = new MeshDraw { StartLocation = 0, PrimitiveType = PrimitiveType.TriangleList, VertexBuffers = new[] { vertexBufferBinding }, IndexBuffer = indexBufferBinding, DrawCount = primitive.IndexBuffer.ElementCount, }; return(data); }
private MeshDraw CreateTileMeshDraw(GraphicsDevice device, VertexPositionNormalColor[] vertices, ushort[] indices) { var vertexBuffer = Buffer.Vertex.New(device, vertices, GraphicsResourceUsage.Dynamic).RecreateWith(vertices); var indexBuffer = Buffer.Index.New(device, indices).RecreateWith(indices); var meshDraw = new MeshDraw { PrimitiveType = PrimitiveType.TriangleList, VertexBuffers = new VertexBufferBinding[] { new VertexBufferBinding(vertexBuffer, VertexPositionNormalColor.Layout, vertexBuffer.ElementCount) }, IndexBuffer = new IndexBufferBinding(indexBuffer, false, indexBuffer.ElementCount), StartLocation = 0, DrawCount = indexBuffer.ElementCount, }; return(meshDraw); }
/// <summary> /// Creates an Entity that contains our dynamic Vertex and Index buffers. /// This Entity will be rendered by the model renderer. /// </summary> /// <param name="verticesCount"></param> /// <param name="indicesCount"></param> private void CreateTerrainModelEntity(int verticesCount, int indicesCount) { // Compute sizes var vertexDeclaration = VertexNormalTexture.VertexDeclaration; var vertexBufferSize = verticesCount * vertexDeclaration.CalculateSize(); var indexBufferSize = indicesCount * sizeof(int); // Create Vertex and Index buffers terrainVertexBuffer = Buffer.Vertex.New(GraphicsDevice, vertexBufferSize, GraphicsResourceUsage.Dynamic); terrainIndexBuffer = Buffer.New(GraphicsDevice, indexBufferSize, BufferFlags.IndexBuffer, GraphicsResourceUsage.Dynamic); // Prepare mesh and entity var meshDraw = new MeshDraw { PrimitiveType = PrimitiveType.TriangleStrip, VertexBuffers = new[] { new VertexBufferBinding(terrainVertexBuffer, vertexDeclaration, verticesCount) }, IndexBuffer = new IndexBufferBinding(terrainIndexBuffer, true, indicesCount), }; // var effect1 = EffectSystem.LoadEffect("SimpleTerrainEffectMain").WaitForResult(); // var effect2 = EffectSystem.LoadEffect("VertexTextureTerrain"); var effectMaterial = LoadAsset <Material>("mt_rock"); Texture tex0 = (Texture)effectMaterial.Parameters[MaterialKeys.DiffuseMap]; // rock Texture tex1 = (Texture)effectMaterial.Parameters[DiffuseMap1]; // grass Texture tex2 = (Texture)effectMaterial.Parameters[DiffuseMap2]; // water effectMaterial.Parameters.Add(VertexTextureTerrainKeys.MeshTexture0, tex1); effectMaterial.Parameters.Add(VertexTextureTerrainKeys.MeshTexture1, tex0); effectMaterial.Parameters.Add(VertexTextureTerrainKeys.MeshTexture2, tex2); effectMaterial.Parameters.Add(MaterialKeys.DiffuseMap, tex1); //terrainMesh = new Mesh { Draw = meshDraw /*, Material = LoadAsset<Material>("TerrainMaterial")*/ }; terrainMesh = new Mesh { Draw = meshDraw, MaterialIndex = 0 }; //terrainEntity = new Entity { { ModelComponent.Key, new ModelComponent { Model = new Model { terrainMesh } } } }; //TerrainEntity.Add<ModelComponent>( ModelComponent.Key, new ModelComponent { Model = new Model { terrainMesh } } ); TerrainEntity.Add <ModelComponent>(ModelComponent.Key, new ModelComponent { Model = new Model { terrainMesh, effectMaterial } }); }
void MakeNumberMesh(float location, int number, float size) { if (number > -1 && number < 10) { for (int line = 0; line < 7; line++) { if (Numbers[number].Lines[line]) { float Xstart = m_NumberLineStart[line].X * (size * 1.25f) + location; float Ystart = m_NumberLineStart[line].Y * size; float Xend = m_NumberLineEnd[line].X * (size * 1.25f) + location; float Yend = m_NumberLineEnd[line].Y * size; Vector3 start = new Vector3(Xstart, Ystart, 0); //numbers->getMesh()->addVertex(Xstart, Ystart, 0); Vector3 end = new Vector3(Xend, Yend, 0); //numbers->getMesh()->addVertex(Xend, Yend, 0); // VertexPositionNormalTexture is the layout that the engine uses in the shaders var vBuffer = Xenko.Graphics.Buffer.Vertex.New(GraphicsDevice, new VertexPositionNormalTexture[] { new VertexPositionNormalTexture(start, new Vector3(0, 1, 1), new Vector2(0, 0)), //Top. new VertexPositionNormalTexture(end, new Vector3(0, 1, 1), new Vector2(0, 0)), //Bottom right. }); MeshDraw meshDraw = new MeshDraw { PrimitiveType = PrimitiveType.LineStrip, // Tell the GPU that this is a line. VertexBuffers = new[] { new VertexBufferBinding(vBuffer, VertexPositionNormalTexture.Layout, vBuffer.ElementCount) }, DrawCount = vBuffer.ElementCount }; Mesh mesh = new Mesh(); mesh.Draw = meshDraw; Model model = new Model(); model.Add(mesh); m_NumberMeshs.Add(new ModelComponent(model)); m_Numbers.Add(new Entity()); m_Numbers[m_Numbers.Count - 1].Add(m_NumberMeshs[m_NumberMeshs.Count - 1]); this.Entity.AddChild(m_Numbers[m_Numbers.Count - 1]); } } } }
public void Build() { var indices = new int[12 * 2]; var vertices = new VertexPositionNormalTexture[8]; vertices[0] = new VertexPositionNormalTexture(new Vector3(-1, 1, -1), Vector3.UnitY, Vector2.Zero); vertices[1] = new VertexPositionNormalTexture(new Vector3(-1, 1, 1), Vector3.UnitY, Vector2.Zero); vertices[2] = new VertexPositionNormalTexture(new Vector3(1, 1, 1), Vector3.UnitY, Vector2.Zero); vertices[3] = new VertexPositionNormalTexture(new Vector3(1, 1, -1), Vector3.UnitY, Vector2.Zero); int indexOffset = 0; // Top sides for (int i = 0; i < 4; i++) { indices[indexOffset++] = i; indices[indexOffset++] = (i + 1) % 4; } // Duplicate vertices and indices to bottom part for (int i = 0; i < 4; i++) { vertices[i + 4] = vertices[i]; vertices[i + 4].Position.Y = -vertices[i + 4].Position.Y; indices[indexOffset++] = indices[i * 2] + 4; indices[indexOffset++] = indices[i * 2 + 1] + 4; } // Sides for (int i = 0; i < 4; i++) { indices[indexOffset++] = i; indices[indexOffset++] = i + 4; } vertexBuffer = Buffer.Vertex.New(graphicsDevice, vertices); MeshDraw = new MeshDraw { PrimitiveType = PrimitiveType.LineList, DrawCount = indices.Length, IndexBuffer = new IndexBufferBinding(Buffer.Index.New(graphicsDevice, indices), true, indices.Length), VertexBuffers = new[] { new VertexBufferBinding(vertexBuffer, VertexPositionNormalTexture.Layout, vertexBuffer.ElementCount) }, }; }
/// <summary> /// Compacts the index buffer from 32 bits to 16 bits per index, if possible. /// </summary> /// <param name="meshData">The mesh data.</param> /// <returns>Returns true if index buffer was actually compacted.</returns> /// <exception cref="System.NotImplementedException"></exception> public static unsafe bool CompactIndexBuffer(this MeshDraw meshData) { // Already processed? if (meshData.IndexBuffer == null || !meshData.IndexBuffer.Is32Bit) { return(false); } // For now, require a MeshData with only one vertex buffer and no index buffer if (meshData.VertexBuffers.Length != 1) { throw new NotImplementedException(); } var vertexBufferBinding = meshData.VertexBuffers[0]; var vertexCount = vertexBufferBinding.Count; // Can't compact? // Note that 65536 could be valid, but 0xFFFF is kept for primitive restart in strips. if (vertexCount >= 65536 || !meshData.IndexBuffer.Is32Bit) { return(false); } // Create new index buffer var indexCount = meshData.IndexBuffer.Count; var indexBufferData = new byte[indexCount * Utilities.SizeOf <ushort>()]; fixed(byte *oldIndexBufferDataStart = &meshData.IndexBuffer.Buffer.GetDataSafe()[0]) fixed(byte *indexBufferDataStart = &indexBufferData[0]) { var oldIndexBufferDataPtr = (int *)oldIndexBufferDataStart; var indexBufferDataPtr = (ushort *)indexBufferDataStart; for (int i = 0; i < indexCount; ++i) { // This also works to convert 0xFFFFFFFF into 0xFFFF (primitive restart in strips). *indexBufferDataPtr++ = (ushort)*oldIndexBufferDataPtr++; } meshData.IndexBuffer = new IndexBufferBinding(new BufferData(BufferFlags.IndexBuffer, indexBufferData).ToSerializableVersion(), false, indexCount); } return(true); }
/// <summary> /// Creates an Entity that contains our dynamic Vertex and Index buffers. /// This Entity will be rendered by the model renderer. /// </summary> /// <param name="verticesCount"></param> /// <param name="indicesCount"></param> private void CreateTerrainModelEntity(int verticesCount, int indicesCount) { // Compute sizes var vertexDeclaration = VertexNormalTexture.VertexDeclaration; var vertexBufferSize = verticesCount * vertexDeclaration.CalculateSize(); var indexBufferSize = indicesCount * sizeof(short); // Create Vertex and Index buffers terrainVertexBuffer = Buffer.Vertex.New(GraphicsDevice, vertexBufferSize, GraphicsResourceUsage.Dynamic); terrainIndexBuffer = Buffer.New(GraphicsDevice, indexBufferSize, BufferFlags.IndexBuffer, GraphicsResourceUsage.Dynamic); // Prepare mesh and entity var meshDraw = new MeshDraw { PrimitiveType = PrimitiveType.TriangleStrip, VertexBuffers = new[] { new VertexBufferBinding(terrainVertexBuffer, vertexDeclaration, verticesCount) }, IndexBuffer = new IndexBufferBinding(terrainIndexBuffer, false, indicesCount), }; // Load the material and set parameters TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.MeshTexture0, WaterTexture); TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.MeshTexture1, GrassTexture); TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.MeshTexture2, MountainTexture); // Set up material regions TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.MinimumHeight0, -10); TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.OptimalHeight0, 40); TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.MaximumHeight0, 70); TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.MinimumHeight1, 60); TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.OptimalHeight1, 80); TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.MaximumHeight1, 90); TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.MinimumHeight2, 85); TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.OptimalHeight2, 95); TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.MaximumHeight2, 125); terrainMesh = new Mesh { Draw = meshDraw, MaterialIndex = 0 }; TerrainEntity.GetOrCreate <ModelComponent>().Model = new Model { terrainMesh, TerrainMaterial }; }
protected Entity AddModelEntity(string suffix, MeshDraw mesh, Material material, Quaternion rotation = default, Vector3 position = default) { var entity = new Entity($"Model_{suffix}"); entity.Transform.Position = position; entity.Transform.Rotation = rotation; entity.Add(new ModelComponent { Model = new Model { material, new Mesh { Draw = mesh } }, RenderGroup = GizmoRenderGroup, }); ModelEntity.AddChild(entity); return(entity); }
/// <summary> /// Extracts a selection of vertices from a vertex buffer stored in this mesh data. /// </summary> /// <param name="meshData">The mesh data.</param> /// <param name="vertexElementToExtract">The declaration to extract (e.g. "POSITION0"...etc.) </param> public static T[] GetVertexBufferData <T>(this MeshDraw meshData, params string[] vertexElementToExtract) where T : struct { var declaration = meshData.VertexBuffers[0].Declaration; var offsets = declaration.EnumerateWithOffsets().Where(vertexElementOffset => vertexElementToExtract.Contains(vertexElementOffset.VertexElement.SemanticAsText)).ToList(); int expectedSize = offsets.Sum(vertexElementWithOffset => vertexElementWithOffset.Size); var count = meshData.VertexBuffers[0].Count; int outputSize = expectedSize * count; int checkSize = (int)(outputSize / Utilities.SizeOf <T>()) * Utilities.SizeOf <T>(); if (checkSize != outputSize) { throw new ArgumentException(string.Format("Size of T is not a multiple of totalSize {0}", outputSize)); } var output = new T[outputSize / Utilities.SizeOf <T>()]; var handleOutput = GCHandle.Alloc(output, GCHandleType.Pinned); var ptrOutput = handleOutput.AddrOfPinnedObject(); var handleInput = GCHandle.Alloc(meshData.VertexBuffers[0].Buffer.GetSerializationData().Content, GCHandleType.Pinned); var ptrInput = handleInput.AddrOfPinnedObject(); for (int i = 0; i < count; i++) { foreach (var vertexElementWithOffset in offsets) { Utilities.CopyMemory(ptrOutput, ptrInput + vertexElementWithOffset.Offset, vertexElementWithOffset.Size); ptrOutput = ptrOutput + vertexElementWithOffset.Size; } ptrInput += declaration.VertexStride; } handleInput.Free(); handleOutput.Free(); return(output); }
private void Draw(RenderDrawContext context, MeshDraw drawData, Vector4 color, DepthStencilStateDescription depthStencilState) { pipelineState.State.DepthStencilState = depthStencilState; pipelineState.State.Output.CaptureState(context.CommandList); pipelineState.Update(); context.CommandList.SetIndexBuffer(drawData.IndexBuffer.Buffer, drawData.IndexBuffer.Offset, drawData.IndexBuffer.Is32Bit); context.CommandList.SetPipelineState(pipelineState.CurrentState); shader.Parameters.Set(SelectionWireframeShaderKeys.LineColor, color); shader.Apply(context.GraphicsContext); if (drawData.IndexBuffer != null) { context.CommandList.DrawIndexed(drawData.DrawCount, drawData.StartLocation); } else { context.CommandList.Draw(drawData.DrawCount, drawData.StartLocation); } }
public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage) { float blendValue = (selectionService?.DisplaySelectionMask ?? false) ? 1.0f : MathUtil.Clamp((1.0f - (float)clockSelection.Elapsed.TotalSeconds), 0.0f, 1.0f); shader.UpdateEffect(context.GraphicsDevice); foreach (var renderNode in renderViewStage.SortedRenderNodes) { var renderMesh = renderNode.RenderObject as RenderMesh; if (renderMesh == null) { continue; } MeshDraw drawData = renderMesh.ActiveMeshDraw; // bind VB for (int slot = 0; slot < drawData.VertexBuffers.Length; slot++) { var vertexBuffer = drawData.VertexBuffers[slot]; context.CommandList.SetVertexBuffer(slot, vertexBuffer.Buffer, vertexBuffer.Offset, vertexBuffer.Stride); } // set shader parameters shader.Parameters.Set(SelectionWireframeShaderKeys.WorldViewProjection, renderMesh.World * renderView.ViewProjection); // matrix shader.Parameters.Set(SelectionWireframeShaderKeys.WorldScale, new Vector3(1.0001f)); // increase scale to avoid z-fight shader.Parameters.Set(SelectionWireframeShaderKeys.Viewport, new Vector4(context.RenderContext.RenderView.ViewSize, 0, 0)); shader.Parameters.Set(SelectionWireframeShaderKeys.LineWidth, LineWidth); // prepare pipeline state pipelineState.State.RootSignature = shader.RootSignature; pipelineState.State.EffectBytecode = shader.Effect.Bytecode; pipelineState.State.PrimitiveType = drawData.PrimitiveType; Draw(context, drawData, GetColor(ColorOccludedLines, blendValue), DepthStencilStates.None); // occluded Draw(context, drawData, GetColor(ColorNonOccludedLines, blendValue), DepthStencilStates.DepthRead); // non-occluded } }
/// <summary> /// Generates an index buffer for this mesh data. /// </summary> /// <param name="meshData">The mesh data.</param> /// <param name="declaration">The final vertex declaration</param> public static unsafe void GenerateIndexBuffer(this MeshDraw meshData, VertexDeclaration declaration) { // For now, require a MeshData with only one vertex buffer and no index buffer if (meshData.VertexBuffers.Length != 1 || meshData.IndexBuffer != null) { throw new NotImplementedException(); } var oldVertexBuffer = meshData.VertexBuffers[0]; var oldVertexStride = oldVertexBuffer.Declaration.VertexStride; var newVertexStride = declaration.VertexStride; var indexMapping = GenerateIndexMapping(oldVertexBuffer, null); var vertices = indexMapping.Vertices; // Generate vertex buffer var vertexBufferData = new byte[declaration.VertexStride * indexMapping.Vertices.Length]; fixed(byte *oldVertexBufferDataStart = &oldVertexBuffer.Buffer.GetDataSafe()[oldVertexBuffer.Offset]) fixed(byte *vertexBufferDataStart = &vertexBufferData[0]) { var vertexBufferDataCurrent = vertexBufferDataStart; for (int i = 0; i < vertices.Length; ++i) { Utilities.CopyMemory((IntPtr)vertexBufferDataCurrent, new IntPtr(&oldVertexBufferDataStart[oldVertexStride * vertices[i]]), newVertexStride); vertexBufferDataCurrent += newVertexStride; } meshData.VertexBuffers[0] = new VertexBufferBinding(new BufferData(BufferFlags.VertexBuffer, vertexBufferData).ToSerializableVersion(), declaration, indexMapping.Vertices.Length); } // Generate index buffer var indexBufferData = new byte[indexMapping.Indices.Length * Utilities.SizeOf <int>()]; fixed(int *indexDataStart = &indexMapping.Indices[0]) fixed(byte *indexBufferDataStart = &indexBufferData[0]) { Utilities.CopyMemory((IntPtr)indexBufferDataStart, (IntPtr)indexDataStart, indexBufferData.Length); meshData.IndexBuffer = new IndexBufferBinding(new BufferData(BufferFlags.IndexBuffer, indexBufferData).ToSerializableVersion(), true, indexMapping.Indices.Length); } }
public override MeshDraw CreateDebugPrimitive(GraphicsDevice device) { if (cachedDebugPrimitive != null) { return(cachedDebugPrimitive); } var verts = new VertexPositionNormalTexture[pointsList.Count]; for (var i = 0; i < pointsList.Count; i++) { verts[i].Position = pointsList[i]; verts[i].TextureCoordinate = Vector2.Zero; verts[i].Normal = Vector3.Zero; } var intIndices = indicesList.Select(x => (int)x).ToArray(); ////calculate basic normals ////todo verify, winding order might be wrong? for (var i = 0; i < indicesList.Count; i += 3) { var i1 = intIndices[i]; var i2 = intIndices[i + 1]; var i3 = intIndices[i + 2]; var a = verts[i1]; var b = verts[i2]; var c = verts[i3]; var n = Vector3.Cross((b.Position - a.Position), (c.Position - a.Position)); n.Normalize(); verts[i1].Normal = verts[i2].Normal = verts[i3].Normal = n; } var meshData = new GeometricMeshData <VertexPositionNormalTexture>(verts, intIndices, false); cachedDebugPrimitive = new GeometricPrimitive(device, meshData).ToMeshDraw(); return(cachedDebugPrimitive); }
/// <summary> /// Determines whether the specified mesh draw data is simple. /// A <see cref="MeshDrawData"/> is simple if: /// * It contains only one <see cref="VertexBufferBindingData"/>, which must be simple. /// * It contains either no <see cref="IndexBufferBindingData"/>, or a simple one. /// * StartLocation is 0. /// * DrawCount is IndexBuffer.Count if there is an index buffer, otherwise VertexBuffers[0].Count. /// </summary> /// <param name="meshDrawData">The mesh draw data.</param> /// <returns></returns> public static bool IsSimple(this MeshDraw meshDrawData) { if (meshDrawData.VertexBuffers.Length != 1) { return(false); } if (!meshDrawData.VertexBuffers[0].IsSimple()) { return(false); } if (meshDrawData.IndexBuffer != null) { if (!meshDrawData.IndexBuffer.IsSimple()) { return(false); } if (meshDrawData.DrawCount != meshDrawData.IndexBuffer.Count) { return(false); } } else { if (meshDrawData.DrawCount != meshDrawData.VertexBuffers[0].Count) { return(false); } } if (meshDrawData.StartLocation != 0) { return(false); } return(true); }
public void Generate(IServiceRegistry services, Model model) { if (model == null) throw new ArgumentNullException(nameof(model)); var needsTempDevice = false; var graphicsDevice = services?.GetSafeServiceAs<IGraphicsDeviceService>().GraphicsDevice; if (graphicsDevice == null) { graphicsDevice = GraphicsDevice.New(); needsTempDevice = true; } var data = CreatePrimitiveMeshData(); if (data.Vertices.Length == 0) { throw new InvalidOperationException("Invalid GeometricPrimitive [{0}]. Expecting non-zero Vertices array"); } if (LocalOffset != Vector3.Zero) { for (var index = 0; index < data.Vertices.Length; index++) { data.Vertices[index].Position += LocalOffset; } } //Scale if necessary if (Scale != Vector3.One) { var inverseMatrix = Matrix.Scaling(Scale); inverseMatrix.Invert(); for (var index = 0; index < data.Vertices.Length; index++) { data.Vertices[index].Position *= Scale; Vector3.TransformCoordinate(ref data.Vertices[index].Normal, ref inverseMatrix, out data.Vertices[index].Normal); } } var boundingBox = BoundingBox.Empty; for (int i = 0; i < data.Vertices.Length; i++) BoundingBox.Merge(ref boundingBox, ref data.Vertices[i].Position, out boundingBox); BoundingSphere boundingSphere; unsafe { fixed (void* verticesPtr = data.Vertices) BoundingSphere.FromPoints((IntPtr)verticesPtr, 0, data.Vertices.Length, VertexPositionNormalTexture.Size, out boundingSphere); } var originalLayout = data.Vertices[0].GetLayout(); // Generate Tangent/BiNormal vectors var resultWithTangentBiNormal = VertexHelper.GenerateTangentBinormal(originalLayout, data.Vertices, data.Indices); // Generate Multitexcoords var result = VertexHelper.GenerateMultiTextureCoordinates(resultWithTangentBiNormal); var meshDraw = new MeshDraw(); var layout = result.Layout; var vertexBuffer = result.VertexBuffer; var indices = data.Indices; if (indices.Length < 0xFFFF) { var indicesShort = new ushort[indices.Length]; for (int i = 0; i < indicesShort.Length; i++) { indicesShort[i] = (ushort)indices[i]; } meshDraw.IndexBuffer = new IndexBufferBinding(Buffer.Index.New(graphicsDevice, indicesShort).RecreateWith(indicesShort), false, indices.Length); if (needsTempDevice) { var indexData = BufferData.New(BufferFlags.IndexBuffer, indicesShort); meshDraw.IndexBuffer = new IndexBufferBinding(indexData.ToSerializableVersion(), false, indices.Length); } } else { if (graphicsDevice.Features.CurrentProfile <= GraphicsProfile.Level_9_3) { throw new InvalidOperationException("Cannot generate more than 65535 indices on feature level HW <= 9.3"); } meshDraw.IndexBuffer = new IndexBufferBinding(Buffer.Index.New(graphicsDevice, indices).RecreateWith(indices), true, indices.Length); if (needsTempDevice) { var indexData = BufferData.New(BufferFlags.IndexBuffer, indices); meshDraw.IndexBuffer = new IndexBufferBinding(indexData.ToSerializableVersion(), true, indices.Length); } } meshDraw.VertexBuffers = new[] { new VertexBufferBinding(Buffer.New(graphicsDevice, vertexBuffer, BufferFlags.VertexBuffer).RecreateWith(vertexBuffer), layout, data.Vertices.Length) }; if (needsTempDevice) { var vertexData = BufferData.New(BufferFlags.VertexBuffer, vertexBuffer); meshDraw.VertexBuffers = new[] { new VertexBufferBinding(vertexData.ToSerializableVersion(), layout, data.Vertices.Length) }; } meshDraw.DrawCount = indices.Length; meshDraw.PrimitiveType = PrimitiveType.TriangleList; var mesh = new Mesh { Draw = meshDraw, BoundingBox = boundingBox, BoundingSphere = boundingSphere }; model.BoundingBox = boundingBox; model.BoundingSphere = boundingSphere; model.Add(mesh); if (MaterialInstance?.Material != null) { model.Materials.Add(MaterialInstance); } if (needsTempDevice) { graphicsDevice.Dispose(); } }
/// <param name="context"></param> /// <inheritdoc/> public override void PrepareEffectPermutations(RenderDrawContext context) { var renderEffects = RootRenderFeature.RenderData.GetData(renderEffectKey); var tessellationStates = RootRenderFeature.RenderData.GetData(tessellationStateKey); int effectSlotCount = ((RootEffectRenderFeature)RootRenderFeature).EffectPermutationSlotCount; foreach (var renderObject in RootRenderFeature.RenderObjects) { var staticObjectNode = renderObject.StaticObjectNode; var renderMesh = (RenderMesh)renderObject; var material = renderMesh.Material; var materialInfo = renderMesh.MaterialInfo; // Material use first 16 bits var materialHashCode = material != null ? (uint)material.GetHashCode() : 0; renderObject.StateSortKey = (renderObject.StateSortKey & 0x0000FFFF) | (materialHashCode << 16); var tessellationState = tessellationStates[staticObjectNode]; // Update draw data if tessellation is active if (material.TessellationMethod != XenkoTessellationMethod.None) { var tessellationMeshDraw = tessellationState.MeshDraw; if (tessellationState.Method != material.TessellationMethod) { tessellationState.Method = material.TessellationMethod; var oldMeshDraw = renderMesh.ActiveMeshDraw; tessellationMeshDraw = new MeshDraw { VertexBuffers = oldMeshDraw.VertexBuffers, IndexBuffer = oldMeshDraw.IndexBuffer, DrawCount = oldMeshDraw.DrawCount, StartLocation = oldMeshDraw.StartLocation, PrimitiveType = tessellationState.Method.GetPrimitiveType(), }; // adapt the primitive type and index buffer to the tessellation used if (tessellationState.Method.PerformsAdjacentEdgeAverage()) { renderMeshesToGenerateAEN.Add(renderMesh); } else { // Not using AEN tessellation anymore, dispose AEN indices if they were generated Utilities.Dispose(ref tessellationState.GeneratedIndicesAEN); } tessellationState.MeshDraw = tessellationMeshDraw; // Save back new state tessellationStates[staticObjectNode] = tessellationState; // Reset pipeline states for (int i = 0; i < effectSlotCount; ++i) { var staticEffectObjectNode = staticObjectNode * effectSlotCount + i; var renderEffect = renderEffects[staticEffectObjectNode]; if (renderEffect != null) renderEffect.PipelineState = null; } } renderMesh.ActiveMeshDraw = tessellationState.MeshDraw; } else if (tessellationState.GeneratedIndicesAEN != null) { // Not using tessellation anymore, dispose AEN indices if they were generated Utilities.Dispose(ref tessellationState.GeneratedIndicesAEN); } for (int i = 0; i < effectSlotCount; ++i) { var staticEffectObjectNode = staticObjectNode * effectSlotCount + i; var renderEffect = renderEffects[staticEffectObjectNode]; // Skip effects not used during this frame if (renderEffect == null || !renderEffect.IsUsedDuringThisFrame(RenderSystem)) continue; if (materialInfo == null || materialInfo.Material != material) { // First time this material is initialized, let's create associated info if (!allMaterialInfos.TryGetValue(material, out materialInfo)) { materialInfo = new MaterialInfo(material); allMaterialInfos.Add(material, materialInfo); } renderMesh.MaterialInfo = materialInfo; } if (materialInfo.CullMode != material.CullMode) { materialInfo.CullMode = material.CullMode; renderEffect.PipelineState = null; } var isMaterialParametersChanged = materialInfo.MaterialParameters != material.Parameters; if (isMaterialParametersChanged // parameter fast reload? || materialInfo.PermutationCounter != material.Parameters.PermutationCounter) { materialInfo.VertexStageSurfaceShaders = material.Parameters.Get(MaterialKeys.VertexStageSurfaceShaders); materialInfo.VertexStageStreamInitializer = material.Parameters.Get(MaterialKeys.VertexStageStreamInitializer); materialInfo.DomainStageSurfaceShaders = material.Parameters.Get(MaterialKeys.DomainStageSurfaceShaders); materialInfo.DomainStageStreamInitializer = material.Parameters.Get(MaterialKeys.DomainStageStreamInitializer); materialInfo.TessellationShader = material.Parameters.Get(MaterialKeys.TessellationShader); materialInfo.PixelStageSurfaceShaders = material.Parameters.Get(MaterialKeys.PixelStageSurfaceShaders); materialInfo.PixelStageStreamInitializer = material.Parameters.Get(MaterialKeys.PixelStageStreamInitializer); materialInfo.HasNormalMap = material.Parameters.Get(MaterialKeys.HasNormalMap); materialInfo.MaterialParameters = material.Parameters; materialInfo.ParametersChanged = isMaterialParametersChanged; materialInfo.PermutationCounter = material.Parameters.PermutationCounter; } // VS if (materialInfo.VertexStageSurfaceShaders != null) renderEffect.EffectValidator.ValidateParameter(MaterialKeys.VertexStageSurfaceShaders, materialInfo.VertexStageSurfaceShaders); if (materialInfo.VertexStageStreamInitializer != null) renderEffect.EffectValidator.ValidateParameter(MaterialKeys.VertexStageStreamInitializer, materialInfo.VertexStageStreamInitializer); // DS if (materialInfo.DomainStageSurfaceShaders != null) renderEffect.EffectValidator.ValidateParameter(MaterialKeys.DomainStageSurfaceShaders, materialInfo.DomainStageSurfaceShaders); if (materialInfo.DomainStageStreamInitializer != null) renderEffect.EffectValidator.ValidateParameter(MaterialKeys.DomainStageStreamInitializer, materialInfo.DomainStageStreamInitializer); // Tessellation if (materialInfo.TessellationShader != null) renderEffect.EffectValidator.ValidateParameter(MaterialKeys.TessellationShader, materialInfo.TessellationShader); // PS if (materialInfo.PixelStageSurfaceShaders != null) renderEffect.EffectValidator.ValidateParameter(MaterialKeys.PixelStageSurfaceShaders, materialInfo.PixelStageSurfaceShaders); if (materialInfo.PixelStageStreamInitializer != null) renderEffect.EffectValidator.ValidateParameter(MaterialKeys.PixelStageStreamInitializer, materialInfo.PixelStageStreamInitializer); if (materialInfo.HasNormalMap) renderEffect.EffectValidator.ValidateParameter(MaterialKeys.HasNormalMap, materialInfo.HasNormalMap); } } }
public void Generate(IServiceRegistry services, Model model) { if (services == null) throw new ArgumentNullException("services"); if (model == null) throw new ArgumentNullException("model"); var graphicsDevice = services.GetSafeServiceAs<IGraphicsDeviceService>().GraphicsDevice; var data = this.CreatePrimitiveMeshData(); if (data.Vertices.Length == 0) { throw new InvalidOperationException("Invalid GeometricPrimitive [{0}]. Expecting non-zero Vertices array"); } var boundingBox = BoundingBox.Empty; for (int i = 0; i < data.Vertices.Length; i++) BoundingBox.Merge(ref boundingBox, ref data.Vertices[i].Position, out boundingBox); BoundingSphere boundingSphere; unsafe { fixed (void* verticesPtr = data.Vertices) BoundingSphere.FromPoints((IntPtr)verticesPtr, 0, data.Vertices.Length, VertexPositionNormalTexture.Size, out boundingSphere); } var originalLayout = data.Vertices[0].GetLayout(); // Generate Tangent/BiNormal vectors var resultWithTangentBiNormal = VertexHelper.GenerateTangentBinormal(originalLayout, data.Vertices, data.Indices); // Generate Multitexcoords var result = VertexHelper.GenerateMultiTextureCoordinates(resultWithTangentBiNormal); var meshDraw = new MeshDraw(); var layout = result.Layout; var vertexBuffer = result.VertexBuffer; var indices = data.Indices; if (indices.Length < 0xFFFF) { var indicesShort = new ushort[indices.Length]; for (int i = 0; i < indicesShort.Length; i++) { indicesShort[i] = (ushort)indices[i]; } meshDraw.IndexBuffer = new IndexBufferBinding(Buffer.Index.New(graphicsDevice, indicesShort).RecreateWith(indicesShort), false, indices.Length); } else { if (graphicsDevice.Features.Profile <= GraphicsProfile.Level_9_3) { throw new InvalidOperationException("Cannot generate more than 65535 indices on feature level HW <= 9.3"); } meshDraw.IndexBuffer = new IndexBufferBinding(Buffer.Index.New(graphicsDevice, indices).RecreateWith(indices), true, indices.Length); } meshDraw.VertexBuffers = new[] { new VertexBufferBinding(Buffer.New(graphicsDevice, vertexBuffer, BufferFlags.VertexBuffer).RecreateWith(vertexBuffer), layout, data.Vertices.Length) }; meshDraw.DrawCount = indices.Length; meshDraw.PrimitiveType = PrimitiveType.TriangleList; var mesh = new Mesh { Draw = meshDraw, BoundingBox = boundingBox, BoundingSphere = boundingSphere }; model.BoundingBox = boundingBox; model.BoundingSphere = boundingSphere; model.Add(mesh); if (MaterialInstance != null && MaterialInstance.Material != null) { model.Materials.Add(MaterialInstance); } }