Pre-transforms and batches up meshes for efficient use as instanced geometry in a scene Shader instancing allows to save both memory and draw calls. While StaticGeometry stores 500 times the same object in a batch to display 500 objects, this shader instancing implementation stores only 80 times the object, and then re-uses the vertex data with different shader parameter. Although you save memory, you make more draw call. However, you still make less draw calls than if you were rendering each object independently. Plus, you can move the batched objects independently of one another which you cannot do with StaticGeometry.
コード例 #1
0
ファイル: InstancedGeometry.cs プロジェクト: bostich83/axiom
            public GeometryBucket(MaterialBucket parent,
                                  String formatString, VertexData vData,
                                  IndexData iData)
                : base()
            {
                mParent       = parent;
                mFormatString = formatString;
                mVertexData   = null;
                mIndexData    = null;
                mBatch        = mParent.Parent.Parent.Parent;
                if (mBatch.BaseSkeleton != null)
                {
                    SetCustomParameter(0, new Vector4(mBatch.BaseSkeleton.BoneCount, 0, 0, 0));
                }

                mVertexData = vData.Clone(false);

                renderOperation.useIndices = true;
                renderOperation.indexData  = new IndexData();

                renderOperation.indexData.indexCount   = 0;
                renderOperation.indexData.indexStart   = 0;
                renderOperation.vertexData             = new VertexData();
                renderOperation.vertexData.vertexCount = 0;

                renderOperation.vertexData.vertexDeclaration = (VertexDeclaration)vData.vertexDeclaration.Clone();
                mIndexType = iData.indexBuffer.Type;
                // Derive the max vertices
                if (mIndexType == IndexType.Size32)
                {
                    mMaxVertexIndex = 0xFFFFFFFF;
                }
                else
                {
                    mMaxVertexIndex = 0xFFFF;
                }

                int   offset = 0, tcOffset = 0;
                short texCoordOffset = 0;
                short texCoordSource = 0;

                for (int i = 0; i < renderOperation.vertexData.vertexDeclaration.ElementCount; i++)
                {
                    if (renderOperation.vertexData.vertexDeclaration.GetElement(i).Semantic == VertexElementSemantic.TexCoords)
                    {
                        texCoordOffset++;
                        texCoordSource = renderOperation.vertexData.vertexDeclaration.GetElement(i).Source;
                        tcOffset       = renderOperation.vertexData.vertexDeclaration.GetElement(i).Offset + VertexElement.GetTypeSize(
                            renderOperation.vertexData.vertexDeclaration.GetElement(i).Type);
                    }
                    offset += VertexElement.GetTypeSize(renderOperation.vertexData.vertexDeclaration.GetElement(i).Type);
                }

                renderOperation.vertexData.vertexDeclaration.AddElement(texCoordSource, tcOffset, VertexElementType.Float1,
                                                                        VertexElementSemantic.TexCoords, texCoordOffset);

                mTexCoordIndex = texCoordOffset;
            }
コード例 #2
0
ファイル: InstancedGeometry.cs プロジェクト: bostich83/axiom
 private GeometryBucket(MaterialBucket parent, String formatString, GeometryBucket bucket)
     : base()
 {
     mParent       = parent;
     mFormatString = formatString;
     mBatch        = mParent.Parent.Parent.Parent;
     if (mBatch.BaseSkeleton != null)
     {
         SetCustomParameter(0, new Vector4(mBatch.BaseSkeleton.BoneCount, 0, 0, 0));
     }
     renderOperation = bucket.RenderOperation;
     mVertexData     = renderOperation.vertexData;
     mIndexData      = renderOperation.indexData;
     BoundingBox     = new BoundingBox(new Vector3(-10000, -10000, -10000), new Vector3(10000, 10000, 10000));
 }
コード例 #3
0
			private GeometryBucket( MaterialBucket parent, String formatString, GeometryBucket bucket )
				: base()
			{
				mParent = parent;
				mFormatString = formatString;
				mBatch = mParent.Parent.Parent.Parent;
				if ( mBatch.BaseSkeleton != null )
				{
					SetCustomParameter( 0, new Vector4( mBatch.BaseSkeleton.BoneCount, 0, 0, 0 ) );
				}
				renderOperation = bucket.RenderOperation;
				mVertexData = renderOperation.vertexData;
				mIndexData = renderOperation.indexData;
				BoundingBox = new BoundingBox( new Vector3( -10000, -10000, -10000 ), new Vector3( 10000, 10000, 10000 ) );
			}
コード例 #4
0
			public GeometryBucket( MaterialBucket parent,
			                       String formatString, VertexData vData,
			                       IndexData iData )
				: base()
			{
				mParent = parent;
				mFormatString = formatString;
				mVertexData = null;
				mIndexData = null;
				mBatch = mParent.Parent.Parent.Parent;
				if ( mBatch.BaseSkeleton != null )
				{
					SetCustomParameter( 0, new Vector4( mBatch.BaseSkeleton.BoneCount, 0, 0, 0 ) );
				}

				mVertexData = vData.Clone( false );

				renderOperation.useIndices = true;
				renderOperation.indexData = new IndexData();

				renderOperation.indexData.indexCount = 0;
				renderOperation.indexData.indexStart = 0;
				renderOperation.vertexData = new VertexData();
				renderOperation.vertexData.vertexCount = 0;

				renderOperation.vertexData.vertexDeclaration = (VertexDeclaration)vData.vertexDeclaration.Clone();
				mIndexType = iData.indexBuffer.Type;
				// Derive the max vertices
				if ( mIndexType == IndexType.Size32 )
				{
					mMaxVertexIndex = 0xFFFFFFFF;
				}
				else
				{
					mMaxVertexIndex = 0xFFFF;
				}

				int offset = 0, tcOffset = 0;
				short texCoordOffset = 0;
				short texCoordSource = 0;
				for ( int i = 0; i < renderOperation.vertexData.vertexDeclaration.ElementCount; i++ )
				{
					if ( renderOperation.vertexData.vertexDeclaration.GetElement( i ).Semantic == VertexElementSemantic.TexCoords )
					{
						texCoordOffset++;
						texCoordSource = renderOperation.vertexData.vertexDeclaration.GetElement( i ).Source;
						tcOffset = renderOperation.vertexData.vertexDeclaration.GetElement( i ).Offset + VertexElement.GetTypeSize(
							renderOperation.vertexData.vertexDeclaration.GetElement( i ).Type );
					}
					offset += VertexElement.GetTypeSize( renderOperation.vertexData.vertexDeclaration.GetElement( i ).Type );
				}

				renderOperation.vertexData.vertexDeclaration.AddElement( texCoordSource, tcOffset, VertexElementType.Float1,
				                                                         VertexElementSemantic.TexCoords, texCoordOffset );

				mTexCoordIndex = texCoordOffset;
			}
コード例 #5
0
		private void CreateInstanceGeom()
		{
			if ( Root.Instance.RenderSystem.HardwareCapabilities.HasCapability( Capabilities.VertexPrograms ) == false )
			{
				throw new AxiomException( "Your video card doesn't support batching" );
			}

			Entity ent = SceneManager.CreateEntity( meshes[ this.mSelectedMesh ], meshes[ this.mSelectedMesh ] + ".mesh" );


			this.renderInstance = new List<InstancedGeometry>( this.mNumRendered );

			//Load a mesh to read data from.	
			var batch = new InstancedGeometry( SceneManager, meshes[ this.mSelectedMesh ] + "s" );
			batch.CastShadows = true;

			batch.BatchInstanceDimensions = new Vector3( 1000000f, 1000000f, 1000000f );
			int batchSize = ( this.mNumMeshes > maxObjectsPerBatch ) ? maxObjectsPerBatch : this.mNumMeshes;
			SetupInstancedMaterialToEntity( ent );
			for ( int i = 0; i < batchSize; i++ )
			{
				batch.AddEntity( ent, Vector3.Zero );
			}
			batch.Origin = Vector3.Zero;

			batch.Build();


			for ( int k = 0; k < this.mNumRendered - 1; k++ )
			{
				batch.AddBatchInstance();
			}

			k = 0;
			foreach ( var batchInstance in batch.BatchInstances )
			{
				int j = 0;
				foreach ( var instancedObject in batchInstance.Objects )
				{
					instancedObject.Position = this.posMatrices[ k ][ j ];
					++j;
				}
				k++;
			}
			batch.IsVisible = true;
			this.renderInstance[ 0 ] = batch;

			SceneManager.RemoveEntity( ent );
		}