Instance Shader Problem

Started by
1 comment, last by Zototh 6 years, 10 months ago

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.

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

This topic is closed to new replies.

Advertisement