Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write reusable glsl code?

My shaders often share much of the same functionality. For instance calculation of diffuse/specular lighting. I would like to write this one time and then reuse the code across different shaders.

Glsl has no knowledge of files, and no support for a c-like #include preprocessor directive.

I know glsl has support for compiling source from multiple cstrings, but how would you know which cstrings to include? Do you implement your own version of include? Or do you create some sort of metafile for each of your shaders?

like image 373
bobbaluba Avatar asked Nov 23 '12 13:11

bobbaluba


2 Answers

In the large projects shaders often assembled at the first run (or when graphic options are changed) so they will include all vendor specific functional and are optimized for user machine and settings. And not only shader but also some stages of render pipeline.
You can treat GLSL as HTML\CSS\JavaSript code that PHP script vomits in response to the request. And you can use same technics as tampleting, code injections(for example amount of texture lookup) in loops. And it's also good for graphic designers because they have simple control on shader source through parameterization - checkbook, input fields etc and it can produce unique shader for unique cases.

like image 80
JAre Avatar answered Oct 21 '22 10:10

JAre


I have a custom solution based on http://blackpixel.com/blog/494/xcode-using-includes-in-opengl-shaders/ [404 now]. Basically it said that you can use m4 tool to preprocess the files.

In the GLSL source files just include the desired fragment you want to reuse:

include(Utils.glsl)
include(Colors.glsl)

...

void main (void) {
    ...
}

In Xcode, add all glsl files to “Copy Bundle Resources”.

Add a “Run Script” phase with this shell script:

#!/bin/sh

cd ${BUILT_PRODUCTS_DIR}/${WRAPPER_NAME}
find . -name "*.fsh" | while read file; do
    echo Preprocess $file
    m4 "$file" > "$file.tmp"
    mv "$file.tmp" "$file"
done

exit 0

The script assumes your shaders have .fsh extension. It’s trivial to modify it to match your shader extensions.

Be warned: your shaders will be easily accessible to almost anyone. You may use it for development and convert them to strings before releasing them (not a real protection unless you encrypt it...).

Also, if there is no much sharing between shaders, you'll end up with a lot of unused code. I guess the shader compiler will take care of it but I'm not 100% sure if there is some performance penalty.

like image 27
djromero Avatar answered Oct 21 '22 10:10

djromero