Sign in to follow this  
RobMaddison

Vertex Shader Question

Recommended Posts

Hi I've been googling for a couple of hours and also looking through my HLSL books, but haven't found the answer to this question: How do I pass the X, Y and Z floats of a vertex into the vertex shader from 2 different streams? I've got a vertex buffer containing floats which are the heights of my heightmap (y) and I've got a vertex buffer containing floats which are the x and z positions of the terrain. I can't see anything that allows you to pass a float and 2 floats into the vertex shader. My decl looks like this: D3DVERTEXELEMENT9 declTerrainXYZ[] = { {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 1}, D3DDECL_END() }; I'm pretty sure this is wrong for a start as D3DDECLUSAGE_POSITION would signify a POSITION which is a 3 float vector - not what I want to pass in. Does anyone know how this is done? Or can point me in the direction of a tutorial? Thanks in advance

Share this post


Link to post
Share on other sites
I'm not sure if 2 positions would work like that. I seem to remember there being some other meaning already applied to a second position. You can however pass it in as anything else. Texcoords make good generic inputs.

In your shader you would list 2 inputs

float2 posxz : POSITION;
float posy : TEXCOORD0;

In your shader code you'd just combine them to make your full position vector.

float4 pos = float4(IN.posxz.x, IN.posy, IN.posxz.y, 1);

At this point you just start using the new "pos" instead of IN.position wherever you're transforming and using your position information.

If you want to test if 2 positions work, just change the semantic on posy to POSITION1

Share this post


Link to post
Share on other sites
Quote:
Original post by RobMaddison
How do I pass the X, Y and Z floats of a vertex into the vertex shader from 2 different streams?

I've got a vertex buffer containing floats which are the heights of my heightmap (y) and I've got a vertex buffer containing floats which are the x and z positions of the terrain. I can't see anything that allows you to pass a float and 2 floats into the vertex shader.

My decl looks like this:

D3DVERTEXELEMENT9 declTerrainXYZ[] =
{
{0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
{1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 1},
D3DDECL_END()
};

I'm pretty sure this is wrong for a start as D3DDECLUSAGE_POSITION would signify a POSITION which is a 3 float vector - not what I want to pass in.

Does anyone know how this is done? Or can point me in the direction of a tutorial?


Position is just a SEMANTIC in this case. That means it has no significance to the runtime or driver. POSITION does not imply three floats, I'm not sure where you've got that idea. The number of floats read in the stream for each input vector is determined by the D3DDECLTYPE member FLOAT1 is for 1 float, FLOAT2 is two floats.

Now about the semantic.. How does that work ?

Well you enter semantics in your vertex stream declaration, this declaration will tell you where the entity called POSITION 0 is coming from (from stream 0 at offset 0) and where the entity called POSITION 1 is coming from (from stream 1 at offset 1).

Now this semantic is matched to your declared inputs in your vertex shader :


vs_2_0
dcl_position0 v0
dcl_position1 v1

mov oPos.xz, v1.xyy
mov oPos.y, v0.x



Note that those are two different vector registers v0 and v1. The POSITION 0 entity has one float that will land in v0.x. The POSITION 1 entity has two floats those will land in v1.xy

So to reconstruct your xyz vector you simply recombine v0.x to be your y, v1.xy to be your x and z.

That's it.

And again, no, POSITION1 has no more meaning as a vertex shader INPUT than POSITION0..

LeGreg

Share this post


Link to post
Share on other sites
Thanks for the quick responses guys.

Ok, so I get the vertex shader part, but I'm still getting errors with my declaration. It is basically saying, if I want to use D3DDECLUSAGE_POSITION, I must supply a FLOAT3. I can't see any other D3DDECLUSAGE that uses FLOAT1 as a type.

Could you possibly suggest a suitable vertex declaration? I have two streams, in the first is just a list of floats and in the second, a list of two floats (although both appear identical, the second stream is just twice as big as the first).

Also, my CreateVertexBuffer call insists I supply an FVF (DWORD) for the 3rd parameter - how do I tell it that it's just one float and not something like D3DFVF_XYZ, etc.

Thanks again

Share this post


Link to post
Share on other sites
I'm now using this vertex declaration:


D3DVERTEXELEMENT9 declTerrainXYZ[] =
{
{0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
{1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
D3DDECL_END()
};



DirectX gives me the following debug error:

"Declaration can't map to fixed function FVF because position field is missing. Usage: D3DDECLUSAGE_POSITION, with usage index 0 is required for fixed function."

And my shader looks like this:


VertexToPixel SimpleVertexShader( float1 y : TEXCOORD, float2 xz : TEXCOORD)
{
...
}



I'm a bit confused as to why it's saying it needs a position field when I haven't specified one anywhere.

Any help, greatly appreciated

Share this post


Link to post
Share on other sites
Hi all

It appears that you can't actually do what I'm trying to do. My first vertex buffer creation (for the y values) specifies 0 (zero) for the FVF parameter (in CreateVertexBuffer) with a sizeof(float). This contains all the y value floats (e.g. y,y,y,y,y,y....

The second vertex buffer creation (for the xz values) specifies 0 (zero) for the FVF parameter (in CreateVertexBuffer) and a sizeof(float) * 2. This stream contains all the x and z value floats sequentially (e.g. x,z,x,z,x,z...)

I cannot use this type of declaration:


D3DVERTEXELEMENT9 declTerrainXYZ[] =
{
{0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
{1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 1},
D3DDECL_END()
};



The reason I can't is because the D3D runtime complains that FLOAT1 is being used for a POSITION usage type, both of these declarations (if using a usage of POSITION) require FLOAT3. If I use FLOAT3 for stream 0 and stream 1, won't it mean that for each vertex of my triangle, 3 floats from each stream will be passed to the vertex shader?

Is there something I can specify in the SetStreamSource call to say that although I want to pass in a FLOAT3 to the shader from this stream, I only want to pass one float (for stream 0) from my vertex stream in, say, the x float part of that FLOAT3 component?

Can anyone help? I'm tearing my hair out over this.

Thanks

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

Sign in to follow this