3
\$\begingroup\$

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.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ most people would combine them all into 1 shader \$\endgroup\$ Nov 18, 2013 at 10:03
  • \$\begingroup\$ @ratchetfreak That is what I'm currently doing, but it is not very flexible doing it that way. I would like to be able to choose at runtime if what I'm drawing has a texture, light or both without constantly switching shader or having to pass a lot of information telling it what it has in the cbuffer. \$\endgroup\$
    – Caesar
    Nov 18, 2013 at 10:24
  • \$\begingroup\$ @Caesar did you try the approach I suggested and if yes why did/nt it work ? \$\endgroup\$
    – concept3d
    Nov 18, 2013 at 14:06
  • \$\begingroup\$ @concept3d Thank you for the answer, it is very interesting but I currently can't test it out. I will test it out later today though. \$\endgroup\$
    – Caesar
    Nov 18, 2013 at 14:08

1 Answer 1

3
\$\begingroup\$

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.

\$\endgroup\$
7
  • \$\begingroup\$ Since both texturing and lighting are needed, won't the use of preprocessor directives require recompilation with each toggle of the flags? That seems sub-optimal. \$\endgroup\$ Nov 18, 2013 at 20:00
  • \$\begingroup\$ actually it's. but it's not suboptimal. Think of this as loading of new resources. sometimes it's needed and it's actually used in real engines. \$\endgroup\$
    – concept3d
    Nov 18, 2013 at 20:05
  • \$\begingroup\$ but anyway my answer was intended as a general solution and not only for his texture and lighting case. \$\endgroup\$
    – concept3d
    Nov 18, 2013 at 20:07
  • \$\begingroup\$ Yes, as far as treating the two paths as different resources is concerned, this is a solution. It's not a solution when the two paths are lighting and texturing, which are to be done every frame. Recompiling shaders on that frequent of a basis is superfluous and adding unnecessary overhead to each frame. \$\endgroup\$ Nov 18, 2013 at 20:40
  • 1
    \$\begingroup\$ @Caesar - concept3d isn't advocating recompiling shaders here. The idea is to pre-compile 3 different versions of the shader, each of which uses different pre-processor tokens: first for texture only, second for light only, third for texture with light, all three pre-compiled from the same source but using the pre-processor to determine which code is used in each. The only overhead is shader switching, but current APIs don't provide any other reasonable means of doing this. \$\endgroup\$ Nov 19, 2013 at 0:45

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .