/// <summary> /// Renders this GeometryResource. /// </summary> /// <param name="renderState">Current render state.</param> public void Render(RenderState renderState) { D3D11.DeviceContext deviceContext = renderState.Device.DeviceImmediateContextD3D11; DXGI.Format indexBufferFormat = renderState.Device.SupportsOnly16BitIndexBuffer ? DXGI.Format.R16_UInt : DXGI.Format.R32_UInt; int lastVertexBufferID = -1; int lastIndexBufferID = -1; for (int loop = 0; loop < m_loadedStructures.Length; loop++) { LoadedStructureInfo structureToDraw = m_loadedStructures[loop]; // Apply VertexBuffer if (lastVertexBufferID != structureToDraw.VertexBufferID) { lastVertexBufferID = structureToDraw.VertexBufferID; deviceContext.InputAssembler.InputLayout = structureToDraw.InputLayout; deviceContext.InputAssembler.SetVertexBuffers(0, new D3D11.VertexBufferBinding(structureToDraw.VertexBuffer, structureToDraw.SizePerVertex, 0)); } // Apply IndexBuffer if (lastIndexBufferID != structureToDraw.IndexBufferID) { deviceContext.InputAssembler.SetIndexBuffer(structureToDraw.IndexBuffer, indexBufferFormat, 0); } // Apply material renderState.ApplyMaterial(structureToDraw.Material); D3D11.InputLayout newInputLayout = null; if (renderState.ForcedMaterial != null) { newInputLayout = renderState.ForcedMaterial.GenerateInputLayout( renderState.Device, StandardVertex.InputElements, MaterialApplyInstancingMode.SingleObject); deviceContext.InputAssembler.InputLayout = newInputLayout; } try { // Draw current rener block deviceContext.DrawIndexed( structureToDraw.IndexCount, structureToDraw.StartIndex, 0); } finally { if (newInputLayout != null) { deviceContext.InputAssembler.InputLayout = null; GraphicsHelper.SafeDispose(ref newInputLayout); } } } }
/// <summary> /// Builds vertex and index buffers. /// </summary> /// <param name="device">The device on which to build all buffers.</param> /// <param name="structures">All structure to be loaded.</param> /// <param name="resources">The current resource dictionary</param> protected virtual LoadedStructureInfo[] BuildBuffers(EngineDevice device, VertexStructure[] structures, ResourceDictionary resources) { List <LoadedStructureInfo> result = new List <LoadedStructureInfo>(structures.Length * 2); List <StandardVertex[]> cachedVertices = new List <StandardVertex[]>(2); List <int[]> cachedIndices = new List <int[]>(6); int structuresCount = structures.Length; int actVertexCount = 0; int actIndexCount = 0; int lastFinishedVertexBufferResultIndex = -1; int lastFinishedIndexBufferResultIndex = -1; int vertexBufferID = 0; int indexBufferID = 0; // Define the action which finishes current index buffer Action actionFinishIndexBuffer = () => { // Create the vertex buffer D3D11.Buffer indexBuffer = GraphicsHelper.CreateImmutableIndexBuffer( device, cachedIndices.ToArray()); cachedIndices.Clear(); actIndexCount = 0; indexBufferID++; // Do also create index buffer for (int loop = lastFinishedIndexBufferResultIndex + 1; loop < result.Count; loop++) { result[loop].IndexBuffer = indexBuffer; } lastFinishedIndexBufferResultIndex = result.Count - 1; }; // Define the action which finishes current vertex buffer Action actionFinishVertexBuffer = () => { // Create the vertex buffer D3D11.Buffer vertexBuffer = GraphicsHelper.CreateImmutableVertexBuffer( device, cachedVertices.ToArray()); cachedVertices.Clear(); actVertexCount = 0; vertexBufferID++; // Do also finish index buffers in this case actionFinishIndexBuffer(); // Do also create index buffer for (int loop = lastFinishedVertexBufferResultIndex + 1; loop < result.Count; loop++) { result[loop].VertexBuffer = vertexBuffer; } lastFinishedVertexBufferResultIndex = result.Count - 1; }; // Load all structures into memory within a loop for (int loopStruct = 0; loopStruct < structuresCount; loopStruct++) { VertexStructure actStructure = structures[loopStruct]; if (actStructure.CountVertices == 0) { continue; } if (actStructure.CountSurfaces == 0) { continue; } // Handle vertex data StandardVertex[] vertexArray = StandardVertex.FromVertexStructure(actStructure); if (actVertexCount + vertexArray.Length > MAX_VERTEX_COUNT_PER_BUFFER) { actionFinishVertexBuffer(); } cachedVertices.Add(vertexArray); int actBaseVertex = actVertexCount; actVertexCount += vertexArray.Length; // Sort all surfaces by material List <VertexStructureSurface> surfaceList = new List <VertexStructureSurface>(actStructure.Surfaces); surfaceList.Sort((left, right) => left.MaterialProperties.GetHashCode().CompareTo(right.MaterialProperties.GetHashCode())); int surfaceCount = surfaceList.Count; for (int loopSurface = 0; loopSurface < surfaceCount; loopSurface++) { VertexStructureSurface actSurface = surfaceList[loopSurface]; if (actSurface.CountTriangles == 0) { continue; } // Handle index data int[] indexArray = actSurface.GetIndexArray(); if (actBaseVertex > 0) { for (int loopIndex = 0; loopIndex < indexArray.Length; loopIndex++) { indexArray[loopIndex] = indexArray[loopIndex] + actBaseVertex; } } if (actIndexCount + indexArray.Length > MAX_INDEX_COUNT_PER_BUFFER) { actionFinishIndexBuffer(); } cachedIndices.Add(indexArray); actIndexCount += indexArray.Length; // Get or create the material LoadedStructureInfo lastStructureInfo = result.Count > 0 ? result[result.Count - 1] : null; if ((lastStructureInfo != null) && (lastStructureInfo.IndexBuffer == null) && (actSurface.MaterialProperties.Equals(lastStructureInfo.MaterialProperties))) { LoadedStructureInfo actStructureInfo = result[result.Count - 1]; actStructureInfo.IndexCount = actStructureInfo.IndexCount + indexArray.Length; } else { MaterialResource actMaterialResource = resources.GetOrCreateMaterialResourceAndEnsureLoaded(actSurface); // Create some information about the loaded structures LoadedStructureInfo newStructureInfo = new LoadedStructureInfo(); newStructureInfo.VertexBufferID = vertexBufferID; newStructureInfo.IndexBufferID = indexBufferID; newStructureInfo.SizePerVertex = StandardVertex.Size; newStructureInfo.VertexStructure = actStructure; newStructureInfo.IndexCount = indexArray.Length; newStructureInfo.StartIndex = actIndexCount - indexArray.Length; newStructureInfo.Material = actMaterialResource; newStructureInfo.MaterialProperties = actSurface.MaterialProperties; newStructureInfo.VertexBuffer = null; newStructureInfo.IndexBuffer = null; newStructureInfo.InputLayout = newStructureInfo.Material.GenerateInputLayout( device, StandardVertex.InputElements, MaterialApplyInstancingMode.SingleObject); result.Add(newStructureInfo); } } } // Finish all remaining buffers finally if (cachedVertices.Count > 0) { actionFinishVertexBuffer(); } if (cachedIndices.Count > 0) { actionFinishIndexBuffer(); } return(result.ToArray()); }