/// <summary> /// /// </summary> /// <typeparam name="T">The type of the vertices</typeparam> /// <param name="primitiveT">The type of primitives to draw with the vertices</param> /// <param name="vertexData">An array of vertices to draw</param> /// <param name="vertexOffset">The index in the array of the first vertex to draw</param> /// <param name="numVertices">The number of vertices to draw</param> /// <param name="indexData">The index data</param> /// <param name="indexOffset">The index in the array of indices of the first index to use</param> /// <param name="primitiveCount">The number of primitives to draw</param> /// <param name="vertexDeclaration">The layout of the vertices</param> public void DrawUserIndexedPrimitives <T>(PrimitiveType primitiveT, T[] vertexData, int vertexOffset, int numVertices, short[] indexData, int indexOffset, int primitiveCount, VertexDeclaration vertexDeclaration) where T : struct { if (vertexData == null || vertexData.Length == 0) { throw new ArgumentNullException("vertexData"); } if (vertexOffset < 0 || vertexOffset >= vertexData.Length) { throw new ArgumentNullException("vertexOffset"); } if (numVertices <= 0 || numVertices > vertexData.Length) { throw new ArgumentNullException("numVertices"); } if (vertexOffset + numVertices > vertexData.Length) { throw new ArgumentOutOfRangeException("numVertices & vertexOffset out of index"); } if (indexData == null || indexData.Length == 0) { throw new ArgumentNullException("indexData"); } if (indexOffset < 0 || indexOffset >= indexData.Length) { throw new ArgumentOutOfRangeException("indexOffset"); } if (primitiveCount <= 0) { throw new ArgumentOutOfRangeException("primitiveCount"); } if (indexOffset + GetElementCountArray(primitiveT, primitiveCount) > indexData.Length) { throw new ArgumentOutOfRangeException("primitiveCount"); } if (vertexDeclaration == null) { throw new ArgumentNullException("vertexDeclaration"); } PlatformDrawUserIndexedPrimitives <T>(primitiveT, vertexData, vertexOffset, numVertices, indexData, indexOffset, primitiveCount, vertexDeclaration); unchecked { _graphicsMetrics._drawCount++; _graphicsMetrics._primitiveCount += primitiveCount; } }
private void PlatformDrawUserIndexedPrimitives <T>(PrimitiveType primitiveT, T[] vertexData, int vertexOffset, int numVertices, short[] indexData, int indexOffset, int primitiveCount, VertexDeclaration vertexDeclaration) { ApplyState(true); //Unbind current VBOs GL.BindBuffer(BufferTarget.ArrayBuffer, 0); GraphicsExtensions.CheckGLError(); GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); GraphicsExtensions.CheckGLError(); _vertexBuffersDirty = _indexBufferDirty = true; //固定对象的地址,这样可以防止垃圾回收器移动对象,从而破坏垃圾收集器的效率,使用Free方法尽快释放分配的句柄 var vbHandle = GCHandle.Alloc(vertexData, GCHandleType.Pinned); var ibHandle = GCHandle.Alloc(indexData, GCHandleType.Pinned); var vertexAddr = (IntPtr)(vbHandle.AddrOfPinnedObject().ToInt64() + vertexDeclaration.VertexStride * vertexOffset); vertexDeclaration.GraphicsDevice = this; //设置顶点声明指向VertexBuffer Data var programHash = _vertexShader.HashKey | _pixelShader.HashKey; vertexDeclaration.Apply(_vertexShader, vertexAddr, programHash); GL.DrawElements(PrimitiveTypeGL(primitiveT), GetElementCountArray(primitiveT, primitiveCount), DrawElementsType.UnsignedShort, (IntPtr)(ibHandle.AddrOfPinnedObject().ToInt64() + (indexOffset * sizeof(short)))); GraphicsExtensions.CheckGLError(); //Release Handle ibHandle.Free(); vbHandle.Free(); }