Conditional in HLSL pass

Started by
2 comments, last by ET3D 14 years, 3 months ago
Is it possible to make a conditional check in a pass? I am trying to change CullMode based on a global set from the client side.If it is not possible should I just set it from the client with SetRenderState or should I make two different techniques like ShadowOneSided and ShadowTwoSided. The following code gives the error None identifier not defined. Any suggestions?

technique Shadow
{
	pass P0
	{
		ColorWriteEnable = RED;
		AlphaBlendEnable = true;
		SrcBlend = One;
        DestBlend = Zero;
		CullMode = (g_TwoSided)?(None):(CCW);
		vertexShader = compile vs_3_0 VertShadow(g_EntitySkinned);
		PixelShader  = compile ps_3_0 PixShadow();
	}
}



Advertisement
This isn't something I've tried before so I don't know if it works, but it seems to at least compile:
bool g_TwoSided;int CullType(){	return (g_TwoSided)?(0):(2);  // Can't use the "None" and "CCW" constants here}technique Shadow{	pass P0	{                ...               		CullMode = CullType();		                ...	}}



MJP's solution looks great, but I don't know if it works.

My suggestion is if the changes are small, go for a setrenderstate.

When the changes are significant go for #ifdefs. In my deferred renderer I have a single .fx file containing the light shader, which generates 6 shaders via #ifdefs, two for each light type.

What's good about #ifdefs is you can reuse the same system to decide which features must be enabled at runtime (and rebuild the shaders on the fly). The total amount of permutations is very high as #defines control features like linear color space, shadow mapping and lighting models supported. Of course the trick is to generate a few shaders, but in case a project didn't need all lighting models, I would just tell the fx compiler not to generate that code.

The cost of switching shaders is high in D3D9, but in D3D10 if the vertex layout is the same (and in theory it's the same) the operation looks a lot cheaper, so #ifdefs could be a good solution...
If you decide to use two techniques, one thing I discovered lately is that doing 'compile' within a technique always creates a shader, so if you compile the same shader in several techniques, you get duplicates. Better to compile before and assign to a variable.

As for the question itself, I'd say do whatever fits your code structure the most. If your code is built around techniques, then introducing another technique might be easier than introducing SetRenderTarget into the code. If, as undead's solution suggests, this isn't dynamic, but an option that's set once, and you can compile the shader with it, what he suggests sounds like a fine solution.

This topic is closed to new replies.

Advertisement