Jump to content
  • Advertisement
Zototh

DX11 Instance Shader Problem

This topic is 483 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 am using slimDX and am having a problem with a shader. I have an instance Shader that works perfect but I needed one for drawing fonts manually. The idea is to create the plane and simple instance it with separate position color and texture coordinates for each char.  I know this post is terribly long but any help would be appreciated. I tried to provide everything needed but if you need more I will be glad to post it.

This is the shader. the only difference between it and the working one is the instance texture coordinates. I was able to render 4,000 spheres with 30,000 faces with the original and still maintain a 100+ framerate. I don't know if that is a lot but it looked like it to me.

cbuffer cbVSPerFrame:register(b0)
{
	row_major matrix world;
	row_major matrix viewProj;
};

Texture2D g_Tex;
SamplerState g_Sampler;

struct VSInstance
{
	float4 Pos : POSITION;
	float3 Normal : NORMAL;
	float2 Texcoord : TEXCOORD0;

	float4 model_matrix0 : TEXCOORD1;

	float4 model_matrix1 : TEXCOORD2;

	float4 model_matrix2 : TEXCOORD3;

	float4 model_matrix3 : TEXCOORD4;
  // this is the only addition
	float2 instanceCoord:TEXCOORD5;
	float4 Color:COLOR;
};
struct PSInput
{
	float4 Pos : SV_Position;
	float3 Normal : NORMAL;
	float4 Color:COLOR;
	float2 Texcoord : TEXCOORD0;
};


PSInput Instancing(VSInstance In)
{
	PSInput Out;
	// construct the model matrix

	row_major float4x4 modelMatrix =
	{
		In.model_matrix0,
		In.model_matrix1,
		In.model_matrix2,
		In.model_matrix3
	};
  
	Out.Normal = mul(In.Normal, (row_major float3x3)modelMatrix);
	float4 WorldPos = mul(In.Pos, modelMatrix);

	Out.Pos = mul(WorldPos, viewProj);
	Out.Texcoord = In.instanceCoord;
	Out.Color = In.Color;
	return Out;
}

float4 PS(PSInput In) : SV_Target
{
	return g_Tex.Sample(g_Sampler, In.Texcoord);
}

technique11 HWInstancing
{
	pass P0
	{
		SetGeometryShader(0);
		SetVertexShader(CompileShader(vs_4_0, Instancing()));
		SetPixelShader(CompileShader(ps_4_0, PS()));
	}
}

this is the input elements for the 2 buffers

        private static readonly InputElement[] TextInstance = {
            new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0, InputClassification.PerVertexData, 0),
            new InputElement("NORMAL", 0, Format.R32G32B32_Float, InputElement.AppendAligned, 0, InputClassification.PerVertexData, 0),
            new InputElement("TEXCOORD", 0, Format.R32G32_Float, InputElement.AppendAligned, 0, InputClassification.PerVertexData, 0),
            new InputElement("TEXCOORD", 1, Format.R32G32B32A32_Float, 0, 1, InputClassification.PerInstanceData, 1 ),
            new InputElement("TEXCOORD", 2, Format.R32G32B32A32_Float, InputElement.AppendAligned, 1, InputClassification.PerInstanceData, 1 ),
            new InputElement("TEXCOORD", 3, Format.R32G32B32A32_Float, InputElement.AppendAligned, 1, InputClassification.PerInstanceData, 1 ),
            new InputElement("TEXCOORD", 4, Format.R32G32B32A32_Float, InputElement.AppendAligned, 1, InputClassification.PerInstanceData, 1 ),
            new InputElement("TEXCOORD", 5, Format.R32G32_Float, InputElement.AppendAligned, 1, InputClassification.PerInstanceData, 1 ),
            new InputElement("COLOR", 0, Format.R32G32B32A32_Float, InputElement.AppendAligned, 1, InputClassification.PerInstanceData, 1 )
        };

the struct for holding instance data. 

    [StructLayout(LayoutKind.Sequential)]
    public struct InstancedText
    {
        public Matrix InstancePosition;
        public Vector2 InstanceCoords;
        public Color4 Color;
    };

instanceData buffer creation. Instance Positions is a simple List<InstancedText> above

            DataStream ds = new DataStream(InstancePositions.ToArray(), true, true);
            
            BufferDescription vbDesc = new BufferDescription();
            vbDesc.BindFlags = BindFlags.VertexBuffer;
            vbDesc.CpuAccessFlags = CpuAccessFlags.None;
            vbDesc.OptionFlags = ResourceOptionFlags.None;
            vbDesc.Usage = ResourceUsage.Default;
            vbDesc.SizeInBytes = InstancePositions.Count * Marshal.SizeOf<InstancedText>();
            vbDesc.StructureByteStride = Marshal.SizeOf<InstancedText>();
            ds.Position = 0;

            instanceData = new Buffer(renderer.Device, vbDesc);

 

and finally the render code.

the mesh is a model class that contains the plane's data. PositionNormalTexture is just a struct for those elements.

            renderer.Context.InputAssembler.InputLayout = new InputLayout(renderer.Device,
                effect.GetTechniqueByName("HWInstancing").GetPassByIndex(0).Description.Signature, TextInstance);
            renderer.Context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
            renderer.Context.InputAssembler.SetVertexBuffers(0, new 
               VertexBufferBinding(mesh.VertexBuffer, Marshal.SizeOf<PositionNormalTexture>(), 0));
            renderer.Context.InputAssembler.SetIndexBuffer(mesh.IndexBuffer, SlimDX.DXGI.Format.R32_UInt, 0);
            renderer.Context.InputAssembler.SetVertexBuffers(1, new VertexBufferBinding(instanceData,
                 Marshal.SizeOf<InstancedText>(), 0));

            effect.GetVariableByName("g_Tex").AsResource().SetResource(textures[fonts[name].Name]);

            EffectTechnique currentTechnique = effect.GetTechniqueByName("HWInstancing");
            for (int pass = 0; pass < currentTechnique.Description.PassCount; ++pass)
            {
                EffectPass Pass = currentTechnique.GetPassByIndex(pass);
                System.Diagnostics.Debug.Assert(Pass.IsValid, "Invalid EffectPass");
                Pass.Apply(renderer.Context);
                renderer.Context.DrawIndexedInstanced(mesh.IndexCount, InstancePositions.Count, 0, 0, 0);
            };

I have been over everything I can think of to find the problem but I can't seem to locate it.

my best guess is the instance data buffer is wrong somehow since VS graphics debugger shows no output from vertex shader stage

 but I just can't see where.

Edited by Zototh

Share this post


Link to post
Share on other sites
Advertisement

wow it just hit me what I missed.

instanceData = new Buffer(renderer.Device, vbDesc); <---- should be instanceData = new Buffer(renderer.Device, ds, vbDesc);

LOL what a dumb mistake and spent 2 days trying to find it.

edit: seems I forgot to do a scaling matrix also when I created the positions but the shader works perfect

Edited by Zototh

Share this post


Link to post
Share on other sites

  • 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!