I must have misunderstood something with shaders:
I thought that as you can attach multiple shaders to one program, you'd be able to simply attach more than one fragment shader, as an example: A crate texture rendered with a color modulation and refraction.
But apparently this is not the case, as you can have only one main function pe开发者_JAVA百科r program.
- How can I work around the main function limit and allow for any dynamic combination of multiple fragment shaders which are in the same program and called after each other?
You can have a set of entry points pre-defined. Suppose you have a limited number of effects (diffuse, specular, environment, etc). None of them is applied at most once, so you just need to create a managing shader like that one:
void apply_diffuse();
void apply_specular();
void apply_environment();
void main(){ ...
apply_diffuse();
apply_specular();
apply_environment();
...}
Then, when it's time to link the shader program you attach the corresponding implementations as separate GLSL objects. Some implementations may be dummies if you don't want the effect. This approach doesn't require source text parsing and has next to no performance penalty.
You can't. This is known as the combinatoric explosion of shaders. Either you use massive shaders- called the Übershader approach- or I believe you can achieve it by messing with the preprocessor and generating the shaders you need on the fly.
Newer versions of GLSL should support virtual functions, which allows you to modularly build them as you would in CPU code- HLSL5 does.
The problem is the terms you are using.
Let me make a similitude:
- An executable is composed by linked objects, objects are compiled from source.
- A shader program is composed by linked shader objects, shader objects are compiled from source.
As you can see, a shader program is the executable. It links multiple shader objects. Each shader object is compiled from a source. As for usual executable, there is only one main entry point, which is defined by only one shader object. Just like compiling with any compilation tool-chain.
The solution is the good balance between shader objects combinations and the number of shader programs. Of course it would be beautyful to have only one shader program for rendering, but that's pretending too much: try to factor the shader functionalities, then compiled separately those functionalities and link as needed.
And you must have a look on OpenGL Registry, I think you may find something interesting in the extension list.
You can have multiple programs in a shader, but not the other way around.
To make multiple combinations, the easiest way is to store each major chunk as a fragment with a named entry point, then include them from another program or combine them at runtime into a single program, calling them in the order you need. That can get messy though, when handling input and outputs.
You can use multiple passes, with different effects and programs in each pass. That has some additional overhead, but can be easier to set up.
精彩评论