Zototh

DX11 Instance Shader Problem

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

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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Forum Statistics

    • Total Topics
      628275
    • Total Posts
      2981740
  • Similar Content

    • By Eck
      I just saw their courses were knocked down to $10 each and figured I'd share the info here. They have stuff for Unity, Unreal, drawing, business, etc. I haven't used their stuff before, but the previews I looked at seemed pretty good and there is a user review system as well.
      https://www.udemy.com/courses/search/?q=Unity&src=ukw
      - Eck
       
    • By Rannion
      Hi,
      I'm trying to fill a win64 Console with ASCII char.
      At the moment I have 2 solutions: one using std::cout for each line, let's say 30 lines at once using std::endl at the end of each one.
      The second solution is using FillConsoleOutputCharacter. This method seems a lot more robust and with less flickering. But I'm guessing, internally it's using a different table than the one used by std::cout. I'm trying to fill the console with the unsigned char 0xB0 which is a sort of grey square when I use std::cout but when using FillConsoleOutputCharacter it is outputted as the UTF8 char '°'.
      I tried using SetConsoleOutputCP before but could not find a proper way to force it to only use the non-extended ASCII code page...
      Has anyone a hint on this one?
      Cheers!
    • By mellinoe
      Hi all,
      First time poster here, although I've been reading posts here for quite a while. This place has been invaluable for learning graphics programming -- thanks for a great resource!
      Right now, I'm working on a graphics abstraction layer for .NET which supports D3D11, Vulkan, and OpenGL at the moment. I have implemented most of my planned features already, and things are working well. Some remaining features that I am planning are Compute Shaders, and some flavor of read-write shader resources. At the moment, my shaders can just get simple read-only access to a uniform (or constant) buffer, a texture, or a sampler. Unfortunately, I'm having a tough time grasping the distinctions between all of the different kinds of read-write resources that are available. In D3D alone, there seem to be 5 or 6 different kinds of resources with similar but different characteristics. On top of that, I get the impression that some of them are more or less "obsoleted" by the newer kinds, and don't have much of a place in modern code. There seem to be a few pivots:
      The data source/destination (buffer or texture) Read-write or read-only Structured or unstructured (?) Ordered vs unordered (?) These are just my observations based on a lot of MSDN and OpenGL doc reading. For my library, I'm not interested in exposing every possibility to the user -- just trying to find a good "middle-ground" that can be represented cleanly across API's which is good enough for common scenarios.
      Can anyone give a sort of "overview" of the different options, and perhaps compare/contrast the concepts between Direct3D, OpenGL, and Vulkan? I'd also be very interested in hearing how other folks have abstracted these concepts in their libraries.
    • By sidbhati32
      I am working on a game in which we control a rectangular box at the bottom of the screen. Three sphere which has alphabets in it fall down. When the game starts, a word is generated from the predefined list of words(which I'll give) and we are supposed to touch the correct sphere having the alphabet based on that word. The question is how to detect if I have touched the correct sphere. 
      secondly, if I have touched a correct sphere before and there is no recurrence of that alphabet in that word then during the second wave the game should not proceed if I touch the same alphabet again.
      Looking forward to your answers, i have to submit this project in a couple of days. please help! (Working on Unity 3D)
      Thanks
    • By zizulot
      Probably one of the hardest Space Shooters you ever play, try your luck
      MOve with arrow keys, SPACE to shot, you can get hit only 3 times.
      Good Luck
      Available HTML5 , Windows,MacOS and Linux ,
      Get it on: https://gamejolt.com/games/spacerecker/297429
  • Popular Now