visual studio 2010 - XNA 4.0 में instancing का उपयोग करने में सहायता की आवश्यकता है



visual-studio-2010 optimization (1)

मैं XNA में instancing के बारे में पूछताछ करने आया हूँ

मैं एक शुरुआती एक्सएनए डेवलपर हूं, जो हाल ही में 2 डी से 3 डी गेम तक बढ़ रहा है।
मैं कूट में बड़ी संख्या में क्यूब्स खींचने की कोशिश कर रहा हूं, जैसा कि किसी को संदेह हो सकता है, इन क्यूब्स की एक बड़ी संख्या को आकर्षित करने से मेरे कंप्यूटर पर काफी तनाव होता है।
जैसा कि मैं प्रदर्शन को बढ़ाने के लिए एक मार्ग की तलाश कर रहा था, मैंने "इंस्टेंटिंग" शब्द भर में आया।
नहीं जानते कि XNA 4.0 में कैसे काम करता है, मैंने अपने स्तर के किसी के लिए ट्यूटोरियल उपयुक्त देखा है
हालांकि, एकमात्र ट्यूटोरियल जो मैंने पाया है (http://blogs.msdn.com/b/shawnhar/archive/2010/06/17/drawinstancedprimitives-in-xna-game-studio-4-0.aspx) है मेरे लिए कुछ भी उन्नत है मुझे लगता है कि वह मॉडल, मैश और जोश के बजाय कोने के लिए उपयोग कर रहा है, इसलिए मुझे पता नहीं लगा कि वास्तव में कौन सा कोड वास्तव में प्रासंगिक है और मैं इसके बाद क्या कर रहा हूं।

यही कारण है कि मैं तुम्हारे पास आ गया हूं। यदि कोई मुझे सरल (यदि संभव हो) ट्यूटोरियल या कोड स्निपेट बताता है कि XNA 4.0 में क्यूब्स (या किसी भी आंकड़े) के साथ आने के तरीके को कैसे इस्तेमाल किया जाए, तो मुझे बहुत बाध्य होना होगा


यह सबसे सरल कोड स्निपेट है जिसके साथ मैं आ सकता हूं। एक कोड का एक अनुकूलन मैं कुछ महीने पहले कुछ क्यूब्स प्रदर्शित करने के लिए बनाया था, बस आप की क्या जरूरत है, कोई मॉडल और न ही फैंसी कुछ भी।

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;

namespace HardwareInstancing
{
    public class Instancing
    {
        Texture2D texture;
        Effect effect;

        VertexDeclaration instanceVertexDeclaration;

        VertexBuffer instanceBuffer;
        VertexBuffer geometryBuffer;
        IndexBuffer  indexBuffer;

        VertexBufferBinding[] bindings;
        InstanceInfo[] instances;

        struct InstanceInfo
        {
            public Vector4 World;
            public Vector2 AtlasCoordinate;
        };

        Int32 instanceCount = 10000;

        public void Initialize(GraphicsDevice device)
        {
            GenerateInstanceVertexDeclaration();
            GenerateGeometry(device);
            GenerateInstanceInformation(device, instanceCount);

            bindings = new VertexBufferBinding[2];
            bindings[0] = new VertexBufferBinding(geometryBuffer);
            bindings[1] = new VertexBufferBinding(instanceBuffer, 0, 1);
        }

        public void Load(ContentManager Content)
        {
            effect = Content.Load<Effect>("InstancingShader");
            texture = Content.Load<Texture2D>("default_256");
        }

        private void GenerateInstanceVertexDeclaration()
        {
            VertexElement[] instanceStreamElements = new VertexElement[2];

            instanceStreamElements[0] = 
                    new VertexElement(0, VertexElementFormat.Vector4, 
                        VertexElementUsage.Position, 1);

            instanceStreamElements[1] = 
                new VertexElement(sizeof(float) * 4, VertexElementFormat.Vector2,
                    VertexElementUsage.TextureCoordinate, 1);

            instanceVertexDeclaration = new VertexDeclaration(instanceStreamElements);
        }

        //This creates a cube!
        public void GenerateGeometry(GraphicsDevice device)
        {
            VertexPositionTexture[] vertices = new VertexPositionTexture[24];

            #region filling vertices
            vertices[0].Position = new Vector3(-1, 1, -1);
            vertices[0].TextureCoordinate = new Vector2(0, 0);
            vertices[1].Position = new Vector3(1, 1, -1);
            vertices[1].TextureCoordinate = new Vector2(1, 0);
            vertices[2].Position = new Vector3(-1, 1, 1);
            vertices[2].TextureCoordinate = new Vector2(0, 1);
            vertices[3].Position = new Vector3(1, 1, 1);
            vertices[3].TextureCoordinate = new Vector2(1, 1);

            vertices[4].Position = new Vector3(-1, -1, 1);
            vertices[4].TextureCoordinate = new Vector2(0, 0);
            vertices[5].Position = new Vector3(1, -1, 1);
            vertices[5].TextureCoordinate = new Vector2(1, 0);
            vertices[6].Position = new Vector3(-1, -1, -1);
            vertices[6].TextureCoordinate = new Vector2(0, 1);
            vertices[7].Position = new Vector3(1, -1, -1);
            vertices[7].TextureCoordinate = new Vector2(1, 1);

            vertices[8].Position = new Vector3(-1, 1, -1);
            vertices[8].TextureCoordinate = new Vector2(0, 0);
            vertices[9].Position = new Vector3(-1, 1, 1);
            vertices[9].TextureCoordinate = new Vector2(1, 0);
            vertices[10].Position = new Vector3(-1, -1, -1);
            vertices[10].TextureCoordinate = new Vector2(0, 1);
            vertices[11].Position = new Vector3(-1, -1, 1);
            vertices[11].TextureCoordinate = new Vector2(1, 1);

            vertices[12].Position = new Vector3(-1, 1, 1);
            vertices[12].TextureCoordinate = new Vector2(0, 0);
            vertices[13].Position = new Vector3(1, 1, 1);
            vertices[13].TextureCoordinate = new Vector2(1, 0);
            vertices[14].Position = new Vector3(-1, -1, 1);
            vertices[14].TextureCoordinate = new Vector2(0, 1);
            vertices[15].Position = new Vector3(1, -1, 1);
            vertices[15].TextureCoordinate = new Vector2(1, 1);

            vertices[16].Position = new Vector3(1, 1, 1);
            vertices[16].TextureCoordinate = new Vector2(0, 0);
            vertices[17].Position = new Vector3(1, 1, -1);
            vertices[17].TextureCoordinate = new Vector2(1, 0);
            vertices[18].Position = new Vector3(1, -1, 1);
            vertices[18].TextureCoordinate = new Vector2(0, 1);
            vertices[19].Position = new Vector3(1, -1, -1);
            vertices[19].TextureCoordinate = new Vector2(1, 1);

            vertices[20].Position = new Vector3(1, 1, -1);
            vertices[20].TextureCoordinate = new Vector2(0, 0);
            vertices[21].Position = new Vector3(-1, 1, -1);
            vertices[21].TextureCoordinate = new Vector2(1, 0);
            vertices[22].Position = new Vector3(1, -1, -1);
            vertices[22].TextureCoordinate = new Vector2(0, 1);
            vertices[23].Position = new Vector3(-1, -1, -1);
            vertices[23].TextureCoordinate = new Vector2(1, 1);
            #endregion

            geometryBuffer = new VertexBuffer(device, VertexPositionTexture.VertexDeclaration,
                                              24, BufferUsage.WriteOnly);
            geometryBuffer.SetData(vertices);

            #region filling indices

            int[] indices = new int [36];
            indices[0] = 0; indices[1] = 1; indices[2] = 2;
            indices[3] = 1; indices[4] = 3; indices[5] = 2;

            indices[6] = 4; indices[7] = 5; indices[8] = 6;
            indices[9] = 5; indices[10] = 7; indices[11] = 6;

            indices[12] = 8; indices[13] = 9; indices[14] = 10;
            indices[15] = 9; indices[16] = 11; indices[17] = 10;

            indices[18] = 12; indices[19] = 13; indices[20] = 14;
            indices[21] = 13; indices[22] = 15; indices[23] = 14;

            indices[24] = 16; indices[25] = 17; indices[26] = 18;
            indices[27] = 17; indices[28] = 19; indices[29] = 18;

            indices[30] = 20; indices[31] = 21; indices[32] = 22;
            indices[33] = 21; indices[34] = 23; indices[35] = 22;

            #endregion

            indexBuffer = new IndexBuffer(device, typeof(int), 36, BufferUsage.WriteOnly);
            indexBuffer.SetData(indices);
        }

        private void GenerateInstanceInformation(GraphicsDevice device, Int32 count)
        {
            instances = new InstanceInfo[count]; 
            Random rnd = new Random();

            for (int i = 0; i < count; i++)
            {
                //random position example
                instances[i].World = new Vector4(-rnd.Next(400), 
                                                 -rnd.Next(400), 
                                                 -rnd.Next(400), 1);

                instances[i].AtlasCoordinate = new Vector2(rnd.Next(0, 2), rnd.Next(0, 2));
            }

            instanceBuffer = new VertexBuffer(device, instanceVertexDeclaration, 
                                              count, BufferUsage.WriteOnly);
            instanceBuffer.SetData(instances);
        }

        //view and projection should come from your camera
        public void Draw(ref Matrix view, ref Matrix projection, GraphicsDevice device)
        {
            device.Clear(Color.CornflowerBlue);

            effect.CurrentTechnique = effect.Techniques["Instancing"];
            effect.Parameters["WVP"].SetValue(view * projection);
            effect.Parameters["cubeTexture"].SetValue(texture);

            device.Indices = indexBuffer;

            effect.CurrentTechnique.Passes[0].Apply();

            device.SetVertexBuffers(bindings);
            device.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0, 24, 0, 12, instanceCount);
        }
    }
}

मैंने इस श्वेत के साथ इस बनावट का उपयोग किया है:

float4x4 WVP;
texture cubeTexture;

sampler TextureSampler = sampler_state
{
    texture = <cubeTexture>;
    mipfilter = LINEAR;
    minfilter = LINEAR;
    magfilter = LINEAR;
};

struct InstancingVSinput
{
    float4 Position : POSITION0;
    float2 TexCoord : TEXCOORD0;
};

struct InstancingVSoutput
{
    float4 Position : POSITION0;
    float2 TexCoord : TEXCOORD0;
};

InstancingVSoutput InstancingVS(InstancingVSinput input, float4 instanceTransform : POSITION1, 
                                float2 atlasCoord : TEXCOORD1)
{
    InstancingVSoutput output;

    float4 pos = input.Position + instanceTransform;
    pos = mul(pos, WVP);

    output.Position = pos;
    output.TexCoord = float2((input.TexCoord.x / 2.0f) + (1.0f / 2.0f * atlasCoord.x),
                             (input.TexCoord.y / 2.0f) + (1.0f / 2.0f * atlasCoord.y));
    return output;
}

float4 InstancingPS(InstancingVSoutput input) : COLOR0
{
    return tex2D(TextureSampler, input.TexCoord);
}

technique Instancing
{
    pass Pass0
    {
        VertexShader = compile vs_3_0 InstancingVS();
        PixelShader = compile ps_3_0 InstancingPS();
    }
}

जिसका नाम InstancingShader.fx होना चाहिए और आपके सामग्री फ़ोल्डर में रखा जाना चाहिए।

इसे अपने गेम 1 से उपयोग करना कॉलिंग के समान सरल है:

instancing = new Instancing();
instancing.Initialize(this.GraphicsDevice);
instancing.Load(Content);

और अपनी ड्रा विधि में:

instancing.Draw(ref camera.View, ref camera.Projection, GraphicsDevice);