У GLSL есть доступ к части функционала OpenGL. В этом уроке я покажу, как получить доступ к переменным цвета, установленным в OpenGL с помощью glColor.
В GLSL есть attribute-переменная, предназначенная для хранения текущего цвета. Кроме того GLSL предоставляет varying-переменные для получения цвета пикселным шейдером от вершинного шейдера.
attribute vec4 gl_Color;
varying vec4 gl_FrontColor; // перезаписываемо вершинным шейдером
varying vec4 gl_BackColor; // перезаписываемо вершинным шейдером
varying vec4 gl_Color; // читаемо пикселным шейдером
Смысл в следующем:
1. Приложение OpenGL посылает цвет, использую glColor.
2. Вершинный шейдер получает его в attribute-переменную gl_Color
3. Вершинный шейдер рассчитывает передние и задние цвета полигонов и записывает их в gl_FrontColor и gl_BackColor соответственно.
4. Пикселный шейдер получает интерполированные значения в varying-переменную glColor в зависимости от ориентации текущего примитива.
5. Пикселный шейдер устанавливает gl_FragColor, основываясь на значении gl_Color
Это исключение из правила, в котором varying-переменная должна быть обьявлена в обоих шейдерах с одинаковым именем. Смысл в том, что у вершинного шейдера есть 2 переменные цвета, gl_FrontColor и gl_BackColor, и они используются для автоматического рассчета gl_Color в зависимости от ориентации полигона. Заметьте, что конфликт между attribute-переменной gl_Color и varying-переменной gl_Color не возникает, так как первая видна только в вершинном шейдере, а вторая — в пикселном.
Итак, код вершинного шейдера, в котором вычисляется только цвет передней стороны полигона:
{
gl_FrontColor = gl_Color;
gl_Position = ftransform();
}
Пикселный шейдер тоже очень прост:
{
gl_FragColor = gl_Color;
}
Создайте два файла: color.vert и color.frag и занесите в них этот код соответственно.
Остальной код возьмите из [a=https://masandilov.ru/glsl/glsl-practic-helloworld:a]предыдущего урока, будем его модифицировать.
Файл main.cpp:
//
// Изменим обьявление переменных; одну уберём, одну добавим:
GLuint v,f,f2,p;
GLint loc;
float a = 0;
////////////////////////////////////////////////////////////
//
// Новая функция: создаёт куб
//
////////////////////////////////////////////////////////////
void drawCube() {
float hd = 1.0;
glColor3f(1,0,0);
glBegin(GL_QUADS);
glVertex3f(—hd,-hd,-hd);
glVertex3f(—hd,hd,-hd);
glVertex3f(hd,hd,-hd);
glVertex3f(hd,-hd,-hd);
glEnd();
glColor3f(1,1,0);
glBegin(GL_QUADS);
glVertex3f(—hd,-hd,-hd);
glVertex3f(hd,-hd,-hd);
glVertex3f(hd,-hd,hd);
glVertex3f(—hd,-hd,hd);
glEnd();
glColor3f(1,0,1);
glBegin(GL_QUADS);
glVertex3f(—hd,-hd,-hd);
glVertex3f(—hd,-hd,hd);
glVertex3f(—hd,hd,hd);
glVertex3f(—hd,hd,-hd);
glEnd();
glColor3f(0,1,0);
glBegin(GL_QUADS);
glVertex3f(—hd,-hd,hd);
glVertex3f(hd,-hd,hd);
glVertex3f(hd,hd,hd);
glVertex3f(—hd,hd,hd);
glEnd();
glColor3f(0,0,1);
glBegin(GL_QUADS);
glVertex3f(—hd,hd,-hd);
glVertex3f(—hd,hd,hd);
glVertex3f(hd,hd,hd);
glVertex3f(hd,hd,-hd);
glEnd();
glColor3f(0,1,1);
glBegin(GL_QUADS);
glVertex3f(hd,-hd,-hd);
glVertex3f(hd,hd,-hd);
glVertex3f(hd,hd,hd);
glVertex3f(hd,-hd,hd);
glEnd();
}
////////////////////////////////////////////////////////////
//
// Немного изменим функцию SetShaders():
// Изменим имена файлов с кодом шейдеров на новые:
vs = textFileRead(«minimal.vert»);
fs = textFileRead(«minimal.frag»);
// И в самый конец добавим:
loc = glGetUniformLocation(p,«time»);
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
//
// И наконец, изменим функцию RenderScene():
void RenderScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glLoadIdentity();
gluLookAt(0.0,5.0,5.0,
0.0,0.0,0.0,
0.0f,1.0f,0.0f);
glRotatef(a,0,1,0);
drawCube();;
a+=0.1;
SwapBuffers(g_hDC);
}
Вот и всё. Теперь, запустив программу, вы увидите вращающийся раскрашенный кубик.
Но если, например, уберёте код из пикселного шейдера — куб не будет окрашен и вы ничего не увидите.