Vertex Shader Question

Started by
4 comments, last by RobM 15 years, 8 months ago
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
Advertisement
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
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_0dcl_position0 v0dcl_position1 v1mov oPos.xz, v1.xyymov 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
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
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
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

This topic is closed to new replies.

Advertisement