Движение камеры OpenGL — шейдер против примитивного рендеринга

#opengl #glsl #shader

#opengl #glsl #шейдер

Вопрос:

В моем приложении OpenGL я использую gluLookAt() для преобразования моей камеры. Затем у меня есть две разные функции рендеринга; одна использует примитивный рендеринг ( glBegin()/glEnd() ) для рендеринга треугольника.

 glBegin(GL_TRIANGLES);
    glVertex3f(0.25, -0.25, 0.5);
    glVertex3f(-0.25, -0.25, 0.5);
    glVertex3f(0.25, 0.25, 0.5);
glEnd();
  

Вторая функция рендеринга использует шейдер для отображения треугольника с использованием тех же координат и вызывается с помощью функции glDrawArrays(GL_TRIANGLES, 0, 3) . shader.vert показан ниже:

 #version 430 core

void main()
{
   const vec4 verts[3] = vec4[3](vec4(0.25, -0.25, 0.5, 1),
                         vec4(-0.25, -0.25, 0.5, 1),
                         vec4(0.25, 0.25, 0.5, 1));
   gl_Position = verts[gl_VertexID];
}
  

Теперь вот в чем моя проблема; если я перемещаю камеру, используя примитивный рендеринг треугольника, я вижу треугольник под разными углами, как и следовало ожидать. Когда я использую функцию рендеринга шейдеров, треугольник остается неподвижным. Очевидно, я чего-то не понимаю в мировых координатах и в том, как они связаны с объектами, визуализируемыми с помощью шейдеров. Может ли кто-нибудь указать мне правильное направление?

Ответ №1:

Если у вас нет активной шейдерной программы, вы используете так называемый «фиксированный конвейер». Фиксированный конвейер выполняет рендеринг на основе многочисленных атрибутов, которые вы устанавливаете с помощью вызовов OpenGL API. Например, вы указываете, какие преобразования вы хотите применить. Вы указываете атрибуты материала и освещения, которые управляют освещением вашей геометрии. Затем применение этих атрибутов обрабатывается OpenGL.

Как только вы используете свою собственную шейдерную программу, вы больше не используете фиксированный конвейер. Это означает, что большая часть того, что фиксированный конвейер ранее обрабатывал за вас, должна быть реализована в вашем шейдерном коде. Применение преобразований является частью этого. Чтобы применить вашу матрицу преобразования, вы должны передать ее в шейдер и применить в своем коде шейдера.

Матрица обычно объявляется как uniform переменная в вашем вершинном шейдере:

 uniform mat4 ModelViewProj;
  

а затем применяется к вашим вершинам:

 gl_Position = ModelViewProj * verts[gl_VertexID];
  

Затем в вашем коде вы будете использовать вызовы типа glGetUniformLocation() , glUniformMatrix4fv() и т.д. Для настройки матрицы. Подробное объяснение этого вопроса несколько выходит за рамки данного ответа, но вы должны быть в состоянии найти его во многих онлайн-руководствах по OpenGL.

Пока вы все еще используете устаревшую функциональность с профилем совместимости, на самом деле есть более простой способ. Вы должны знать, что это устарело и недоступно в профиле ядра OpenGL. Профиль совместимости делает доступными определенные атрибуты фиксированной функции для вашего кода шейдера, включая матрицы преобразования. Таким образом, вам не нужно ничего объявлять, и вы можете просто написать:

 gl_Position =  gl_ModelViewProjectionMatrix * verts[gl_VertexID];