Shader about the fixed pipeline

Started by
6 comments, last by ET3D 15 years, 8 months ago
Hi, there is some code like this: ///////////////////////////////////////////// //pDevice is a IDirect3DDevice9 pointer //pEffect is a ID3DXEffect pointer //hTechnique is a vaild technique handle ///////////////////////////////////////////// pEffect->SetTechnique( hTechnique ); pDevice->SetFVF( D3DFVF_XYZRHW | D3DFVF_TEX1 ); pDevice->DrawPrimitive(...); The used technique only contains a pixel shader, which accept a float2 UV and returns a float4 COLOR. ///////////////////////////////////////////// technique GaussBlur5x5 { pass P0 { PixelShader = compile ps_2_0 GaussBlur5x5_func(); MinFilter[0] = Point; AddressU[0] = Clamp; AddressV[0] = Clamp; } } So which vertex shader does the pipeline use to process vertices? And if I want to replace the SetFVF() function, what should I do? Thanks!
Advertisement
If you don't specify a vertex shader in an effect technique, then the application of the technique does not change the vertex shader already set on the device. Usually, you will want to set all shaders for a technique, because the i/o structure between the shader stages generally varies depending on the usage of the technique.

As for replacing SetFVF, you should create a IDirect3D9VertexDeclaration9 object containing your vertex element descriptors, and use it by calling Device::SetVertexDeclaration. While SetFVF and this method are interchangeable at the most basic level, you will get an enormous amount of flexibility (arbitrary order and offsets of elements, ability to use multiple input streams) when you use vertex declarations instead of FVF codes.

Niko Suni

Thanks.If I had never set any vertexshader, then after use the technique, what will happen?
Evil things.

In all seriousness, you can expect undefined behavior if you use pixel shaders without vertex shaders.

In most cases I've seen, the default behavior is for the device to pass at least some vertex data through the pipeline. However, you cannot trust that this will happen - nor will you actually know what data you have available - so don't use pixel shaders without vertex shaders if you want to write robust code.

Mismatching vertex formats, missing and/or malfunctioning shaders and data structure mismatches can create all kinds of nice bugs, including access violations in both hardware and software; these, in turn, cause blue screens if you're lucky, and random behavior such as potential loss of data if you're unlucky. Professional programmers tend not to trust luck on these things.

Note that the omission of the vertex shader from the effect technique is perfectly legal, if you have set a vertex shader (output of which matches the technique's PS input) at least once in the host application.

Niko Suni

Oh, if I use a technique which just contains a pixel shader but still use
SetFVF() function, the default vertex shader will be implicitly used.
And if I use the same technique but do NOT use SetFVF(), undefined behavior may be happen, am I right?

Thanks again.
The problem here is that "default vertex shader" is likely non-existent or, if it does exist, you don't know exactly what it outputs.

A basic vertex shader is not very difficult to write, so I heavily recommend that you do just that [smile]

The default fixed-function T/L processing does very little other than multiplies the incoming position and normal by the world*view*projection matrix, optionally calculates basic diffuse and specular lighting, optionally transforms or generates texture coordinates, and passes the data to the rasterizer. These are very trivial operations to emulate in a vertex shader.

struct PS_IN //pixel shader input{float4 pos : POSITION; //rasterizer needs positionfloat4 diffuse : COLOR;float2 texcoord : TEXCOORD;//add or remove stuff as needed};struct VS_IN //vertex shader input; should match vertex format{float4 pos : POSITION;float3 normal : NORMAL;float2 texcoord : TEXCOORD;//add or remove stuff as needed};//constants; set these from the host program using ID3DXBaseEffect::Set* callsfloat4x4 wvp; // world*view*projection matrixfloat3 lightdir; // light directionPS_IN BasicVS (VS_IN input) //vertex shader{PS_IN ret; //allocate structure to send to pixel shaderret.pos = mul(input.pos, wvp); //transform position to projection spaceret.color = saturate (dot(normalize(mul(input.normal, (float3x3)wvp)), lightdir)); //calculate basic diffuse lightingret.texcoord = input.texcoord; //pass the incoming texcoord directly to ps//add or remove stuff as neededreturn ret;}//...pixel shader omitted...//...techniques omitted...


You must use either SetFVF or SetVertexDeclaration. The hardware does not attempt to (and cannot) guess what the data layout of your incoming vertices is.

If you are using the ID3DXMesh interfaces, they call SetFVF or SetVertexDeclaration automatically behind the scenes when you call DrawSubset.

[Edited by - Nik02 on August 15, 2008 4:02:10 AM]

Niko Suni

I understand. Thanks very much! And I have another question.

How to declare a vertex declaration for the combination like this:
[ D3DFVF_XYZRHW | D3DFVF_TEX2 ] but without [ D3DFVF_TEX1 ]

////////////////////////////////////////////////////////////
D3DVERTEXELEMENT9 FVF[] =
{
{ 0, 0, D3DDECLTYPE_FLOAT4,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_POSITION, 0 },//POS
{ 0, 16,D3DDECLTYPE_FLOAT2,D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_TEXCOORD, [0or1]? },
D3DDECL_END()
};
////////////////////////////////////////////////////////////

Note: I do not use D3DDECLUSAGE_POSITION[T] because I want to use shader to do the conversion myself.
Quote:Original post by wswqwps
Oh, if I use a technique which just contains a pixel shader but still use
SetFVF() function, the default vertex shader will be implicitly used.
And if I use the same technique but do NOT use SetFVF(), undefined behavior may be happen, am I right?

Your usage looks fine to me, but I think it'd be safer and clearer to use "FVF = ..." within the technique, instead of setting it in the code.

This topic is closed to new replies.

Advertisement