Vertex Shader and Vertex declaration question

Started by
7 comments, last by Halsafar 18 years, 10 months ago
So far my Vertex Shader learning curve has been TERRIBLE. It seems every step through learning it I end up having many questions go unanswered and thus find myself researching the research which is a terrible way to learn one thing... With that said I have come to a point where I create the shader using CreateVertexShader. It seems this function requires a parameter of a DWORD array which resembles the VertexDeclarations. Can anyone walk me through this declaration and give me some insight on what it all means:

 DWORD dwVertexDecl[] =
  {
  	D3DVSD_STREAM( 0 ),
  	D3DVSD_REG(D3DVSDE_POSITION,  D3DVSDT_FLOAT3),
  	D3DVSD_REG(D3DVSDE_BLENDWEIGHT, D3DVSDT_FLOAT2), //blending weight
  	D3DVSD_REG(D3DVSDE_BLENDINDICES, D3DVSDT_FLOAT2), //matrices
  	D3DVSD_REG(D3DVSDE_NORMAL,    D3DVSDT_FLOAT3),
  	D3DVSD_REG(D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT2),
  	D3DVSD_END()
  };

I've made vertex declarations before and none of them looked like this, what is this stuff... Now I've used vertex declarations to render instead of the SetFVF, but this same tutorial where the snippet comes from has a FVF declared like this:

  static const int MAX_MATRIX_INDEX=2;
  typedef struct
  {
  	D3DXVECTOR3 p;
  	float		fWeights[MAX_MATRIX_INDEX];	//Weights
  	float		matrixBoneIndicies[MAX_MATRIX_INDEX];	//Weights
  	D3DXVECTOR3 n;
  	D3DXVECTOR2 uv;
  } D3DBlendVertex_t;
  #define D3DFVF_BLENDVERTEX (D3DFVF_XYZ | D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE2(2) |  D3DFVF_TEXCOORDSIZE2(1)
  |D3DFVF_NORMAL | D3DFVF_TEXCOORDSIZE2(0) )


Why TEX3? what are these TEXCOORDSIZE macros' doing, why are there two of them declared. This FVF is actually set before rendering. I've researched mostly all this on MSDN and came up with only basic information like a one sentence explanation, return values, etc. Thanks for any help, Halsafar
Advertisement
The TEX3 means there are three different sets of texture coordinates with each vertex. There is also the possibility of TEX2 etc. depending on how many you want. I'm not sure I can be any clearer than that.

The TEXCOORDSIZE macros tell D3D how many elements each set of texture coordinates has. For example, you might have 1D, 2D, or 3D texture coordinates. The actual syntax is a little backwards in my opinion, but it works like this:

D3DFVF_TEXCOORDSIZEn(texCoordSet)

So:

D3DFVF_TEXCOORDSIZE2(0)

The first (remembering zero-based index) set of texture coordinates have two components, i.e. standard UV coordinates.

Does that clear things up a bit?

-Mezz
That first vertex declaration is the DX8 way of making a shader. In DX8 a shader needed one of these declarations and was tied to that specific vertex format.

In DX9 you can use an FVF or vertex declaration, and as long as it provides the elements the shader wants, it's fine.

The prototype for making a shader in DX9 shouldn't be taking one of those vertex declarations
Clears up the FVF part a little bit.
So by declaring TEX3 that vertex struct can have 3 sets of texture coords... Alright thats easy.

D3DFVF_TEXCOORDSIZE2(0) is the standard tu,tv
So what would D3DFVF_TEXCOORDSIZE2(1) be, 3 coords?
How can you have 3D texture coordinates? I didn't think it was possible...


I'd still like to hear whats up with the Vertex declaration above.
texcoordsize2(1) would mean UV set 1 (the second set of uvs) is 2d. texcoordsize2 is pretty useless as it's the default anyway.

1D coords are good for nx1 textures. 2D coords are for standard nxn textures. 3D coords are used for volume textures. 1D, 2D, 3D, and 4D texture coords can be used to pass in any arbitrary data to a shader as well. In DX8 you would use a 3D or 4D coordinate to hold tangent vectors for example. In DX9 there is a specific tangent usage enum.

Lets use a good example:

tex1 = struct vertex{float u,v};
tex2 = struct vertex{float u1,v1, u2,v2};
tex2|texcoordsize1(0) = struct vertex{float u1, u2,v2};
tex2|texcoordsize3(1) = struct vertex{float u1,v1, u2,v2,w2};
tex2|texcoordsize3(0)|texcoordsize1(1) = struct vertex{float u1,v1,w1, u2};

texn = number of sets of uvs;
texcoordsizex(y) = uv set y is x dimensional.

D3DVSD_STREAM( 0 ):
Direct3D Vertex Shader Declaration Stream 0 - Says the data is coming from stream 0

D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3):
Register 0 is of type float3, and holds a position value.

D3DVSD_REG(D3DVSDE_BLENDWEIGHT, D3DVSDT_FLOAT2):
Register 1 is of type float2, and holds blend weights.

D3DVSD_REG(D3DVSDE_BLENDINDICES, D3DVSDT_FLOAT2):
Register 2 is of type float3, and holds indices to blending matrices.

D3DVSD_REG(D3DVSDE_NORMAL, D3DVSDT_FLOAT3):
Register 3 is of type float3, and holds a normal

D3DVSD_REG(D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT2):
Register 4 is of type float2, and holds a texture coordinate set

D3DVSD_END():
End vertex shader declaration (much like a null terminator in a string)

Yes, I examined the HLSL first but figured I'd be best to start with the vs/ps learn.


I am still confused on the tex coord part, lets see if I have it.

D3DFVF_TEXCOORDSIZE2(0) for example sets the second set of texture coords to the regular uv coords.

D3DFVF_TEXCOORDSIZE3(1) sets the third set of textures coords to...

The sample that Namethatnobodyelsetook posted blew my mind, I can't make any sense of it...
Not quite, Halsafar...
Quote:
D3DFVF_TEXCOORDSIZE2(0) for example sets the second set of texture coords to the regular uv coords.


The two in the macro does not mean the second set. It's the zero in the brackets which tells you which set we are editing. In this case the first set (since an index of 0 would be the first position of an array).

D3DFVF_TEXCOORDSIZE2(0)

Think of this macro as a function like SetTexCoordSize2D(int indexPosition)
where you pass the index of the set you whish to modify to 2D. Then you can apply the same thinking to the other versions.

D3DFVF_TEXCOORDSIZE3(1) or SetTexCoordsSize3D(int indexPosition)

Now you are giving the macro a set index you wish to convert to 3D tex co-ords.

So in your original example:

#define D3DFVF_BLENDVERTEX (D3DFVF_XYZ | D3DFVF_TEX3 | D3DFVF_TEXCOORDSIZE2(2) | D3DFVF_TEXCOORDSIZE2(1) |D3DFVF_NORMAL | D3DFVF_TEXCOORDSIZE2(0) )

We can see that the first set (set index 0) is being set to 2D (D3DFVF_TEXCOORDSIZE2(0)), the second set (set index 1) is being set to 2D (D3DFVF_TEXCOORDSIZE2(1)), and the third set (set index 2) is being set to 2D as well (D3DFVF_TEXCOORDSIZE2(2)).

And this makes sense, since that vertex you defined only has UV texture coords, and you'll notice that you defined MAX_MATRIX_INDEX as 2... all 3 positions in that array you have defined as 2D through those macros.

Hope this is a little clearer.
---------------------------------------------------------------"The problem with computers is they do what you tell them.""Computer programmers know how to use their hardware."- Geek#
Wow that sure did clear it up a ton.
Thank you very much guys for turning the greek into english for me :)

Halsafar

This topic is closed to new replies.

Advertisement