public SetBinding ( short index, |
||
index | short | Index at which to bind the buffer. |
buffer | Vertex buffer to bind. | |
return | void |
public Rectangle2D(bool includeTextureCoordinates) { vertexData = new VertexData(); vertexData.vertexStart = 0; vertexData.vertexCount = 4; VertexDeclaration decl = vertexData.vertexDeclaration; VertexBufferBinding binding = vertexData.vertexBufferBinding; decl.AddElement(POSITION, 0, VertexElementType.Float3, VertexElementSemantic.Position); HardwareVertexBuffer buffer = HardwareBufferManager.Instance.CreateVertexBuffer( decl.GetVertexSize(POSITION), vertexData.vertexCount, BufferUsage.StaticWriteOnly); binding.SetBinding(POSITION, buffer); if (includeTextureCoordinates) { decl.AddElement(TEXCOORD, 0, VertexElementType.Float2, VertexElementSemantic.TexCoords); buffer = HardwareBufferManager.Instance.CreateVertexBuffer( decl.GetVertexSize(TEXCOORD), vertexData.vertexCount, BufferUsage.StaticWriteOnly); binding.SetBinding(TEXCOORD, buffer); buffer.WriteData(0, buffer.Size, texCoords, true); } // TODO: Fix material = MaterialManager.Instance.GetByName("BaseWhite"); material.Lighting = false; }
protected void CreateCpuVertexData() { if ( this.mVertexDataRecord != null ) { DestroyCpuVertexData(); // create vertex structure, not using GPU for now (these are CPU structures) var dcl = new VertexDeclaration(); var bufbind = new VertexBufferBinding(); this.mVertexDataRecord.CpuVertexData = new VertexData( dcl, bufbind ); // Vertex declaration // TODO: consider vertex compression int offset = 0; // POSITION // float3(x, y, z) offset += dcl.AddElement( POSITION_BUFFER, offset, VertexElementType.Float3, VertexElementSemantic.Position ).Size; // UV0 // float2(u, v) // TODO - only include this if needing fixed-function offset += dcl.AddElement( POSITION_BUFFER, offset, VertexElementType.Float2, VertexElementSemantic.TexCoords, 0 ).Size; // UV1 delta information // float2(delta, deltaLODthreshold) offset = 0; offset += dcl.AddElement( DELTA_BUFFER, offset, VertexElementType.Float2, VertexElementSemantic.TexCoords, 1 ).Size; // Calculate number of vertices // Base geometry size * size var baseNumVerts = (int)Utility.Sqr( this.mVertexDataRecord.Size ); var numVerts = baseNumVerts; // Now add space for skirts // Skirts will be rendered as copies of the edge vertices translated downwards // Some people use one big fan with only 3 vertices at the bottom, // but this requires creating them much bigger that necessary, meaning // more unnecessary overdraw, so we'll use more vertices // You need 2^levels + 1 rows of full resolution (max 129) vertex copies, plus // the same number of columns. There are common vertices at intersections var levels = this.mVertexDataRecord.TreeLevels; this.mVertexDataRecord.NumSkirtRowsCols = (ushort)( System.Math.Pow( 2, levels ) + 1 ); this.mVertexDataRecord.SkirtRowColSkip = (ushort)( ( this.mVertexDataRecord.Size - 1 )/( this.mVertexDataRecord.NumSkirtRowsCols - 1 ) ); numVerts += this.mVertexDataRecord.Size*this.mVertexDataRecord.NumSkirtRowsCols; numVerts += this.mVertexDataRecord.Size*this.mVertexDataRecord.NumSkirtRowsCols; //manually create CPU-side buffer var posBuf = HardwareBufferManager.Instance.CreateVertexBuffer( dcl.Clone( POSITION_BUFFER ), numVerts, BufferUsage.StaticWriteOnly, false ); var deltabuf = HardwareBufferManager.Instance.CreateVertexBuffer( dcl.Clone( DELTA_BUFFER ), numVerts, BufferUsage.StaticWriteOnly, false ); this.mVertexDataRecord.CpuVertexData.vertexStart = 0; this.mVertexDataRecord.CpuVertexData.vertexCount = numVerts; var updateRect = new Rectangle( this.mOffsetX, this.mOffsetY, this.mBoundaryX, this.mBoundaryY ); UpdateVertexBuffer( posBuf, deltabuf, updateRect ); this.mVertexDataRecord.IsGpuVertexDataDirty = true; bufbind.SetBinding( POSITION_BUFFER, posBuf ); bufbind.SetBinding( DELTA_BUFFER, deltabuf ); } }
/// <summary> /// Modifies the vertex data to be suitable for use for rendering shadow geometry. /// </summary> /// <remarks> /// <para> /// Preparing vertex data to generate a shadow volume involves firstly ensuring that the /// vertex buffer containing the positions is a standalone vertex buffer, /// with no other components in it. This method will therefore break apart any existing /// vertex buffers if position is sharing a vertex buffer. /// Secondly, it will double the size of this vertex buffer so that there are 2 copies of /// the position data for the mesh. The first half is used for the original, and the second /// half is used for the 'extruded' version. The vertex count used to render will remain /// the same though, so as not to add any overhead to regular rendering of the object. /// Both copies of the position are required in one buffer because shadow volumes stretch /// from the original mesh to the extruded version. /// </para> /// <para> /// It's important to appreciate that this method can fundamentally change the structure of your /// vertex buffers, although in reality they will be new buffers. As it happens, if other /// objects are using the original buffers then they will be unaffected because the reference /// counting will keep them intact. However, if you have made any assumptions about the /// structure of the vertex data in the buffers of this object, you may have to rethink them. /// </para> /// </remarks> // TODO: Step through and test public void PrepareForShadowVolume() { /* NOTE * Sinbad would dearly, dearly love to just use a 4D position buffer in order to * store the extra 'w' value I need to differentiate between extruded and * non-extruded sections of the buffer, so that vertex programs could use that. * Hey, it works fine for GL. However, D3D9 in it's infinite stupidity, does not * support 4d position vertices in the fixed-function pipeline. If you use them, * you just see nothing. Since we can't know whether the application is going to use * fixed function or vertex programs, we have to stick to 3d position vertices and * store the 'w' in a separate 1D texture coordinate buffer, which is only used * when rendering the shadow. */ // Upfront, lets check whether we have vertex program capability RenderSystem renderSystem = Root.Instance.RenderSystem; bool useVertexPrograms = false; if (renderSystem != null && renderSystem.Caps.CheckCap(Capabilities.VertexPrograms)) { useVertexPrograms = true; } // Look for a position element VertexElement posElem = vertexDeclaration.FindElementBySemantic(VertexElementSemantic.Position); if (posElem != null) { ushort posOldSource = posElem.Source; HardwareVertexBuffer vbuf = vertexBufferBinding.GetBuffer(posOldSource); bool wasSharedBuffer = false; // Are there other elements in the buffer except for the position? if (vbuf.VertexSize > posElem.Size) { // We need to create another buffer to contain the remaining elements // Most drivers don't like gaps in the declaration, and in any case it's waste wasSharedBuffer = true; } HardwareVertexBuffer newPosBuffer = null, newRemainderBuffer = null; if (wasSharedBuffer) { newRemainderBuffer = HardwareBufferManager.Instance.CreateVertexBuffer( vbuf.VertexSize - posElem.Size, vbuf.VertexCount, vbuf.Usage, vbuf.HasShadowBuffer); } // Allocate new position buffer, will be FLOAT3 and 2x the size int oldVertexCount = vbuf.VertexCount; int newVertexCount = oldVertexCount * 2; newPosBuffer = HardwareBufferManager.Instance.CreateVertexBuffer( VertexElement.GetTypeSize(VertexElementType.Float3), newVertexCount, vbuf.Usage, vbuf.HasShadowBuffer); // Iterate over the old buffer, copying the appropriate elements and initializing the rest IntPtr baseSrcPtr = vbuf.Lock(BufferLocking.ReadOnly); // Point first destination pointer at the start of the new position buffer, // the other one half way along IntPtr destPtr = newPosBuffer.Lock(BufferLocking.Discard); // oldVertexCount * 3 * 4, since we are dealing with byte offsets here IntPtr dest2Ptr = new IntPtr(destPtr.ToInt32() + (oldVertexCount * 12)); int prePosVertexSize = 0; int postPosVertexSize = 0; int postPosVertexOffset = 0; if (wasSharedBuffer) { // Precalculate any dimensions of vertex areas outside the position prePosVertexSize = posElem.Offset; postPosVertexOffset = prePosVertexSize + posElem.Size; postPosVertexSize = vbuf.VertexSize - postPosVertexOffset; // the 2 separate bits together should be the same size as the remainder buffer vertex Debug.Assert(newRemainderBuffer.VertexSize == (prePosVertexSize + postPosVertexSize)); IntPtr baseDestRemPtr = newRemainderBuffer.Lock(BufferLocking.Discard); int baseSrcOffset = 0; int baseDestRemOffset = 0; unsafe { float *pDest = (float *)destPtr.ToPointer(); float *pDest2 = (float *)dest2Ptr.ToPointer(); int destCount = 0, dest2Count = 0; // Iterate over the vertices for (int v = 0; v < oldVertexCount; v++) { float *pSrc = (float *)((byte *)baseSrcPtr.ToPointer() + posElem.Offset + baseSrcOffset); // Copy position, into both buffers pDest[destCount++] = pDest2[dest2Count++] = pSrc[0]; pDest[destCount++] = pDest2[dest2Count++] = pSrc[1]; pDest[destCount++] = pDest2[dest2Count++] = pSrc[2]; // now deal with any other elements // Basically we just memcpy the vertex excluding the position if (prePosVertexSize > 0) { Memory.Copy( baseSrcPtr, baseDestRemPtr, baseSrcOffset, baseDestRemOffset, prePosVertexSize); } if (postPosVertexSize > 0) { Memory.Copy( baseSrcPtr, baseDestRemPtr, baseSrcOffset + postPosVertexOffset, baseDestRemOffset + prePosVertexSize, postPosVertexSize); } // increment the pointer offsets baseDestRemOffset += newRemainderBuffer.VertexSize; baseSrcOffset += vbuf.VertexSize; } // next vertex } // unsafe } else { // copy the data directly Memory.Copy(baseSrcPtr, destPtr, vbuf.Size); Memory.Copy(baseSrcPtr, dest2Ptr, vbuf.Size); } vbuf.Unlock(); newPosBuffer.Unlock(); if (wasSharedBuffer) { newRemainderBuffer.Unlock(); } // At this stage, he original vertex buffer is going to be destroyed // So we should force the deallocation of any temporary copies HardwareBufferManager.Instance.ForceReleaseBufferCopies(vbuf); if (useVertexPrograms) { unsafe { // Now it's time to set up the w buffer hardwareShadowVolWBuffer = HardwareBufferManager.Instance.CreateVertexBuffer( sizeof(float), newVertexCount, BufferUsage.StaticWriteOnly, false); // Fill the first half with 1.0, second half with 0.0 IntPtr wPtr = hardwareShadowVolWBuffer.Lock(BufferLocking.Discard); float *pDest = (float *)wPtr.ToPointer(); int destCount = 0; for (int v = 0; v < oldVertexCount; v++) { pDest[destCount++] = 1.0f; } for (int v = 0; v < oldVertexCount; v++) { pDest[destCount++] = 0.0f; } } // unsafe hardwareShadowVolWBuffer.Unlock(); } // if vertexPrograms ushort newPosBufferSource = 0; if (wasSharedBuffer) { // Get the a new buffer binding index newPosBufferSource = vertexBufferBinding.NextIndex; // Re-bind the old index to the remainder buffer vertexBufferBinding.SetBinding(posOldSource, newRemainderBuffer); } else { // We can just re-use the same source idex for the new position buffer newPosBufferSource = posOldSource; } // Bind the new position buffer vertexBufferBinding.SetBinding(newPosBufferSource, newPosBuffer); // Now, alter the vertex declaration to change the position source // and the offsets of elements using the same buffer for (int i = 0; i < vertexDeclaration.ElementCount; i++) { VertexElement element = vertexDeclaration.GetElement(i); if (element.Semantic == VertexElementSemantic.Position) { // Modify position to point at new position buffer vertexDeclaration.ModifyElement( i, newPosBufferSource, // new source buffer 0, // no offset now VertexElementType.Float3, VertexElementSemantic.Position); } else if (wasSharedBuffer && element.Source == posOldSource && element.Offset > prePosVertexSize) { // This element came after position, remove the position's // size vertexDeclaration.ModifyElement( i, posOldSource, // same old source element.Offset - posElem.Size, // less offset now element.Type, element.Semantic, element.Index); } } } // if posElem != null }
private void CreateBuffers(ushort[] indices, short[] vertices) { var numIndices = indices.Length; var numVertices = vertices.Length; _vertexDeclaration = HardwareBufferManager.Instance.CreateVertexDeclaration(); _vertexDeclaration.AddElement(0, 0, VertexElementType.Short2, VertexElementSemantic.Position); _ib = HardwareBufferManager.Instance.CreateIndexBuffer(IndexType.Size16, numIndices, BufferUsage.WriteOnly); _vb = HardwareBufferManager.Instance.CreateVertexBuffer(_vertexDeclaration, numVertices, BufferUsage.WriteOnly, false); _ib.WriteData(0, numIndices * sizeof(ushort), indices, true); _vb.WriteData(0, numVertices * sizeof(ushort), vertices, true); var binding = new VertexBufferBinding(); binding.SetBinding(0, _vb); VertexData = new VertexData(); VertexData.vertexDeclaration = _vertexDeclaration; VertexData.vertexBufferBinding = binding; VertexData.vertexCount = numVertices; VertexData.vertexStart = 0; IndexData = new IndexData(); IndexData.indexBuffer = _ib; IndexData.indexCount = numIndices; IndexData.indexStart = 0; }
protected void SetPointsImpl(List <Vector3> points, List <ColorEx> colors, List <List <VertexBoneAssignment> > boneAssignments) { if (colors != null && points.Count != colors.Count) { throw new Exception("Invalid parameters to SetPoints. Point list length does not match colors list length"); } Vector3 min = Vector3.Zero; Vector3 max = Vector3.Zero; // set up vertex data vertexData = new VertexData(); // set up vertex declaration VertexDeclaration vertexDeclaration = vertexData.vertexDeclaration; int currentOffset = 0; // always need positions vertexDeclaration.AddElement(0, currentOffset, VertexElementType.Float3, VertexElementSemantic.Position); currentOffset += VertexElement.GetTypeSize(VertexElementType.Float3); int colorOffset = currentOffset / sizeof(float); if (colors != null) { vertexDeclaration.AddElement(0, currentOffset, VertexElementType.Color, VertexElementSemantic.Diffuse); currentOffset += VertexElement.GetTypeSize(VertexElementType.Color); } int boneIndexOffset = currentOffset / sizeof(float); if (boneAssignments != null) { vertexDeclaration.AddElement(0, currentOffset, VertexElementType.UByte4, VertexElementSemantic.BlendIndices); currentOffset += VertexElement.GetTypeSize(VertexElementType.UByte4); } int boneWeightOffset = currentOffset / sizeof(float); if (boneAssignments != null) { vertexDeclaration.AddElement(0, currentOffset, VertexElementType.Float4, VertexElementSemantic.BlendWeights); currentOffset += VertexElement.GetTypeSize(VertexElementType.Float4); } int stride = currentOffset / sizeof(float); vertexData.vertexCount = points.Count; // allocate vertex buffer HardwareVertexBuffer vertexBuffer = HardwareBufferManager.Instance.CreateVertexBuffer(vertexDeclaration.GetVertexSize(0), vertexData.vertexCount, BufferUsage.StaticWriteOnly); // set up the binding, one source only VertexBufferBinding binding = vertexData.vertexBufferBinding; binding.SetBinding(0, vertexBuffer); // Generate vertex data unsafe { // lock the vertex buffer IntPtr data = vertexBuffer.Lock(BufferLocking.Discard); byte * pData = (byte *)data.ToPointer(); float *pFloat = (float *)pData; uint * pInt = (uint *)pData; for (int i = 0; i < points.Count; ++i) { Vector3 vec = points[i]; // assign to geometry pFloat[stride * i] = vec.x; pFloat[stride * i + 1] = vec.y; pFloat[stride * i + 2] = vec.z; if (colors != null) { // assign to diffuse pInt[stride * i + colorOffset] = Root.Instance.RenderSystem.ConvertColor(colors[i]); } if (boneAssignments != null) { for (int j = 0; j < 4; ++j) { pData[4 * (stride * i + boneIndexOffset) + j] = (byte)(boneAssignments[i][j].boneIndex); pFloat[stride * i + boneWeightOffset + j] = boneAssignments[i][j].weight; } } } // unlock the buffer vertexBuffer.Unlock(); } // unsafe for (int i = 0; i < points.Count; ++i) { Vector3 vec = points[i]; // Also update the bounding sphere radius float len = vec.Length; if (len > boundingSphereRadius) { boundingSphereRadius = len; } // Also update the bounding box if (vec.x < min.x) { min.x = vec.x; } if (vec.y < min.y) { min.y = vec.y; } if (vec.z < min.z) { min.z = vec.z; } if (vec.x > max.x) { max.x = vec.x; } if (vec.y > max.y) { max.y = vec.y; } if (vec.z > max.z) { max.z = vec.z; } } // Set the SimpleRenderable bounding box box = new AxisAlignedBox(min, max); }