Jump to content
  • Advertisement
Sign in to follow this  
Mathy

[SlimDX] Instancing problems - It worked in XNA!

This topic is 3122 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm doing instancing in SlimDX now after I got it working all by myself in XNA Game Studio 3.1. I now understand how instancing works entirely, but after converting my working code from XNA to SlimDX, instancing no longer works as expected. My shader code (which worked in XNA) is pasted in here:
float4x4 View;
float4x4 Projection;

float3 LightDirection = normalize(float3(1, -1, 2));
float3 DiffuseLight = 0.5;
float3 AmbientLight = 0.1;

struct VertexShaderInput
{
    float4 position : POSITION0;
    float3 normal : NORMAL0;
    float4 color : COLOR0;
};


struct VertexShaderOutput
{
    float4 position : POSITION0;
    float4 color : COLOR0;
};


// Vertex shader helper function shared between the different instancing techniques.
VertexShaderOutput VertexShaderCommon(VertexShaderInput input, float4x4 instanceTransform)
{
    VertexShaderOutput output;

    // Apply the world and camera matrices to compute the output position.
    float4 worldPosition = mul(input.position, instanceTransform);
    float4 viewPosition = mul(worldPosition, View);
    
    output.position = mul(viewPosition, Projection);
    
    // Compute lighting, using a simple Lambert model.
    float3 worldNormal = mul(input.normal, instanceTransform);
    float diffuseAmount = max(-dot(worldNormal, LightDirection), 0);
    float3 lightingResult = saturate(diffuseAmount * DiffuseLight + AmbientLight);
    //output.color = float4(lightingResult, 1);
	output.color=1.0f;
    
    //output.textureCoordinate = input.textureCoordinate;


    return output;
}

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
    //return input.color;
	return 1.0f;
}

// On Windows shader 3.0 cards, we can use hardware instancing, reading
// the per-instance world transform directly from a secondary vertex stream.
VertexShaderOutput HardwareInstancingVertexShader(VertexShaderInput input,
                                                float4x4 instanceTransform : TEXCOORD1)
{
    return VertexShaderCommon(input, transpose(instanceTransform));
}

technique HardwareInstancing
{
    pass Pass1
    {
        VertexShader = compile vs_3_0 HardwareInstancingVertexShader();
        PixelShader = compile ps_3_0 PixelShaderFunction();
    }
}
Now, the shader compiles correctly and gets loaded as an effect just fine, so that can't be the problem. Below you see my vertex declaration.
        private static VertexElement[] VertexElements =
             {
                 new VertexElement(0, 0, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Position, 0),
                 new VertexElement(0, sizeof(float)*3, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Normal, 0),
                 new VertexElement(0, sizeof(float)*6, DeclarationType.Color, DeclarationMethod.Default, DeclarationUsage.Color, 0),
                 new VertexElement(1, 0, DeclarationType.Float4, DeclarationMethod.Default, DeclarationUsage.TextureCoordinate, 1),
                 new VertexElement(1, 16, DeclarationType.Float4, DeclarationMethod.Default, DeclarationUsage.TextureCoordinate, 2),
                 new VertexElement(1, 32, DeclarationType.Float4, DeclarationMethod.Default, DeclarationUsage.TextureCoordinate, 3),
                 new VertexElement(1, 48, DeclarationType.Float4, DeclarationMethod.Default, DeclarationUsage.TextureCoordinate, 4),
                 VertexElement.VertexDeclarationEnd
             };
Now, here's my vertex structure:
    [StructLayout(LayoutKind.Sequential)]
    public struct PositionNormalColored
    {
        public Vector3 position;
        public int color;
        public Vector3 normal;
        public static readonly VertexFormat format = VertexFormat.Diffuse | VertexFormat.Position | VertexFormat.Normal;

        public PositionNormalColored(Vector3 position, int color) {
            this.position = position;
            this.color = color;
            this.normal = Vector3.Zero;
        }

        public static int SizeInBytes = sizeof(float) * (6 + 1);
    }
And finally, here's the code I use to render the objects. I believe that is the part that is not working (since it is converted from XNA).
        public static void performInstancing(Device device, Matrix view, Matrix projection, VertexBuffer vertexBuffer, IndexBuffer indexBuffer, VertexDeclaration vertexDeclaration, Matrix[] instancePositions, short vertexCount, short indexCount)
        {
            if (instancePositions==null || instancePositions.Length == 0)
            {
                return;
            }

            effect.Technique = new EffectHandle("HardwareInstancing");
            effect.SetValue(new EffectHandle("View"), view);
            effect.SetValue(new EffectHandle("Projection"), projection);

            device.SetStreamSource(0, vertexBuffer, 0, Vertices.PositionNormalColored.SizeInBytes);
            device.SetStreamSourceFrequency(0, instancePositions.Length, StreamSource.IndexedData);

            device.VertexDeclaration = vertexDeclaration;
            device.Indices = indexBuffer;

            int instanceDataSize = sizeOfMatrix * instancePositions.Length;
            if ((instanceDataStream == null) || (instanceDataStream.Description.SizeInBytes < instanceDataSize))
            {
                if (instanceDataStream != null)
                {
                    instanceDataStream.Dispose();
                }
                instanceDataStream = new VertexBuffer(device, instanceDataSize, Usage.WriteOnly, VertexFormat.Texture0, Pool.Default);
            }
            DataStream dataStream = instanceDataStream.Lock(0, instanceDataSize, LockFlags.None);
            dataStream.WriteRange(instancePositions);
            instanceDataStream.Unlock();

            device.SetStreamSource(1, instanceDataStream, 0, sizeOfMatrix);
            device.SetStreamSourceFrequency(1, 1, StreamSource.InstanceData);

            int passes = effect.Begin(FX.None);
            for(int i=0;i<passes;i++)
            {

                effect.BeginPass(i);
                device.DrawIndexedPrimitives(PrimitiveType.TriangleList,
                                                     0, 0, vertexCount,
                                                     0, indexCount / 3);
                effect.EndPass();

            }
            effect.End();

            device.SetStreamSource(0, null, 0, 0);
            device.SetStreamSource(1, null, 0, 0);
        }
Can anyone tell me what I am perhaps doing wrong? I tried changing this line: instanceDataStream = new VertexBuffer(device, instanceDataSize, Usage.WriteOnly, VertexFormat.Texture0, Pool.Default); Into: instanceDataStream = new VertexBuffer(device, instanceDataSize, Usage.WriteOnly, VertexFormat.Texture0 | VertexFormat.Texture1 | VertexFormat.Texture2 | VertexFormat.Texture3, Pool.Default); But without hope.

Share this post


Link to post
Share on other sites
Advertisement
You shouldn't be using FVF codes if you're also using vertex declarations. Use VertexFormat.None to specify this.

Also, VertexFormat.Texture0 indicates that you have 0 texture coordinates in your declaration, which is obviously incorrect.

Share this post


Link to post
Share on other sites
Nevermind, I got it all working! It turned out to be some coordinates being weird.

Share this post


Link to post
Share on other sites
Quote:
Original post by Mike.Popoloski
Your vertex declaration doesn't match your vertex structure.


I fixed that, and now the lighting effects work too! Thanks! Instancing worked with weird structures anyway though ;) Rating for you.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!