0

I have two questions, two very important ones:

  1. Is there a C preprocessor out there that will be able to to take any custom function for locating a file invokved by #include? Because, say, I have my codes stored in a ZIP file or something, and rely on PhysFS to access them instead of unzipping them. Is there an open-source C preprocessor out there that can work with that, instead of being restricted to normal fopen?
  2. Is it possible to use a custom or standard C preprocessor on GLSL code? I know that GLSL already has a preprocessor, but it lacks the #include feature, and I want to rectify that.
  3. Is it possible to combine the above two, to have a program or video game, where GLSL source codes are stored within a ZIP or PK3 file (therefore accessed with PhysFS, or any custom IO thing), and a custom/modded C preprocessor is used to process #include and procure the included sources?

I am asking this because I have no desire to write my own C preprocessor for GLSL unless it is absolutely necessary, and would prefer to make use of an existing one to implement #include with custom IO.

Pretty much the only reason I need the C preprocessor thingie is because I want #include, and I want it with my custom IO thing.

Examples of the preprocessor functionality I would like to implement:

  1. Prepending the whole already-preprocessed source code with #version 450, or #version 310 es, as well as #extension GL_ARB_separate_shader_objects : enable
    1. Including runtime constants. Some say that uniforms might be better for this purpose, but pre-defined ambigious constants are probably fine too.
    2. Reusability of functions.

One example of the intended usage:

ColourGradient.glsl

#ifndef COLOURGRADIENT_GLSL
#define COLOURGRADIENT_GLSL
vec4 gradient(vec4 cl1, vec4 cl2, float distance)
{
    return cl1+((cl2-cl1)*distance);
}
#endif // COLOURGRADIENT_GLSL

Gradient.frag

#include <colours/ColourGradient.glsl>
layout(location = 0) in vec2 TexCoords;
layout(location = 0) out vec4 FragColor;

uniform vec4 colourA;
uniform vec4 colourB;
uniform bool colourCentering;
#define MAX_DISTANCE 1.4142135623731 // the square root of 2, basically

void main()
{
    float dist = length(TexCoords) / MAX_DISTANCE;
    if(colourCentering) 
    {
        FragColor = gradient(colourA,colourB,(abs(dist -0.5) * 2.0));
    }
    else FragColor = gradient(colourA,colourB,(diff * dist));
}

This is obviously a trivial example, but the main purpose is to increase the reusability of code, and reduce the amount of unnecessary code the non-preprocessed shaders must contain.

My final intention is to integrate GlSlang and SPIR-V Cross to compile Vulkan-compatible GLSL (extended with a custom C preprocessor) to SPIR-V, and optionally back to GLSL (or HLSL) if the used backend isn't Vulkan. Since I don't know how to stitch together multiple SPIR-V binaries before decompiling back to GLSL, I think it's important to have only one binary per shader module, hence the necessity of #include instead of using multiple binaries.

1 Answers1

0

The #include directive is nothing more than pasting code into a spot so a simple matching against "#include <path>" or "#include "path"" should be enough.

If more complex inclusions are necessary, defines should also be handled to facilitate guards (like you have in your code) but these are not necessary at the start.

All that said, I consider it a bad practice to support these additions:

  1. Include should not be used to get access to code in other units, since functions can already be called in other units of the same shader type. You basically force "semi inlining" which will probably just lead to bloat instead of speed improvement.
  2. Defines for the use of constants should also be avoided since they are not type and context safe. Using const float in this instance would be much safer.

All in all, the fact these don't exist is mainly because these are not necessary with the carefully designed GLSL to begin with. So before blatantly adding "features" to something that works, one must ask whether these additions are necessary, or can be achieved by other means.

Daniël Sonck
  • 869
  • 7
  • 9