I have two questions, two very important ones:
- 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? - 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. - 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:
- Prepending the whole already-preprocessed source code with
#version 450
, or#version 310 es
, as well as#extension GL_ARB_separate_shader_objects : enable
- Including runtime constants. Some say that uniforms might be better for this purpose, but pre-defined ambigious constants are probably fine too.
- 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.