#include с пользовательским вводом-выводом для GLSL / C? - PullRequest
0 голосов
/ 10 мая 2018

У меня два вопроса, два очень важных:

  1. Существует ли препроцессор C, который сможет использовать любую пользовательскую функцию для определения местоположения файла, вызванного #include?Потому что, скажем, мои коды хранятся в ZIP-файле или где-то еще, и я полагаюсь на PhysFS, чтобы получить к ним доступ, а не разархивировать их.Существует ли препроцессор C с открытым исходным кодом, который может с этим работать, вместо того, чтобы ограничиваться обычным fopen?
  2. Можно ли использовать собственный или стандартный препроцессор C в коде GLSL?Я знаю, что в GLSL уже есть препроцессор, но в нем отсутствует функция #include, и я хочу исправить это.
  3. Можно ли объединить два вышеупомянутых варианта, чтобы получить программу или видеоигру, где GLSLисходные коды хранятся в файле ZIP или PK3 (поэтому доступ к нему осуществляется с помощью PhysFS или любой другой вещи ввода-вывода) , а специальный / модифицированный препроцессор C используется для обработки #include и получения включенных источников?

Я спрашиваю об этом, потому что у меня нет желания писать свой собственный препроцессор C для GLSL, кроме случаев, когда это абсолютно необходимо, и предпочел бы использовать существующий для реализации #include с пользовательским вводом-выводом.

Практически единственная причина, по которой мне нужен штуковина препроцессора C, заключается в том, что я хочу #include, и я хочу это с моим пользовательским вводом-выводом.

Примеры функций препроцессора, которые я хотел бы реализовать:

  1. С добавлением всего предварительно обработанного исходного кода к #version 450 или #version 310 es, а также #extension GL_ARB_separate_shader_objects : enable
  2. Включая константы времени выполнения.Некоторые говорят, что униформа может быть лучше для этой цели, но предопределенные неоднозначные константы, вероятно, тоже подойдут.
  3. Возможность повторного использования функций.

Один примерпредполагаемое использование:

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 вместо использования нескольких двоичных файлов.

1 Ответ

0 голосов
/ 13 мая 2018

Директива #include - это не что иное, как вставка кода в точку, поэтому достаточно простого сопоставления с "#include <path>" или "#include "path"".

Если необходимы более сложные включения,Определения также должны обрабатываться, чтобы облегчить охрану (как у вас в коде), но это не обязательно в начале.

Все это говорит, я считаю плохой практикой поддерживать эти дополнения:

  1. Включить не следует использовать для получения доступа к коду в других модулях, поскольку функции уже могут вызываться в других модулях того же типа шейдера.Вы в основном принудительно используете «полулинейность», которая, скорее всего, приведет только к вздутию, а не к повышению скорости.
  2. Следует также избегать определений использования констант, поскольку они не являются безопасными по типу и контексту.Использование const float в этом случае было бы намного безопаснее.

В общем, тот факт, что они не существуют, в основном потому, что они не нужны с тщательно разработанным GLSL для начала.Поэтому, прежде чем явно добавлять «функции» к чему-то, что работает, нужно спросить, нужны ли эти дополнения или могут быть достигнуты другими способами.

...