У меня два вопроса, два очень важных:
- Существует ли препроцессор C, который сможет использовать любую пользовательскую функцию для определения местоположения файла, вызванного
#include
?Потому что, скажем, мои коды хранятся в ZIP-файле или где-то еще, и я полагаюсь на PhysFS, чтобы получить к ним доступ, а не разархивировать их.Существует ли препроцессор C с открытым исходным кодом, который может с этим работать, вместо того, чтобы ограничиваться обычным fopen? - Можно ли использовать собственный или стандартный препроцессор C в коде GLSL?Я знаю, что в GLSL уже есть препроцессор, но в нем отсутствует функция
#include
, и я хочу исправить это. - Можно ли объединить два вышеупомянутых варианта, чтобы получить программу или видеоигру, где GLSLисходные коды хранятся в файле ZIP или PK3 (поэтому доступ к нему осуществляется с помощью PhysFS или любой другой вещи ввода-вывода) , а специальный / модифицированный препроцессор C используется для обработки #include и получения включенных источников?
Я спрашиваю об этом, потому что у меня нет желания писать свой собственный препроцессор C для GLSL, кроме случаев, когда это абсолютно необходимо, и предпочел бы использовать существующий для реализации #include с пользовательским вводом-выводом.
Практически единственная причина, по которой мне нужен штуковина препроцессора C, заключается в том, что я хочу #include
, и я хочу это с моим пользовательским вводом-выводом.
Примеры функций препроцессора, которые я хотел бы реализовать:
- С добавлением всего предварительно обработанного исходного кода к
#version 450
или #version 310 es
, а также #extension GL_ARB_separate_shader_objects : enable
- Включая константы времени выполнения.Некоторые говорят, что униформа может быть лучше для этой цели, но предопределенные неоднозначные константы, вероятно, тоже подойдут.
- Возможность повторного использования функций.
Один примерпредполагаемое использование:
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));
}
Это, очевидно,тривиальный пример, но главная цель состоит в том, чтобы увеличить возможность повторного использования кода и уменьшить количество ненужного кода, который должны содержать необработанные шейдеры.
Мое окончательное намерение - интегрировать GlSlang и SPIR-V Cross для компиляции Vulkan-совместимого GLSL (расширен с помощью специального препроцессора C) для SPIR-V и, при необходимости, обратно к GLSL (или HLSL) если используемый бэкэнд не Vulkan.Поскольку я не знаю, как соединить несколько двоичных файлов SPIR-V перед декомпиляцией обратно в GLSL, я думаю, что важно иметь только один двоичный файл на шейдерный модуль, поэтому необходимо использовать #include
вместо использования нескольких двоичных файлов.