SetBinding() public method

Set a binding, associating a vertex buffer with a given index.
If the index is already associated with a vertex buffer, the association will be replaced. This may cause the old buffer to be destroyed if nothing else is referring to it. You should assign bindings from 0 and not leave gaps, although you can bind them in any order.
public SetBinding ( short index, HardwareVertexBuffer buffer ) : void
index short Index at which to bind the buffer.
buffer HardwareVertexBuffer 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;
        }
Ejemplo n.º 2
0
		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
        }
Ejemplo n.º 4
0
        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);
        }