Подтвердить что ты не робот

Прикрепление нескольких шейдеров одного типа в одной программе OpenGL?

При чтении спецификаций OpenGL я заметил, что в нем упоминается, что вы можете включать несколько шейдеров одного и того же типа в одну программу (т.е. более одного GL_VERTEX_SHADER, связанного с glAttachShader). В частности, в OpenGL 4.2, §2.11.3, "Объекты программы": "Несколько объектов шейдера одного типа могут быть прикреплены к одному программному объекту...".

Здесь могут применяться программы и подпрограммы OpenGL, но это было определено до того, как они существовали (на самом деле это восходит к спецификации 2.1, §2.15.2), поэтому я ищу пример этой идеи до GL4. Когда я сделал несколько простых тестов, я обнаружил, что включение более чем одного void main() вызвало ошибки связывания. Кто-нибудь знает о практическом примере, где это используется?

4b9b3361

Ответ 1

Вы можете поместить общие функции в отдельный шейдер. Затем скомпилируйте его только один раз и ссылку в нескольких программах.

Это похоже на то, как вы компилируете свои файлы cpp только один раз, чтобы получить статическую или общую библиотеку. Затем вы связываете эту библиотеку с несколькими исполняемыми программами, тем самым сохраняя время компиляции.

Скажем, у вас есть сложная функция освещения:

vec3 ComputeLighting(vec3 position, vec3 eyeDir)
{
    // ...
    return vec3(...);
}

Затем для каждого из шейдеров, где вы хотите использовать эту функциональность, выполните следующее:

vec3 ComputeLighting(vec3 position, vec3 eyeDir);

void main()
{
    vec3 light = ComputeLighting(arg1, arg2);
    gl_FragColor = ...;
}

Затем вы компилируете отдельно общий шейдер и основной шейдер. Но делать компиляцию общих шейдеров только один раз.

Ответ 2

Я обнаружил, что включение более чем одного void main() вызвало ошибки связывания

Для каждого этапа шейдера должна быть только основная функция ввода.

практический пример, где это используется (pre-GL4)?

Вы можете объявить функцию в источнике шейдера и не определять ее, а при связывании времени вы можете предоставить определение из другого источника шейдера (очень похожее на привязку c/С++).

Пример:

generate_txcoord.glsl:

#version 330
precision highp float;

const vec2 madd = vec2(0.5, 0.5);

vec2 generate_txcoord(vec2 v)
{ 
  return v * madd + madd; 
}

vertex.glsl:

#version 330
precision highp float;

in vec2 vxpos;

out vec2 out_txcoord;

vec2 generate_txcoord(vec2 vxpos); // << declared, but not defined

void main()
{
  // generate 0..+1 domain txcoords and interpolate them
  out_txcoord = generate_txcoord(vxpos);

  // interpolate -1..+1 domain vxpos
  gl_Position = vec4(vxpos, 0.0, 1.0);
}