Tuesday, October 13, 2015

c++ - Multiple pixel shader passes


I currently have a pixel shader that calculates the texture and I have another that calculates the light. I want another shader that does both. What I would ideally like to do is instead of creating a third shader that does that, I would like to have my object run through the first shader, then run through the second and then combine the final colors. Is this possible in DirectX11?


If this is possible, is it also possible that I run through the same shader multiple times? For example, could I load a texture and then run my texture shader then load another texture and then run the same texture shader again. Also same with lights, where I load light information to the cbuffer, run light shader, load another light informationm ,run light shader and rinse and repeat until I have run all lights.



Answer



Use conditional shader compilation! Well, to explain what I mean:



You can write one shader, that calculate several things, and pass to it a preprocessor token. The shader will compile based on what tokens were passed. This is similar to preprocessor directive we used for a long time in C:


#ifdef WIN32
//do this
#else
//do that
#endif

The same could be done with any shading language,(unless you are using precompiled binary shaders).


vec3 CalculateTexture(){ ... }


vec3 CalcualteLight() { ... }

void main()
{
#ifdef CALC_TEXTURE
vec3 CalculateTexture();
#endif

#ifdef CALC_LIGHT
vec3 CalcualteLight();

#endif
//rest of shader code
}

You can pre-pend tokens to your shader source and compile conditionally for example if you pass #define CALC_TEXTURE this will only compile the part between the appropriate compiler preprocessor.


This is a common technique called Uber-shader, it will let you re-use your shader code by passing the appropriate tokens each time.


I am familiar with this technique in OpenGL, actually the reason glShaderSource takes array of strings is that you can pre-pend tokens to shader source.


void glShaderSource(GLuint shader,
GLsizei count,
const GLchar **string,

const GLint *length);

Am not sure how this is done in DirectX (as am not familiar with it's api), but because HLSL supports preprocessor directives I am sure it's straightforward to be done.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...