예제 #1
0
        /// <summary>
        /// Draws a collection of instances. Requires an HLSL effect designed for hardware instancing.
        /// </summary>
        /// <param name="device"></param>
        /// <param name="camera"></param>
        /// <param name="instances"></param>
        protected virtual void drawInstances(RenderParameters parameters, Matrix transform)
        {
            if (this.Instances.Length == 0)
            {
                return;
            }

            bool recalculate = this.instanceVertexBuffer == null || this.instanceVertexBuffer.IsContentLost || (parameters.IsMainRender && (this.instancesChanged || this.lastInstancesChanged));

            if (recalculate)
            {
                // If we have more instances than room in our vertex buffer, grow it to the neccessary size.
                if (this.instanceVertexBuffer == null || this.instanceVertexBuffer.IsContentLost || this.Instances.Length > this.instanceVertexBuffer.VertexCount)
                {
                    if (this.instanceVertexBuffer != null)
                    {
                        this.instanceVertexBuffer.Dispose();
                    }

                    int bufferSize = (int)Math.Pow(2.0, Math.Ceiling(Math.Log(this.Instances.Length, 2.0)));

                    this.instanceVertexBuffer = new DynamicVertexBuffer
                                                (
                        this.main.GraphicsDevice,
                        Model.instanceVertexDeclaration,
                        bufferSize,
                        BufferUsage.WriteOnly
                                                );

                    InstanceVertex[] newData = new InstanceVertex[bufferSize];
                    if (this.instanceVertexData != null)
                    {
                        Array.Copy(this.instanceVertexData, newData, Math.Min(bufferSize, this.instanceVertexData.Length));
                        for (int i = this.instanceVertexData.Length; i < this.Instances.Length; i++)
                        {
                            newData[i].LastTransform = this.Instances[i].Transform;
                        }
                    }
                    this.instanceVertexData = newData;
                }

                for (int i = 0; i < this.Instances.Length; i++)
                {
                    this.instanceVertexData[i].LastTransform = this.instanceVertexData[i].Transform;
                    Instance instance = this.Instances[i];
                    this.instanceVertexData[i].Transform = instance.Transform;
                    this.instanceVertexData[i].Param     = instance.Param;
                }

                // Transfer the latest instance transform matrices into the instanceVertexBuffer.
                this.instanceVertexBuffer.SetData <InstanceVertex>(this.instanceVertexData, 0, this.Instances.Length, SetDataOptions.Discard);

                this.lastInstancesChanged = this.instancesChanged;
                this.instancesChanged     = false;
            }

#if !MONOGAME // TODO: enable hardware instancing for MonoGame
            // Set up the instance rendering effect.
            if (this.setParameters(transform, parameters))
            {
                this.main.LightingManager.SetRenderParameters(this.effect, parameters);

                RasterizerState originalState = this.main.GraphicsDevice.RasterizerState;
                RasterizerState noCullState   = null;
                if (recalculate && this.DisableCulling)
                {
                    noCullState = new RasterizerState {
                        CullMode = CullMode.None
                    };
                    this.main.GraphicsDevice.RasterizerState = noCullState;
                }

                for (int i = 0; i < this.model.Meshes.Count; i++)
                {
                    ModelMesh mesh = this.model.Meshes[i];
                    for (int j = 0; j < mesh.MeshParts.Count; j++)
                    {
                        ModelMeshPart meshPart = mesh.MeshParts[j];
                        // Tell the GPU to read from both the model vertex buffer plus our instanceVertexBuffer.

                        // TODO: Monogame support for GraphicsDevice.SetVertexBuffers()
                        this.main.GraphicsDevice.SetVertexBuffers
                        (
                            new VertexBufferBinding(meshPart.VertexBuffer, meshPart.VertexOffset, 0),
                            new VertexBufferBinding(instanceVertexBuffer, 0, 1)
                        );

                        this.main.GraphicsDevice.Indices = meshPart.IndexBuffer;

                        // Draw all the instance copies in a single call.
                        this.effect.CurrentTechnique.Passes[0].Apply();
                        // TODO: Monogame support for GraphicsDevice.DrawInstancedPrimitives()
                        this.main.GraphicsDevice.DrawInstancedPrimitives
                        (
                            PrimitiveType.TriangleList,
                            0,
                            0,
                            meshPart.NumVertices,
                            meshPart.StartIndex,
                            meshPart.PrimitiveCount,
                            this.Instances.Length
                        );
                        Model.DrawCallCounter++;
                        Model.TriangleCounter += meshPart.PrimitiveCount * this.Instances.Length;
                    }
                }

                if (noCullState != null)
                {
                    this.main.GraphicsDevice.RasterizerState = originalState;
                }
            }
#endif

            if (parameters.IsMainRender)
            {
                this.lastTransform           = transform;
                this.lastWorldViewProjection = transform * parameters.Camera.ViewProjection;
            }
        }
예제 #2
0
파일: Model.cs 프로젝트: kernelbitch/Lemma
        /// <summary>
        /// Draws a collection of instances. Requires an HLSL effect designed for hardware instancing.
        /// </summary>
        /// <param name="device"></param>
        /// <param name="camera"></param>
        /// <param name="instances"></param>
        protected virtual void drawInstances(RenderParameters parameters, Matrix transform)
        {
            if (this.Instances.Count == 0)
                return;

            bool recalculate = this.instanceVertexBuffer == null || this.instanceVertexBuffer.IsContentLost || (parameters.IsMainRender && (this.instancesChanged || this.lastInstancesChanged));
            if (recalculate)
            {
                // If we have more instances than room in our vertex buffer, grow it to the neccessary size.
                if (this.instanceVertexBuffer == null || this.instanceVertexBuffer.IsContentLost || this.Instances.Count > this.instanceVertexBuffer.VertexCount)
                {
                    if (this.instanceVertexBuffer != null)
                        this.instanceVertexBuffer.Dispose();

                    int bufferSize = (int)Math.Pow(2.0, Math.Ceiling(Math.Log(this.Instances.Count, 2.0)));

                    this.instanceVertexBuffer = new DynamicVertexBuffer
                    (
                        this.main.GraphicsDevice,
                        Model.instanceVertexDeclaration,
                        bufferSize,
                        BufferUsage.WriteOnly
                    );

                    InstanceVertex[] newData = new InstanceVertex[bufferSize];
                    if (this.instanceVertexData != null)
                    {
                        Array.Copy(this.instanceVertexData, newData, Math.Min(bufferSize, this.instanceVertexData.Length));
                        for (int i = this.instanceVertexData.Length; i < this.Instances.Count; i++)
                            newData[i].LastTransform = this.Instances[i];
                    }
                    this.instanceVertexData = newData;
                }

                for (int i = 0; i < this.Instances.Count; i++)
                {
                    this.instanceVertexData[i].LastTransform = this.instanceVertexData[i].Transform;
                    this.instanceVertexData[i].Transform = this.Instances[i];
                    this.instanceVertexData[i].InstanceIndex = i;
                }

                // Transfer the latest instance transform matrices into the instanceVertexBuffer.
                this.instanceVertexBuffer.SetData<InstanceVertex>(this.instanceVertexData, 0, this.Instances.Count, SetDataOptions.Discard);

                this.lastInstancesChanged = this.instancesChanged;
                this.instancesChanged = false;
            }

            #if !MONOGAME // TODO: enable hardware instancing for MonoGame
            // Set up the instance rendering effect.
            if (this.setParameters(transform, parameters))
            {
                this.main.LightingManager.SetRenderParameters(this.effect, parameters);

                RasterizerState originalState = this.main.GraphicsDevice.RasterizerState;
                RasterizerState noCullState = null;
                if (recalculate && this.DisableCulling)
                {
                    noCullState = new RasterizerState { CullMode = CullMode.None };
                    this.main.GraphicsDevice.RasterizerState = noCullState;
                }

                foreach (ModelMesh mesh in this.model.Meshes)
                {
                    foreach (ModelMeshPart meshPart in mesh.MeshParts)
                    {
                        // Tell the GPU to read from both the model vertex buffer plus our instanceVertexBuffer.

                        // TODO: Monogame support for GraphicsDevice.SetVertexBuffers()
                        this.main.GraphicsDevice.SetVertexBuffers
                        (
                            new VertexBufferBinding(meshPart.VertexBuffer, meshPart.VertexOffset, 0),
                            new VertexBufferBinding(instanceVertexBuffer, 0, 1)
                        );

                        this.main.GraphicsDevice.Indices = meshPart.IndexBuffer;

                        // Draw all the instance copies in a single call.
                        foreach (EffectPass pass in this.effect.CurrentTechnique.Passes)
                        {
                            pass.Apply();
                            // TODO: Monogame support for GraphicsDevice.DrawInstancedPrimitives()
                            this.main.GraphicsDevice.DrawInstancedPrimitives
                            (
                                PrimitiveType.TriangleList,
                                0,
                                0,
                                meshPart.NumVertices,
                                meshPart.StartIndex,
                                meshPart.PrimitiveCount,
                                this.Instances.Count
                            );
                        }
                    }
                }

                if (noCullState != null)
                    this.main.GraphicsDevice.RasterizerState = originalState;
            }
            #endif

            if (parameters.IsMainRender)
            {
                this.lastTransform = transform;
                this.lastWorldViewProjection = transform * parameters.Camera.ViewProjection;
            }
        }