- •Что такое OpenGl?
- •Первое знакомство с программой OpenGl
- •Синтаксис OpenGl
- •Конвейер визуализации OpenGl
- •Подготовка данных для отправки в OpenGl
- •Вершинные шейдеры
- •Мозаичные шейдеры
- •Наша первая программа: Подробное обсуждение Ввод main()
- •Запуск OpenGl
- •Распределение объектов буфера вершин
- •Инициализация вершинных и фрагментарных шейдеров
- •Наш первый рендеринг в OpenGl
- •Рисование в OpenGl
- •Включение и выключение команд в OpenGl
- •Шейдеры и OpenGl
- •Настраиваемый конвейер OpenGl
- •Обзор OpenGl Shading Language
- •Создание шейдера при помощи glsl Точка отправления
- •Задача переменных
- •Охват переменных
- •Инициализация переменных
- •Сложные типы
- •Получение доступа к элементам матриц и векторов
- •Структуры
- •Квалификаторы хранилищ
- •Заявления
- •Вычислительная инвариантность
- •Глобальные функции компиляции шейдеров
- •Блоки интерфейса
- •Унифицированные блоки
- •Указание унифицированных блоков в шейдере
- •Доступ к унифицированным блокам из приложения
- •Блоки In/Out
- •Компилирование шейдеров
- •Наша функция LoadShaders()
- •Подпрограммы шейдеров
- •Установка подпрограмм glsl
- •Раздельные объекты шейдеров
Блоки In/Out
Переменный шейдеров, которые вводятся в него и выводятся на следующую стадию, можно организовать в блоки интерфейса. Эти логические группы могут облегчить визуальную проверку совпадений интерфейса между стадиями, а также сделают привязку разных программ проще.
Например, вершинный шейдер выводит данные:
out Lighting {
vec3 normal;
vec2 bumpCoord;
};
Эти данные совпадают с данными ввода фрагментарного шейдера:
in Lighting {
vec3 normal;
vec2 bumpCoord;
};
Данные вывода вершинного шейдера, помеченные material и lighting, каждые сгруппированы в свой блок. Интерфейсы, встроенные в OpenGL Shading Language, также представлены в виде блоков, как например, gl_PerVertex, в котором есть встроенная переменная gl_Positions, помимо прочих. Полный список этих блоков находится в Appendix C
Компилирование шейдеров
Написание шейдеров для OpenGL схоже с использованием языка “С”, основанного на компиляции. Вы задаете компилятору анализировать ваше программу, проверить на ошибки, а потом перевести ее в код объектов. Далее, вы объединяете набор объектов вместе в фазе привязки, для создания выполняемой программы. Использование GLSL шейдеров в вашей программе - схожий процесс, за тем лишь исключением, что компилятор и компоновщик оба являются частью API OpenGL.
Диаграмма 2.1 показывает шаги по созданию объекта шейдера GLSL и привязки его к исполняемой программе шейдера.
[картинка]
Для каждой программы, которую вы хотите использовать в вашем приложении, вам понадобится следующая последовательность шагов:
Для каждого объекта:
Создать объект шейдера.
Компилировать код вашего шейдера в объект.
Проверить, успешно ли компилируется ваш шейдер.
Затем, для привязки нескольких объектов шейдера в программу, нужно:
Создать программу шейдера.
Прикрепить соответствующий объект шейдреа к программе шейдера.
Привязать программу шейдера.
Убедиться, что стадия привязки прошла успешно.
Использовать шейдер для обработки вершин или фрагментов.
Зачем создавать несоклько объектов шейдера? Точно так же, как можно повторно использовать функцию и другой программе, можно поступить и с программой GLSL. Общие процедуры, которые вы пишете, могут быть использованы в других шейдерах. Вместо того, чтобы писать несколько тяжелых программ шейдинга, использующих отрывки общего кода, вам понадобится лишь отослать шейдер к соответствующему объекту шейдера.
Для создания объекта шейдера запросите glCreateShader().
GLuint glCreateShader(GLenum type);
Allocates a shader object. type must be one of GL_VERTEX_SHADER,
GL_FRAGMENT_SHADER, GL_TESS_CONTROL_SHADER,
GL_TESS_EVALUATION_SHADER, or GL_GEOMETRY_SHADER. The
return value is either a nonzero integer or zero if an error occurred.
Когда вы закончите создание объекта шейдера, вам нужно будет ассоциировать исходный код шейдера с этим объектом, созданным glCreateShader(). Это делается вызовом glSHaderSource().
glShaderSource(GLuint shader, GLsizei count,
const GLchar **string, const GLint *length);
Associates the source of a shader with a shader object shader. string is an
array of count GLchar strings that compose the shader’s source. The
character strings in string may be optionally null-terminated. length can
be one of three values. If length is NULL, then it’s assumed that each
string provided in string is null-terminated. Otherwise, length has count
elements, each of which specifies the length of the corresponding entry
in string. If the value of an element in the array length is a positive
integer, the value represents the number of characters in the
corresponding string element. If the value is negative for particular
elements, then that entry in string is assumed to be null-terminated
Для компиляции кода объекта шейдера используйте glCompileshader().
void glCompileShader(GLuint shader);
Compiles the source code for shader. The results of the compilation can
be queried by calling glGetShaderiv() with an argument of
GL_COMPILE_STATUS.
По тому же принципу, что и компиляция программы на “С”, вам нужно убедиться, что компиляция пойдет успешно. Запрос к glGetShaderiv() с поправкой GL_COMPILE_STATUS возвращает статус фазы компиляции. Если приходит GL_TRUE, значит компиляция удалась, и объект можно привязать к программе. Если компиляция не удалась, вы можете определить, какая ошибка тому помешала, запросив лог компиляции. glGetSharedInfoLog() выдаст сообщения по использованию с записью ошибок компиляции. Текущий размер лога ошибок может быть запрошен вызовом glGetShaderiv() с поправкой GL_INFO_LOG_LENGTH.
"> void glGetShaderInfoLog(GLuint shader, GLsizei bufSize,
GLsizei *length, char *infoLog);
Returns the log associated with the last compilation of shader. The log is
returned as a null-terminated character string of length characters in the
buffer infoLog. The maximum return size of the log is specified in bufSize.
If length is NULL, infoLog’s length is not returned.
Когда вы создали и скомпилировали все необходимые объекты шейдеров, вам нужно будет привязать их для создания выполняемой программы шейдера. Это процесс схожий с созданием самих объектов ешйдера. Сначала вам нужно создать программу шейдера, к которой вы можете прикрепить объекты. Используя glCreateProgramm(), вы получите программу для дальнейшей с ней работы.
GLuint glCreateProgram(void);
Creates an empty shader program. The return value is either a n
integer, or zero if an error occurred.
Когда вы получите свою программу шейдера, вам нужно будет заполнить её необходимыми объектами шейдера, для создания исполняемой программы. Это сопровождается прикреплением объектов шейдера к программе посредством вызова glAttachShader()
void glAttachShader(GLuint program, GLuint shader);
Associates the shader object, shader, with the shader program, program. A
shader object can be attached to a shader program at any time, although
its functionality will only be available after a successful link of the shader
program. A shader object can be attached to multiple shader programs
simultaneously
Для контроля четности, вам нужно убрать объект шейдера из программы для модификации операций шейдера, отсоедините объект вызовом glDetachShader() с идетификатором объекта шейдра.
void glDetachShader(GLuint program, GLuint shader);
Removes the association of a shader object, shader, from the shader
program, program. If shader is detached from program and had been
previously marked for deletion (by calling glDeleteShader()), it is deleted
at that time.
После того, как все необходимые объекты шейдера были прикреплены к программе, вам привязать их к исполняемой программе. Это делается вызовом glLinkProgram().
void glLinkProgram(GLuint program);
Processes all shader objects attached to program to generate a completed
shader program. The result of the linking operation can be queried by
calling glGetProgramiv() with GL_LINK_STATUS. GL_TRUE is returned
for a successful link; GL_FALSE is returned otherwise.
Также как с объектами шейдеров, есть вероятность, что эта фаза не пройдет успешно из-за ошибок в привязанных объектах. Вы можете запросить результат операции привязки вызовом glGetProgramiv() с поправкой GET_LINK_STATUS. Если ответ будет в форме GL_TRUE, то операция прошла успешно, и вы можете определить шейдер для обработки вершин и фрагментов. Если привзяка не была успешной, придет ответ GL_FALSE. Вы можете определить причину ошибки запросом glGetProgramInfoLog()
void glGetProgramInfoLog(GLuint program, GLsizei bufSize,
GLsizei *length, char *infoLog);
Returns the log associated with the last compilation of program. The log
is returned as a null-terminated character string of length characters in
the buffer infoLog. The maximum return size of the log is specified in
bufSize. If length is NULL, infoLog’s length is not returned.
После успешной привязки программы, вы можете запустить вершинный или фрагментарный шейдер вызовом glUseProgram() с дескриптором программы.
void glUseProgram(GLuint program);
Use the linked shader program program. If program is zero, any shaders
currently in use are unbound. OpenGL’s operation is undefined if no
shader is bound, but no error is generated.
While a program is in use, it can have new shader objects attached to it,
or detach previously attached objects. It may also be relinked. If the link
phase is successful, the newly linked shader program replaces the
previously active program. If the link fails, the currently bound shader
program remains active and is not replaced until either a new program is
specified with glUseProgram() or the program is successfully relinked.
Когда вы закончите работу с объектом шейдера,вы можете удалить его командой glDeleteShader(), даже если он прикреплен к активной программе. Также как с привязкой программы в “С”, когда у вас готово исполняемое приложение, вам больше не нужны объекты до тех пор, пока вы не повторите компиляцию.
void glDeleteShader(GLuint shader);
Deletes shader. If shader is currently linked to one or more active shader
programs, the object is tagged for deletion and deleted once the shader
program is no longer being used by any shader program.
Также, когда вы закончите с программой шейдера, вы можете её удалить через glDeleteProgram()
void glDeleteProgram(GLuint program);
Deletes program immediately if not currently in use in any context, or
schedules program for deletion when the program is no longer in use by
any contexts.
Наконец, для полного завершения вы также можете запросить, использыется ли имя файла каким-нибудь объектом шейдера, запросив glIsShader(), или для программы шейдера glIsProgram():
GLboolean glIsShader(GLuint shader);
Returns GL_TRUE if shader is the name of a shader object that was
previously generated with glCreateShader(), but has not been
subsequently deleted. Returns GL_FALSE if shader is zero or a nonzero
value that is not the name of a shader object.
GLboolean glIsProgram(GLuint program);
Returns GL_TRUE if program is the name of a program object that was
previously generated with glCreateProgram(), but has not been
subsequently deleted. Returns GL_FALSE if program is zero or a nonzero
value that is not the name of a program object.
