Using uniforms with multiple fragment shaders

Started by pdid, January 10, 2017, 17:03:13

Previous topic - Next topic

pdid

In my game I use one shader for rendering entities and another for rendering terrain, but the use a lot of the same code so I have a third shader that has all these functions and then I link the common shader along with the other shader at when my game starts. The issue occurs when I use a uniform in the third shader. (the one without the main function) When I use a uniform in the third shader, I cannot find the pointer for the uniform. (glGetUniformLocation returns -1) The OpenGL specifications says that when you link multiple shaders of the same shader stage  (vertex, fragment, etc.) together the code is combined:

From OpenGL wiki on khronos.org:
Note: It is possible to attach multiple shader objects for the same shader stage to a program. This is perfectly legal. When linking them, all of the code will be combined. However, only one of those shader objects can have a mainââ,¬â€¹ function. Linking like this will work very much like linking multiple object files in a C/C++ program: one .cpp file can call code in another .cpp file if it has forward declarations of functions. So you can have "libraries" of functions that individual shaders can choose to use.

Because the code is combined It leads me to believe that what I am doing is legal, but I'm still getting the error. Does anyone know why I'm getting this error, or has had this same issue in the past? Thanks in advance to anyone who can help me out.

Kai

Remember that the GLSL linker will eliminate any uniforms which no output (varyings/out variables for vertex shaders or fragment outputs for fragment shaders) depends on. So you must use your uniforms for them to exist. That brings another problem: You have to forward-declare the uniforms everywhere you use them (to satisfy the compiler, not the linker), as you have to do with functions. But uniforms are just declarations, so you would essentially double-declare the uniforms everywhere.

pdid

I'd rather not specify every single uniform in the entity or terrain shader. What I'd like to do is specify all the methods, structs and uniforms I need for lighting in a separate shader and then reference them in the original shader. I've heard that it's possible to do this by affecting the source code, but this is something I'd prefer not to do. If anyone has a solution or any sort of advice that would be great.

Kai

A shader is a single compilation unit, which must have all referenced variables (in, out, uniforms), types and functions, at least declared, in source-code-form so that the compiler knows what code it needs to generate to read/access them.
So, everywhere you want to access a uniform, it must be declared in that source file as a uniform.

Your options are:
a) use the glShaderSource() overload of LWJGL that accepts multiple source strings: glShaderSource(int shader, CharSequence... strings). This way you can let OpenGL append your common shader source and the using shader source. You would declare the shader #version directive in the common shader source
b) use a custom source (pre-)processor to manually include the common shader source file into each using shader source file

I would really look into option a).

pdid

Thanks for all the help, I'll look into the first option.