Присоединение нескольких шейдеров одного типа в одной программе OpenGL? - PullRequest
19 голосов
/ 07 февраля 2012

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

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

Ответы [ 2 ]

27 голосов
/ 07 февраля 2012

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

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

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

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

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

vec3 ComputeLighting(vec3 position, vec3 eyeDir);

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

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

7 голосов
/ 07 февраля 2012

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

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

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

Вы можете объявить функцию в источнике шейдера и не определять ее, а во время компоновки вы можете предоставитьопределение из другого источника шейдеров (очень похоже на линковку c / 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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...