Pygmy's picture

Problems adding "#pragma include" support to shaders

Since GLSL doesn't have an include-file option I'm trying to add this by using a "#pragma include" parser.
(I want this because I have some generic methods I'd like to implement only once but might use in many different shaders)

Parsing the shader files to get the included files works fine.
But when setting the ShaderSource with the multiple source files I always run into problems; since my main shader normally starts with "#version 330" and the #version-line always has to be the first line in the shader,
I can only add my main file as the first in the list[string] passed to Shadersource, and after that all the included files.
But then my main file can't use any functions implemented in those included files, since they'll essentially be concatenated *after* my main file so the compiler complains that it doesn't know the functions my main file is using.

The only way I can think of to get it to work is to read the main file, parse the include pragma, and then *replace* that pragma line with the file-contents of the file to be included (recursively applying this same method to all included files that might include other files themselves) - but that would mean the linenumbers in compilation-errors would not match the real linenumbers of the main file anymore.

Has anybody set up some sort of "include" functionality that works and keeps the linenumbers ? And if so - how ?


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
tksuoran's picture

I have something super simple like this:

public class Shader { public static Dictionary<string,string> Replacements = new Dictionary<string,string>(); ... }
...
Shader.Replacements.Add("UNIFORMS;", System.IO.File.ReadAllText("res/shaders330/uniforms.txt"));
Shader.Replacements.Add("SHADOWS;", ...

Edit: To deal with line numbers, I always format and print the full source code with line numbers AFTER replacements have been done, when compile or link errors occur. This way you can locate errors in replacements as well, although the outputted shaders are a bit longer.

kvark's picture

Pre-scriptum: I see that your question is about how to include files, while my answer is about a different approach. Please, discard my answer if you really want to put your hands in the GLSL source code.

Consider linking multiple GLSL objects together, having some of them to implement entry-point functions of the main object (the one containing 'main()'). I'm using it for at least 3 years, and despite some difficulties with drivers this approach proved to be very useful.

It works in a way similar to C programs with no headers : you have multiple code files, some of them declaring and using functions that are implemented by others. I'm keeping a huge library of shaders that I attach to programs that need some functionality (e.g. transforming from camera NDC into world space in deferred shading).

This will erase the need to parse GLSL texts by hand. More to that, when debugging you'll just need to know the paths to shader objects included (not the contents passed to GL), because you are not modifying any GLSL code manually.