Re: [Algorithms] How do people use shader effect "compile" parameters?
Brought to you by:
vexxed72
|
From: Ian T. <ITh...@re...> - 2008-09-24 22:07:39
|
I've used static pipeline control structures to manage combinations of shaders.
struct ShaderConfig
{
bool bLighting;
bool bScattering;
bool bShadowing;
};
I then have modifier functions that mutate these configs.
ShaderConfig StdConfig_2_0 =
{
true,
false,
true,
};
ShaderConfig StdConfig_3_0 =
ShaderConfig NoShadows( ShaderConfig sc )
{
sc.bShadowing = false;
return sc;
}
technique t
{
pass p
{
VertexShader = compile vs_2_0 Standard_v( NoShadows( StdConfig_2_0 ) );
...
}
}
This allowed us to define standard settings for shader models (we supported 1.1, 2.0 (and variants), 3.0, and later 4.0).
We generated large technique files (1000s of techniques, duplicate shaders shared) due to our need/desire to toggle settings and have them compile down optimally.
This handles most things except for differences in interpolator usage. To manage that better, we sometimes 'compile'd a wrapper that would just store the parameters it needed from an uber function.
I would rarely pass in static variables and would just leave them to be globals.
________________________________________
From: Robin Green [mailto:rob...@gm...]
Sent: Wednesday, September 24, 2008 2:08 PM
To: Game Development Algorithms
Subject: [Algorithms] How do people use shader effect "compile" parameters?
I'm doing a little research into how people use shader effects with an
emphasis on understanding and reasoning about them from source. My
question to the group goes like this:
When defining a shader effect, a single translation unit of code is
used to generate both a fragment and a vertex shader. These functions
can share global variables and structures, and the place where the
arbitration happens is in the interaction between the function
signature and the "compile" declaration inside each pass, e.g.
float4 global_color = { 0.3f, 0.3f, 0.3f, 1.0f };
void MyVertexShader( in float4 pos : POSITION,
in float4 color) : POSITION { ... }
technique {
pass {
...
VertexProgram = compile vs_3_0 MyVertexShader(global_color * 2.0f);
}
}
In this example the function "MyVertexShader" is parameterized with an
expression, and the documentation for both Cg and HLSL state that
these parameters are arbitrary "constant expressions" - any expression
that can evaluate to an R-value of the correct type. These expressions
are free to read global variables, operate with any literal value, use
typedef user types, struct accessors, array indexes, conditional
operators :? and the full range of intrinsic functions in their
evaluation.
Yet almost all the examples I see in the SDKs or online hardly touch
this feature, maybe substituting in a different sampler, doing vector
normalization or a simple biasing expression.
Q: If I were to make a tool that enforced only simple use of these
expression parameters (no intrinsics, no structures, no typedefs, no
conditionals), what cool tricks would I be giving up? Is using these
arbitrary expressions a key technique for anyone?
Thanks in advance,
- Robin Green.
|