Введение в использование шейдеров OpenGL Компьютерная графика. Лекция 7.

Презентация:



Advertisements
Похожие презентации
Кратко об OpenGL OpenGL – развитие программного интерфейса IrisGL фирмы Silicon Graphics, Inc. Цель создания библиотеки - обеспечение низкоуровневого.
Advertisements

GPU vs. CPU 681 млн. транзисторов Тактовая частота 575Mhz * 768MB 1.8 Ghz памяти DDR4 ~650 млн. транзисторов Тактовая частота ~700Mhz 1GB 1.1 Ghz памяти.
Практическое занятие 6. Функции. Большинство языков программирования используют понятия функции и процедуры. C++ формально не поддерживает понятие процедуры,
Министерство образования Республики Беларусь Белорусский государственный университет Управляющие структуры языков программирования.
Графический конвейер Преобразования геометрии Александр Шубин.
Функции Функция – именованная последовательность описаний и операторов, выполняющая некоторое действие. Может иметь параметры и возвращать значение. Функция.
Основы информатики Лекция. Функции Заикин Олег Сергеевич
Лекция 4 Программирование на Паскале. Элементы языка Турбо Паскаль 7.0. Типы данных. Управляющие конструкции.
Обработка исключительных ситуаций Исключительная ситуация (исключение) – это ошибка, возникающая во время выполнения программы. Например, ошибка работы.
Глава 6. УПРАВЛЯЮЩИЕ СТРУКТУРЫ Оператор присваивания Простой и составной операторы Условный оператор Оператор множественного выбора Оператор цикла с предусловием.
Преобразования типов В языке C/C++ имеется несколько операций преобразования типов. Они используются в случае, если переменная одного типа должна рассматриваться.
Основы информатики Классы Заикин Олег Сергеевич zaikin.all24.org
Лекция 8 Область видимости Время жизни. Область видимости Область видимости – характеристика именованного объекта Область видимости - часть текста программы,
Лекция 9 Функции. Массивы-параметры функции Передача массива в функцию Пример: void array_enter(int a[], int size) { int i; for (i = 0; i < size; i++)
Работа с файлами Сазонов Д.О. ПМиЭММ Часть 2. Тема занятия: Работа с файлами через потоки Для реализации файлового ввода/вывода, необходимо включить в.
Тема: Управление потоком в PHP Изучить возможности языка PHP при решении задач, требующих использования условного оператора. Рассмотреть примеры управления.
Массивы 9 класс. Основные теоретические сведения Примеры решения задач.
©Павловская Т.А. (СПбГУ ИТМО) Курс «С#. Программирование на языке высокого уровня» Павловская Т.А.
Тема 2. Операторы (инструкции) передачи управления. Условный оператор (инструкция) и его формы. Логические выражения и логические переменные. Составные.
Языки и методы программирования Преподаватель – доцент каф. ИТиМПИ Кузнецова Е.М. Лекция 7.
Транксрипт:

Введение в использование шейдеров OpenGL Компьютерная графика. Лекция 7

Программируемое графическое аппаратное обеспечение существует почти столько же времени, сколько и обычное. Акселераторы разрабатываются несколько лет, а устаревают за год. Единственный способ гарантировать поддержу современных API – внести программируемость Н ЕОБХОДИМОСТЬ ПРОГРАММИРОВАНИЯ ГРАФИЧЕСКИХ АДАПТЕРОВ Компьютерная графика. Лекция 7

Несмотря на поддержу программируемости на уровне аппаратуры ей нельзя было воспользоваться, т.к. ни один графический API ее не поддерживал! Раскрытие возможностей программируемости требовало дорогостоящего обучения разработчиков и поддержки пользователей Но принципы разработки графической аппаратуры изменились. Разработчики требовали все новых и новых возможностей, чтобы создавать захватывающие эффекты и аппаратура стала более программируемой, чем когда либо ранее П РОБЛЕМЫ ПРОГРАММИРОВАНИЯ ГРАФИЧЕСКИХ АДАПТЕРОВ Компьютерная графика. Лекция 7

Одновременно с совершенствованием графической аппаратуры совершенствовались графические API. Первоначально разработчикам были доступны подобные ассемблеру языки для обработки графики, однако со временем появились удобные и надежные языки высокого уровня. Сегодня GPU стали универсальными процессорами для параллельной обработки чисел с плавающей запятой и могут быть использованы для решения огромного числа задач, даже не имеющих прямого отношения к графике Компьютерная графика. Лекция 7 Р АЗВИТИЕ ГРАФИЧЕСКИХ API

Интерактивные шейдерные языки стали доступны всем! Для желающего воспользоваться программируемостью графического аппаратного обеспечения существует множество вариантов: HLSL (Microsoft) Cg (NVidia) GLSL (ARB) Компьютерная графика. Лекция 7 Я ЗЫКИ ДЛЯ РАЗРАБОТКИ ШЕЙДЕРОВ

Ч ТО ТАКОЕ ШЕЙДЕР ? Шейдер (англ. – shader) – целостный кусок кода на языке шейдеров, предназначенный для выполнения на одном из программируемых процессоров В OpenGL 2.0 введены два типа шейдеров Вершинные шейдеры Фрагментные шейдеры Компьютерная графика. Лекция 7

Д ЛЯ ЧЕГО НУЖНЫ ШЕЙДЕРЫ ? OpenGL предоставляет программистам гибкий, но статический интерфейс для рисования графики Шейдеры позволяют приложению переопределить стандартный способ обработки графики на некоторых этапах рендеринга С помощью шейдеров стало возможным применение продвинутых технологий рендеринга в реальном времени Компьютерная графика. Лекция 7

Я ЗЫК ШЕЙДЕРОВ В O PEN GL 2.0 В 2004 году опубликован OpenGL2.0, основное нововведение – высокоуровневой язык шейдеров GLSL (OpenGL Shading Language), предоставляющих приложениям возможность реализации собственных механизмов рендеринга при помощи замены стандартных обработчиков вершин и фрагментов Отличительная особенность GLSL в том, что он тщательно анализировался и оценивался многими производителями аппаратного обеспечения. Основная цель при его создании – достижение кроссплатформенности, надежности и стандартизации Компьютерная графика. Лекция 7

О ТЛИЧИТЕЛЬНЫЕ ОСОБЕННОСТИ GLSL Тесная интеграция с OpenGL API GLSL был спроектирован для совместного использования с OpenGL. Специально предусмотрено, чтобы приложения можно было легко модифицировать для поддержки шейдеров. GLSL имеет встроенные возможности доступа к состоянию OpenGL Открытый межплатформенный стандарт За исключением языка шейдеров OpenGL, нет других шейдерных языков, являющихся частью межплатформенного стандарта. GLSL может быть реализован разными производителями на произвольных платформах Компьютерная графика. Лекция 7

О ТЛИЧИТЕЛЬНЫЕ ОСОБЕННОСТИ GLSL Компиляция во время выполнения Исходный код хранится в первоначальном, легко поддерживаемом виде и компилируется при необходимости Независимость от языка ассемблера различных производителей Проектировщики аппаратуры не ограничены языком ассемблера и имеют больше шансов получить выигрыш в производительности Компьютерная графика. Лекция 7

О ТЛИЧИТЕЛЬНЫЕ ОСОБЕННОСТИ GLSL Неограниченные возможности по оптимизации компилятора под различные платформы Усовершенствовать компиляторы можно с каждой новой версией драйвера OpenGL и приложения не придется модифицировать или перекомпилировать Отсутствие дополнительных библиотек и программ Все необходимое – язык шейдеров, компилятор и компоновщик – определены как часть OpenGL Компьютерная графика. Лекция 7

РАЗЛИЧИЕ МЕЖДУ ЯЗЫКАМИ O PEN GL И HLSL: Код на языке GLSL компилируется в машинный код непосредственно внутри драйвера графического ускорителя Код на HLSL транслируется в язык ассемблера внутри DirectX, а затем переводится в машинный код внутри драйвера Компьютерная графика. Лекция 7 Шейдер HLSL Транслятор HLSL Программа D3D Драйвер Direct3D Аппаратура Ассемблер Шейдер GLSL Драйвер OpenGL Аппаратура Компилятор GLSL ЯВУ

К ОНВЕЙЕР ОПЕРАЦИЙ O PEN GL Вплоть до версии 2.0 OpenGL предоставлял программистам статичный или фиксированный интерфейс для рисования графики На функционирование OpenGL можно смотреть как на стандартную последовательность операций, применяемую к геометрическим данным для вывода их на экран На различных этапах обработки графики разработчик может изменять массу параметров и получать различные результаты. Однако нельзя изменить ни сами фундаментальные операции, ни их порядок Рассмотрим стандартный конвейер операций OpenGL подробнее Компьютерная графика. Лекция 7

Д ИАГРАММА РАБОТЫ СТАНДАРТНОГО КОНВЕЙЕРА O PEN GL Основные этапы работы стандартного графического конвейера OpenGL Обработка вершин Трансформация вершин и нормалей Расчет освещения в вершинах Генерирование текстурных координат Обработка примитивов Сборка примитивов Отсечение Проецирование вершин Обработка фрагментов Растеризация примитивов, наложение текстур Операции над пикселями Компьютерная графика. Лекция 7

К ОНВЕЙЕР ОПЕРАЦИЙ O PEN GL Компьютерная графика. Лекция 7

П РОГРАММИРУЕМАЯ ФУНКЦИОНАЛЬНОСТЬ Самое большое изменение OpenGL со времени его создания – внедрение программируемых вершинных и фрагментных процессоров С введением программируемости, если она используется приложением, стандартная (или фиксированная ) функциональность выключается Часть процесса обработки вершин и фрагментов заменяется программируемой функциональностью. Потоки данных идут от приложения к вершинному процессору, потом к фрагментному и в итоге попадают в буфер кадров Рассмотрим конвейер операций с программируемыми процессорами Компьютерная графика. Лекция 7

К ОНВЕЙЕР ОПЕРАЦИЙ O PEN GL Компьютерная графика. Лекция 7

В ЕРШИННЫЙ ПРОЦЕССОР Это программируемый модуль, который выполняет операции над входными значениями вершин и другими связанными с ними данными. Вершинный процессор выполняет: Преобразование вершин Преобразование и нормализация нормалей Генерирование и преобразование текстурных координат Настройка освещения Наложение цвета на материал Шейдеры, предназначенные для выполнения на этом процессоре, называются вершинными Компьютерная графика. Лекция 7

В ХОДНЫЕ И ВЫХОДНЫЕ ДАННЫЕ ВЕРШИННОГО ПРОЦЕССОРА Вершинный процессор Встроенные переменные атрибутов: gl_Color, gl_Normal, gl_Vertex, gl_MultiTexCoord0 и др. Встроенные переменные атрибутов: gl_Color, gl_Normal, gl_Vertex, gl_MultiTexCoord0 и др. Определенные пользователем переменные атрибутов: StartColor, Velocity, Elevation, Tangent и т.п. Определенные пользователем переменные атрибутов: StartColor, Velocity, Elevation, Tangent и т.п. Определенные пользователем uniform-переменые: Time, EyePosition, LightPosition и т.п. Определенные пользователем uniform-переменые: Time, EyePosition, LightPosition и т.п. Встроенные uniform- переменые: gl_ModelViewMatrix, gl_FrontMaterial, gl_LightSource [0..n], gl_Fog и т.п. Встроенные uniform- переменые: gl_ModelViewMatrix, gl_FrontMaterial, gl_LightSource [0..n], gl_Fog и т.п. Встроенные varying- переменные: gl_FrontColor, gl_BackColor, gl_FogFragCoord и др. Встроенные varying- переменные: gl_FrontColor, gl_BackColor, gl_FogFragCoord и др. Специальные выходные переменные: gl_Position, gl_PointSize, gl_ClipVertex Специальные выходные переменные: gl_Position, gl_PointSize, gl_ClipVertex Определенные пользователем varying-переменные: Normal, ModelCoord, RefractionIndex, Density и т.п. Определенные пользователем varying-переменные: Normal, ModelCoord, RefractionIndex, Density и т.п. Карты текстур Компьютерная графика. Лекция 7

КВАЛИФИКАТОРЫ ТИПОВ Для управления входными и выходными данными вершинного шейдера используются квалификаторы типов, определенные как часть языка шейдеров OpenGL: Переменные-атрибуты ( attribute ) Однообразные переменные ( uniform ) Разнообразные переменные ( varying ) Компьютерная графика. Лекция 7

A TTRIBUTE - ПЕРЕМЕННЫЕ ВЕРШИННОГО ШЕЙДЕРА Представляют собой данные, передаваемые вершинному шейдеру от приложения Могут задавать значения атрибутов либо между glBegin()/glEnd(), либо при помощи функций, работающих с вершинными массивами OpenGL поддерживает как встроенные, так и определенные пользователем attribute- переменные gl_Normal, gl_Vertex, gl_Color Компьютерная графика. Лекция 7

U NIFORM - ПЕРЕМЕННЫЕ Используются для передачи редко изменяемых данных как вершинному, так и фрагментному шейдеру Uniform-переменные не могут задаваться между вызовами glBegin() и glEnd() OpenGL поддерживает как встроенные, так и определенные пользователем uniform-переменные Для передачи значения uniform-переменной приложение должно сначала определить расположение данной переменной (индекс) по имени Компьютерная графика. Лекция 7

V ARYING - ПЕРЕМЕННЫЕ Данные в varying-переменных передаются из вершинного шейдера в фрагментный Бывают как встроенными, так и определенными пользователем Для каждой вершины значение соответствующей varying-переменной будет своим В процессе растеризации происходит интерполяция значений varying-переменных с учетом перспективы Компьютерная графика. Лекция 7

Ф РАГМЕНТНЫЙ ПРОЦЕССОР Это программируемый модуль, выполняющий операции над фрагментами и другими связанными с ними данными ФП выполняет следующие стандартные операции: Операции над интерполируемыми значениями Доступ к текстурам Наложение текстур Создание эффекта тумана Смешивание цветов Шейдеры, предназначенные для выполнения на этом процессоре, называются фрагментными Компьютерная графика. Лекция 7

В ХОДНЫЕ И ВЫХОДНЫЕ ДАННЫЕ ФРАГМЕНТНОГО ПРОЦЕССОРА Фрагментный процессор Встроенные varying- переменные: gl_Color, gl_SecondaryColor, gl_TexCoord[0..n], gl_FogFragCoord Встроенные varying- переменные: gl_Color, gl_SecondaryColor, gl_TexCoord[0..n], gl_FogFragCoord Специальные входные переменные: gl_FragCoord gl_FrontFacing Специальные входные переменные: gl_FragCoord gl_FrontFacing Определенные пользователем varying-переменные: Normal, ModelCoord, RefractionIndex, Density и т.п. Определенные пользователем varying-переменные: Normal, ModelCoord, RefractionIndex, Density и т.п. Специальные выходные переменные: gl_FragColor gl_FragDepth Специальные выходные переменные: gl_FragColor gl_FragDepth Определенные пользователем uniform-переменные: ModelScaleFactor, AnimationPhase, WeightingFactor и т.п. Определенные пользователем uniform-переменные: ModelScaleFactor, AnimationPhase, WeightingFactor и т.п. Карты текстур Встроенные uniform- переменые: gl_ModelViewMatrix, gl_FrontMaterial, gl_LightSource [0..n], gl_Fog и т.п. Встроенные uniform- переменые: gl_ModelViewMatrix, gl_FrontMaterial, gl_LightSource [0..n], gl_Fog и т.п.

Ф РАГМЕНТНЫЙ ПРОЦЕССОР НЕ ЗАМЕНЯЕТ СЛЕДУЮЩИЕ ОПЕРАЦИИ : Покрытие Проверка на видимость Отсечение по прямоугольнику (scissors test) Тест трафарета Тест прозрачности Тест глубины Отсечение по трафарету Смешивание цветов Логические операции Dithering Определение видимости плоскостей Компьютерная графика. Лекция 7

В ХОДНЫЕ ДАННЫЕ ФРАГМЕНТНОГО ПРОЦЕССОРА Встроенные varying -переменные Определенные разработчиком varying- переменные Имена и типы должны совпадать с именами varying-переменных, определенных в вершинном шейдере Встроенные uniform -переменные Определенные разработчиком uniform- переменные Компьютерная графика. Лекция 7

Я ЗЫК ПРОГРАММИРОВАНИЯ ШЕЙДЕРОВ GLSL

Ц ЕЛИ, ПРЕСЛЕДУЕМЫЕ ЯЗЫКОМ ШЕЙДЕРОВ O PEN GL Обеспечение хорошей совместимости с OpenGL Использование гибкости графических ускорителей ближайшего будущего Предоставление независимости от графического ускорителя Увеличение производительности Легкость использования Обеспечение актуальности языка в будущем Невмешательство в более высокие уровни параллельной обработки Легкость разработки программ Компьютерная графика. Лекция 7

С ОВМЕСТИМОСТЬ С O PEN GL Язык GLSL разработан для использования совместно с OpenGL Предоставляются программируемые альтернативы стандартной функциональности OpenGL Язык и программируемые им процессоры имеют как минимум ту же функциональность, какую они заменяют Доступ к текущим состояниям OpenGL Компьютерная графика. Лекция 7

И СПОЛЬЗОВАНИЕ ГИБКОСТИ АКСЕЛЕРАТОРОВ БЛИЖАЙШЕГО БУДУЩЕГО Язык предоставляет необходимый уровень абстракции для данной предметной области Поддержка большого количества операций над скалярными и векторными величинами Исчезла необходимость развитие частичных расширений функциональности OpenGL Компьютерная графика. Лекция 7

Н ЕЗАВИСИМОСТЬ ОТ ГРАФИЧЕСКОГО УСКОРИТЕЛЯ Предшествующие расширения закончились созданием интерфейсов на языке ассемблера Ухудшает переносимость программ Высокоуровневой язык обеспечивает уровень абстракции, достаточный для переносимости Производители ускорителей используют гибкость языка для внедрения новейших архитектур и технологий компиляции Компьютерная графика. Лекция 7

У ВЕЛИЧЕНИЕ ПРОИЗВОДИТЕЛЬНОСТИ Современные компиляторы высокоуровневых языков генерируют код, практически не уступающий по производительности вручную написанному коду Высокоуровневой код может с легкостью компилироваться в более компактный и быстрый код, учитывающий возможности современных графических процессоров Для кода на языке ассемблера может потребоваться переписывание кода Компьютерная графика. Лекция 7

Л ЕГКОСТЬ ИСПОЛЬЗОВАНИЯ Легкость освоения языка программистами, знакомыми с Си и Си++ Язык для программируемых процессоров (в т.ч. и будущих) должен быть один и очень простой Компьютерная графика. Лекция 7

А КТУАЛЬНОСТЬ ЯЗЫКА В БУДУЩЕМ При разработке GLSL были приняты во внимание особенности ранее созданных языков, таких как C и RenderManRenderMan Язык тщательно стандартизован Ожидается, что ранее написанные программы будут актуальны и через 10 лет Компьютерная графика. Лекция 7

Н ЕВМЕШАТЕЛЬСТВО В БОЛЕЕ ВЫСОКИЕ УРОВНИ ПАРАЛЛЕЛЬНОЙ ОБРАБОТКИ Современные графические ускорители выполняют параллельную обработку вершин и фрагментов Язык проектировался с учетом возможного распараллеливания обработки на более высоких уровнях Компьютерная графика. Лекция 7

Л ЕГКОСТЬ РАЗРАБОТКИ ПРОГРАММ Язык шейдеров GLSL не поддерживает указатели и ссылки, параметры передаются по значению Нет проблемы с алиасингом Облегчается работа оптимизирующего компилятора Компьютерная графика. Лекция 7

С ВЯЗЬ С ЯЗЫКОМ C Точка входа в шейдерную программу – функция void main(), с кодом внутри фигурных скобок Константы, идентификаторы, операторы, выражения и предложения имеют много общего с языком C Циклы, ветвление, вызовы функций также аналогичны с языком C Многострочные комментарии Компьютерная графика. Лекция 7

Д ОПОЛНЕНИЕ К ЯЗЫКУ C Векторные типы данных для чисел с плавающей запятой, целых и булевых значений 2-х, 3-х и 4-х мерные векторы Матричные типы данных для чисел с плавающей запятой Матрицы 2x2, 3x3 и 4x4 Дискретизаторы (sampler-ы) для доступа к текстурам Спецификаторы attribute, uniform и varying входных и выходных переменных Встроенные переменные состояния OpenGL Начинаются с префикса gl_- gl_FragColor, gl_Position Множество встроенных функций Компьютерная графика. Лекция 7

Д ОПОЛНЕНИЯ К ЯЗЫКУ ИЗ C++ Перегрузка функций Конструкторы Объявление переменных в произвольном месте программы, а не только в начале блока Тип bool Однострочные комментарии Функции должны быть объявлены до их первого использования одним из следующих способов Определением тела функции Объявлением прототипа Компьютерная графика. Лекция 7

Н Е ПОДДЕРЖИВАЕМЫЕ ВОЗМОЖНОСТИ C Отсутствие неявного приведения типов float f = 0; // ошибка float f = 0.0; // правильно Нет поддержки указателей, строк, символов и операций над ними Нет чисел с плавающей запятой двойной точности Нет коротких, длинных и беззнаковых целых Нет union, enum и побитовых операторов Язык не файловый Нет директив типа #include и других ссылок на имена файлов Компьютерная графика. Лекция 7

П РОЧИЕ ОТЛИЧИЯ Вместо операторов приведения типов используются конструкторы Входные и выходные параметры функций передаются по значению Входные параметры функции обозначаются in Выходные параметры – out Входные и выходные одновременно – inout Компьютерная графика. Лекция 7

П РИМЕР ПРОСТЕЙШЕГО ВЕРШИННОГО ШЕЙДЕРА void main() { /* то же самое, что и gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; но обеспечивает инвариантность преобразования координат */ gl_Position = ftransform(); gl_FrontColor = gl_Color; } Компьютерная графика. Лекция 7

П РИМЕР ПРОСТЕЙШЕГО ФРАГМЕНТНОГО ШЕЙДЕРА void main() { gl_FragColor = gl_Color; } Компьютерная графика. Лекция 7

З АГРУЗКА, КОМПИЛЯЦИЯ И КОМПОНОВКА ШЕЙДЕРНЫХ ПРОГРАММ

М ОДЕЛЬ ПОДГОТОВКИ O PEN GL- ШЕЙДЕРОВ Приложение Исходный код шейдера Компилятор Объектный код шейдера Компоновщик Объектный код программы Графический ускоритель OpenGL API Компьютерная графика. Лекция 7

Ш АГ 1 – СОЗДАНИЕ ШЕЙДЕРНОГО ОБЪЕКТА Для начала необходимо создать шейдерный объект (структура данных драйвера OpenGL для работы с шейдером) Для создания шейдерного объекта служит функция glCreateShaderObjectARBglCreateShaderObjectARB Возвращенный данной функцией объект имеет тип GLhandleARB и используется приложением для дальнейшей работы с шейдерным объектом Компьютерная графика. Лекция 7

П РИМЕР СОЗДАНИЯ ШЕЙДЕРА // создание вершинного шейдера GLhandleARB vertexShader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); // создание фрагментного шейдера GLhandleARB fragmentShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); Компьютерная графика. Лекция 7

Ш АГ 2 – ЗАГРУЗКА ИСХОДНОГО КОДА ШЕЙДЕРА В ШЕЙДЕРНЫЙ ОБЪЕКТ Исходный код шейдера – массив строк, состоящих из символов Каждая строка может состоять из нескольких обычных строк, разделенных символом конца строки Для передачи исходного кода приложение должно передать массив строк в OpenGL при помощи glShaderSourceARBglShaderSourceARB Компьютерная графика. Лекция 7

П РИМЕР ЗАГРУЗКИ ИСХОДНОГО КОДА В ШЕЙДЕРНЫЙ ОБЪЕКТ const GLcharARB shaderSource1[] = исходный код шейдера - начало; const GLcharARB shaderSource2[] = исходный код шейдера - окончание; GLcharARB const * shaderSources[] = { shaderSource1, shaderSource2 }; glShaderSourceARB(vertexShader, 2, shaderSources, NULL); const GLcharARB shaderSource1[] = исходный код шейдера - начало; const GLcharARB** pShaderSource = &shaderSource; glShaderSourceARB(vertexShader, 1, pShaderSource, NULL); В случае, когда исходный код находится в одной строке, задача слегка упрощается: Компьютерная графика. Лекция 7

Ш АГ 3 – КОМПИЛЯЦИЯ ШЕЙДЕРНОГО ОБЪЕКТА Компиляция шейдерного объекта преобразует исходный код шейдера из текстового представления в объектный код Скомпилированные шейдерные объекты могут быть в дальнейшем связаны с программным объектом, для ее дальнейшей компоновки Компиляция шейдерного объекта осуществляется при помощи функции glCompileShaderARB glCompileShaderARB Компьютерная графика. Лекция 7

П РИМЕР КОМПИЛЯЦИИ ШЕЙДЕРНОГО ОБЪЕКТА glCompileShaderARB(shader); // проверяем успешность компиляции GLint compileStatus; glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &compileStatus); if (compileStatus != GL_TRUE) { printf(Shader compilation error); return 0; } Компьютерная графика. Лекция 7

Ш АГ 4 – СОЗДАНИЕ ПРОГРАММНОГО ОБЪЕКТА Программный объект включает в себя один или более шейдеров и заменяет собой часть стандартной функциональности OpenGL Программный объект создается при помощи функции glCreateProgramObjectARBglCreateProgramObjectARB Возвращенный данной функцией программный объект имеет тип GLhandleARB и может быть использован для дальнейшей работы с программным объектом Компьютерная графика. Лекция 7

П РИМЕР СОЗДАНИЯ ПРОГРАММНОГО ОБЪЕКТА GLhandleARB program = glCreateProgramObjectARB(); Компьютерная графика. Лекция 7

Ш АГ 5 – СВЯЗЫВАНИЕ ШЕЙДЕРНЫХ ОБЪЕКТОВ С ПРОГРАММНЫМ ОБЪЕКТОМ Приложение может использовать несколько программных объектов, собранных из разных шейдеров Для указания OpenGL, какие шейдеры с данной программой используются, служит функция glAttachObjectARB, выполняющая присоединение шейдерного объекта к программному объектуglAttachObjectARB Компьютерная графика. Лекция 7

П РИМЕР СВЯЗЫВАНИЯ ШЕЙДЕРНЫХ ОБЪЕКТОВ С ШЕЙДЕРНОЙ ПРОГРАММОЙ GLhandleARB program; GLhandleARB vertexShader; GLhandleARB fragmentShader; // … glAttachObjectARB(program, vertexShader); glAttachObjectARB(program, fragmentShader); Компьютерная графика. Лекция 7

Ш АГ 6 – КОМПОНОВКА ШЕЙДЕРНОЙ ПРОГРАММЫ После связывания скомпилированных шейдерных объектов с программным объектом программу необходимо скомпоновать Скомпонованный программный объект можно использовать для включения в процесс рендеринга Компоновка программы осуществляется при помощи функции glLinkProgramARBglLinkProgramARB Компьютерная графика. Лекция 7

П РИМЕР КОМПОНОВКИ ПРОГРАММНОГО ОБЪЕКТА glLinkProgramARB(program); GLint linkStatus; glGetObjectParameterivARB(program, GL_OBJECT_LINK_STATUS_ARB, &linkStatus); if (linkStatus != GL_TRUE) { printf(Program linking error); } Компьютерная графика. Лекция 7

Ш АГ 7 – ВАЛИДАЦИЯ ПРОГРАММНОГО ОБЪЕКТА Необязательный шаг, позволяющий проверить скомпонованную программу на корректность Например, получить сведения о возможных причинах неэффективной работы шейдерной программы Проверка корректности скомпонованной программы осуществляется при помощи функции glValidateProgramARBglValidateProgramARB Компьютерная графика. Лекция 7

П РИМЕР ВАЛИДАЦИИ ШЕЙДЕРНОЙ ПРОГРАММЫ void Validate() { //... glValidateProgramARB(program); GLint validationStatus; glGetObjectParameterivARB(program, GL_OBJECT_VALIDATE_STATUS_ARB, &validationStatus); PrintInfoLog(program) if (validationStatus != GL_TRUE) { return; } //... } void PrintInfoLog(GLhandleARB object) { GLcharARB buffer[10000]; GLsizei length; glGetInfoLogARB(object, sizeof(buffer) - 1, &length, buffer); printf(%s, buffer); } Компьютерная графика. Лекция 7

Ш АГ 8 – УСТАНОВКА ШЕЙДЕРНОЙ ПРОГРАММЫ КАК ЧАСТЬ ТЕКУЩЕГО СОСТОЯНИЯ O PEN GL Приложение может скомпоновать одну или несколько шейдерных программ Каждая программа может реализовывать тот или иной способ рендеринга Данные программы могут быть установлены в текущее состояние для рендеринга при помощи функции glUseProgramObjectARBglUseProgramObjectARB При этом стандартные механизмы рендеринга вершин и/или фрагментов будут заменены на определенные пользователем Компьютерная графика. Лекция 7

П РИМЕР УСТАНОВКИ ПРОГРАММНОГО ОБЪЕКТА // делаем программный объект активным glUseProgramObjectARB(program); // выполняем настройку программного объекта и рендеринг объектов //... // переключаемся на стандартный механизм рендеринга glUseProgramObjectARB(NULL); Компьютерная графика. Лекция 7

У ДАЛЕНИЕ ПРОГРАММ И ШЕЙДЕРОВ Ставшие ненужными шейдерные и программные объекты необходимо удалить при помощи функции glDeleteObjectARBglDeleteObjectARB Шейдерные объекты, с помощью которых была скомпонована шейдерная программа можно удалять – программный объект при этом сохранит работоспособность Компьютерная графика. Лекция 7

П РИМЕР УДАЛЕНИЯ ШЕЙДЕРНЫХ И ПРОГРАММНЫХ ОБЪЕКТОВ glDeleteObjectARB(program); glDeleteObjectARB(vertexShader); glDeleteObjectARB(fragmentShader); Компьютерная графика. Лекция 7

П ЕРЕДАЧА ПАРАМЕТРОВ В ШЕЙДЕРНУЮ ПРОГРАММУ

П ЕРЕДАЧА ЗНАЧЕНИЙ UNIFORM - ПЕРЕМЕННЫХ В ШЕЙДЕРНУЮ ПРОГРАММУ Приложение может задать значение uniform- переменной программного объекта с заданным расположением при помощи функции glUniformARB glUniformARB Программный объект должен быть предварительно сделан активным Расположение uniform-переменной по ее имени можно получить при помощи функции glGetUniformLocationARB glGetUniformLocationARB Компьютерная графика. Лекция 7

П РИМЕР ПЕРЕДАЧИ UNIFORM - ПЕРЕМЕННОЙ В ШЕЙДЕР // делаем программный объект активным glUseProgramObjectARB(program); // получаем расположение uniform-переменной phase (предполагается, что данная переменная объявлена в одном из шейдеров с квалификатором uniform) GLint phaseLocation = glGetUniformLocationARB(program, "phase"); // задаем значение данной переменной (предполагается, что переменная имеет тип float (суффикс 1f в имени функции glUniform*ARB) glUniform1fARB(phaseLocation, 0.8f); // деактивируем шейдерную программу glUseProgramObjectARB(NULL); Компьютерная графика. Лекция 7

П ЕРЕДАЧА ATTRIBUTE - ПЕРЕМЕННЫХ ШЕЙДЕРНОЙ ПРОГРАММЕ Значение attribute-переменной с известным расположением может быть передано шейдеру при помощи функции glVertexAttrib*ARB внутри glBegin()/glEnd() перед вызовом glVertex()glVertexAttrib*ARB Целый массив атрибутов вершин может быть передан вершинному шейдеру при помощи функции glVertexAttribPointerARBglVertexAttribPointerARB Узнать расположение attribute-переменной можно при помощи функции glGetAttribLocationARB glGetAttribLocationARB Компьютерная графика. Лекция 7

П РИМЕР ПЕРЕДАЧИ ЗНАЧЕНИЯ ATTRIBUTE - ПЕРЕМЕННОЙ ОТДЕЛЬНО ВЗЯТОЙ ВЕРШИНЫ // получаем расположение атрибута vertex2 GLint vertex2Location = glGetAttribLocationARB(program, "vertex2"); // делаем программный объект активным glUseProgramObjectARB(program); glBegin(GL_TRIANGLES); // задаем значение attribute-переменной vertex2, объявленной как vec3 glVertexAttrib3fARB(vertex2Location, 0, 0.5f, 1); glVertex3f(0, 0, 0); glVertexAttrib3fARB(vertex2Location, 2, 0.5f, 1); glVertex3f(0, 1, 0); glVertexAttrib3fARB(vertex2Location, 3, 0.5f, 1); glVertex3f(0, 0, 1); glEnd(); glUseProgramObjectARB(NULL); Компьютерная графика. Лекция 7

П РИМЕР ПЕРЕДАЧИ МАССИВА ATTRIBUTE - ПЕРЕМЕННЫХ ШЕЙДЕРУ // получаем расположение атрибута vertex2 GLint vertex2Location = glGetAttribLocationARB(program, "vertex2"); // делаем программный объект активным glUseProgramObjectARB(program); // задаем параметры массива атрибутов и массива вершин (в данном случае attribute- переменная vertex2 объявлена как vec3) glVertexAttribPointerARB(vertex2Location, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), &g_shapeVertices[0].x1); glVertexPointer(3, GL_FLOAT, sizeof(Vertex), &g_shapeVertices[0]); // разрешаем доступ к массивам вершин и атрибутов glEnableVertexAttribArrayARB(vertex2Attribute); glEnableClientState(GL_VERTEX_ARRAY); // рисуем массив примитивов glDrawArrays(GL_LINE_LOOP, 0, NUMBER_OF_VERTICES); // запрещаем доступ к массивам вершин и атрибутов glDisableVertexAttribArrayARB(vertex2Attribute); glDisableClientState(GL_VERTEX_ARRAY); // делаем программу неактивной glUseProgramObjectARB(NULL); Компьютерная графика. Лекция 7

О СНОВЫ ЯЗЫКА ПРОГРАММИРОВАНИЯ ШЕЙДЕРОВ O PEN GL

Т ИПЫ ДАННЫХ GLSL поддерживает следующие типы данных Скалярные типы Векторы Матрицы Дискретизаторы (samplers) Структуры Массивы Тип void Компьютерная графика. Лекция 7

С КАЛЯРНЫЕ ТИПЫ ДАННЫХ float – целое число с плавающей запятой float f; float g, h = 2.4; float scale = 3.0; int – целое число (как минимум 16 разрядов) int i = 0x18; int numberOfTextures = 5; Особенности: нет побитовых операций, не происходит переполнения или исчезновения значащих разрядов bool – булева переменная bool pointIsOutsideThePlane; bool overflow; Конструкции if-else принимают только булевы значения Компьютерная графика. Лекция 7

В ЕКТОРНЫЕ ТИПЫ ДАННЫХ Векторы чисел c плавающей запятой vec2, vec3, vec4 vec3 normal; vec4 color = vec4(0.3, 0.1, 0.2, 1.0); Векторы целых чисел ivec2, ivec3, ivec4 ivec3 v(3, 2, 1); Векторы булевых значений bvec2, bvec3, bvec4 bvec2 usage(true, false); bvec3 intersectionFlags; Компьютерная графика. Лекция 7

А ДРЕСАЦИЯ ЭЛЕМЕНТОВ ВЕКТОРА По индексам pos[3] = 5.0; По именам Вектор рассматривается как координаты или направление: x, y, z, w position.z -= 1.0; Вектор рассматривается как значение цвета: r, g, b, a gl_Color.g = 0.1; Вектор рассматривается как координаты текстуры: s, t, p, q gl_TexCoord[1].s = 0.4; Компьютерная графика. Лекция 7

М АТРИЦЫ В GLSL поддерживаются встроенные матрицы из чисел с плавающей запятой mat2 mat3 mat4 Матрицу можно рассматривать как массив столбцов векторов mat4 transform; vec4 col2 = transform[2]; // третий столбец матрицы Компьютерная графика. Лекция 7

Д ИСКРЕТИЗАТОРЫ В стандарте OpenGL не определено, в каком виде будут реализованы текстурные модули Доступ к текстурному объекту (выборка из текстуры) осуществляется при помощи дискретизатора (sampler) Типы дискретизаторов sampler1D sampler2D sampler3D samplerCube sampler1DShadow sampler2DShadow Компьютерная графика. Лекция 7

С ТРУКТУРЫ Объявление структуры похоже на их объявление в языке C struct LightSource { vec3 position; vec3 color; }; LightSource light1; Структуры могут быть объявлены внутри других структур В состав структур могут входить массивы Битовые поля не поддерживаются Компьютерная графика. Лекция 7

М АССИВЫ Язык допускает создание массивов любых типов vec4 points[10]; // массив из 10 элементов (индексы от 0 до 9) points[3].x = 3.0; // ссылка на четвертый элемент Компьютерная графика. Лекция 7

О БЪЯВЛЕНИЕ МАССИВОВ БЕЗ УКАЗАНИЯ РАЗМЕРОВ Допускается объявлять массивы без указания размера, если выполняется одно из условий: Перед ссылкой на массив он объявлен еще раз с указанием размера того же типа vec4 points[]; // размер неизвестен vec4 points[10]; // размер 10 элементов vec4 points[]; // ошибка – размер уже определен vec4 points[20]; // ошибка – размер уже определен Индексы, ссылающиеся на массив – константы времени компиляции vec4 points[]; // размер неизвестен points[3].z = 0.3; // размер – 4 элемента points[5].y = 3.4; // размер – 6 элементов Компьютерная графика. Лекция 7

Т ИП VOID Используется для указания, что функция не возвращает никакого значения void main() { … } Компьютерная графика. Лекция 7

О БЪЯВЛЕНИЯ И ОБЛАСТЬ ВИДИМОСТИ Переменные могут объявляться по мере необходимости (как в C++), а не в начале блока Область видимости ограничена блоком, в котором переменная была объявлена Исключение – нельзя объявлять переменные внутри оператора if Область видимости переменной, объявленной в операторе for заканчивается в конце тела цикла Компьютерная графика. Лекция 7

С ОГЛАСОВАНИЕ И ПРЕОБРАЗОВАНИЕ ТИПОВ Язык GLSL строго типизирован Типы аргументов, передаваемых в функцию, должны соответствовать типу формальных параметров Типы аргументов операторов должны соответствовать требованиям конкретного оператора Строгая типизация позволяет избежать неоднозначностей при использовании перегруженных функций Компьютерная графика. Лекция 7

И НИЦИАЛИЗАТОРЫ Инициализация может быть совмещена вместе с объявлением переменной float a, b = 3.0, c; Константные переменные должны быть обязательно инициализированы const int size = 4; Attribute, uniform и varying-переменные при объявлении нельзя инициализировать attribute float temparature; uniform int size; varying float transparency; Компьютерная графика. Лекция 7

И НИЦИАЛИЗАЦИЯ СОСТАВНЫХ ТИПОВ Для инициализации составных типов используются конструкторы vec4 v = vec4(1.0, 2.0, 3.0, 4.0); vec4 v; v = vec4(1.0, 2.0, 3.0, 4.0); mat2 m(1.0, 2.0, 3.0, 4.0); // элементы матрицы перечисляются по столбцам Дискретизаторы не имеют конструкторов Возможно инициализация структур с помощью конструкторов Элементы перечисляются в порядке их объявления в структуре Компьютерная графика. Лекция 7

С ПЕЦИФИКАТОРЫ ПЕРЕМЕННЫХ attribute Используется для объявления переменной-атрибута вершины, значение которой задается приложением для каждой отдельно взятой вершины uniform Используется для объявления переменной, значение которой задается приложением для группы примитивов varying Используется для объявления переменной, посредством которой вершинный шейдер передает результаты вычислений фрагментному шейдеру const Константы времени компиляции, не видимые вне шейдера, в котором объявлены Компьютерная графика. Лекция 7

П ЕРЕМЕННЫЕ БЕЗ СПЕЦИФИКАТОРОВ Переменные в глобальной области видимости, объявленные без спецификаторов могут использоваться совместно шейдерами одного типа, скомпонованными в одну программу Время существования таких переменных ограничено одним запуском шейдера Понятие «статических переменных» отсутствует Сохранение значения переменной между запусками шейдера препятствовало бы параллельной обработке вершин и фгагментов Компьютерная графика. Лекция 7

П ОСЛЕДОВАТЕЛЬНОЕ ВЫПОЛНЕНИЕ Программа на языке шейдеров OpenGL выполняется последовательно Точка входа в шейдер – функция void main() Перед входом в функцию выполняется инициализация глобальных переменных Операторы for, while, do-while огранизуют циклическое выполнение Условное выполнение обеспечивается операторами if-else и оператором ?: В операторе ?: типы 2-го и 3-го операндов должны совпадать Оператор discard может запретить запись фрагмента в кадровый буфер Операторы goto и switch отсутствуют Компьютерная графика. Лекция 7

Ф УНКЦИИ, ОПРЕДЕЛЯЕМЫЕ ПОЛЬЗОВАТЕЛЕМ Функции объявляются аналогично C++ Допускается перегрузка функций Более строгий контроль над типами входных и выходных параметров Запрещен явный или косвенный рекурсивный вызов функции Для аргументов можно задать следующие спецификаторы in – аргумент копируется при входе out – аргумент копируется при выходе inout – аргумент копируется как при входе, так и при выходе К аргументам может применяться спецификатор const не применим к out и inout-параметрам Компьютерная графика. Лекция 7

П РИМЕРЫ ОБЪЯВЛЕНИЯ ФУНКЦИЙ void ComputeCoord(in vec3 normal, vec3 tangent, inout vec3 coord); vec3 ComputeCoord(const vec3 normal, vec3 tangent, in vec3 coord); Компьютерная графика. Лекция 7

В СТРОЕННЫЕ ФУНКЦИИ В языке GLSL есть обширный набор встроенных функций Полный набор встроенных функций можно найти в спецификации языка спецификации языка Любая из встроенных функций может быть переопределена в шейдере Компьютерная графика. Лекция 7

О ПЕРАЦИИ Операции в основном объявляются аналогично операциям в языке C Отсутствуют побитовые операции Многие операции применимы как к скалярным, так и к векторным операндам Компьютерная графика. Лекция 7

О БРАЩЕНИЕ К КОМПОНЕНТАМ ВЕКТОРОВ И S WIZZLING При обращении к элементам векторов можно перечислять компоненты, к которым проводится обращение vec4 v4; vec4 v41 = v4.rgba; vec3 v3 = v4.rgb; v4.b = 4.3; v4.yx = v4.xy; v4.xy = v3.rr; Компьютерная графика. Лекция 7

П ОКОМПОНЕНТНЫЕ ОПЕРАЦИИ Если к вектору применяется какой-либо оператор, операция выполняется так же, как если бы она выполнялась над каждым компонентом вектора в отдельности vec3 v, u; float f; v = u + f; // v.x = u.x + f; v.y = u.y + f; v.z = u.z + f; vec2 v, y, w; v = y + w; // v.x = y.x + w.x; v.y = y.y + w.y; Исключение – умножение вектора на матрицу или матрицы на вектор производит математическое, а не покомпонентное умножение Компьютерная графика. Лекция 7

П РЕПРОЦЕССОР Поддерживаются директивы препроцессора #define, #undef, #if, #ifdef, #ifndef, #else, #elif, #defined, #error, #line, #pragma Имеется набор встроенных макросов __LINE__, __FILE__, __VERSION__ Компьютерная графика. Лекция 7

О БРАБОТКА ОШИБОК Некоторые ошибки в процессе компиляции могут быть не замечены Невозможен полный контроль над использованием неинициализированных переменных Программы, содержащие такие ошибки по- разному могут выполняться на разных платформах Спецификация языка не гарантирует корректное выполнение программ, в которых присутствует обращение к неинициализированным переменным Компьютерная графика. Лекция 7

П РАКТИЧЕСКОЕ ИСПОЛЬЗОВАНИЕ ШЕЙДЕРОВ

П РОСТЕЙШИЙ ПРИМЕР ИСПОЛЬЗОВАНИЯ ШЕЙДЕРОВ Разработаем вершинный и фрагментный шейдеры, выполняющие базовые преобразования вершин и фрагментов Простейший вершинный шейдер будет выполнять преобразование вершин в пространство координат канонический объем Сделать это можно при помощи встроенной функции ftransform() Простейший фрагментный шейдер будет задавать константное значение цвета фрагмента Компьютерная графика. Лекция 7

П РИМЕР // Простейший вершинный шейдер void main() { // аналогично gl_Vertex = gl_ModelViewProjectionMatrix * gl_Vertex; gl_Position = ftransform(); } // Простейший фрагментный шейдер void main() { gl_FragColor = vec4(0.5, 0.2, 0.5, 1.0); } Компьютерная графика. Лекция 7

П РОСТЕЙШЕЕ ДИФФУЗНОЕ ОСВЕЩЕНИЕ Вспомним формулу Ламберта для расчета диффузной составляющей освещения I d – интенсивность рассеянного света I s – интенсивность падающего света s – направление на источник света m – направление нормального вектора в точке поверхности Компьютерная графика. Лекция 7

О СОБЕННОСТИ РЕАЛИЗАЦИИ НА GLSL Стандартная модель освещения OpenGL производит вычисления освещенности лишь в вершинах примитивов, интерполируя полученный свет вдоль фрагментов примитива На практике объекты выглядят довольно некрасиво При помощи языка шейдеров GLSL можно вычислить диффузное освещение для каждого фрагмента примитива Компьютерная графика. Лекция 7

П РИНЦИП РАБОТЫ m1m1 m2m2 m3m3 s2s2 s1s1 s3s3 Вершинный шейдер вычисляет необходимые векторы в вершинах примитива В процессе примитива растеризации значения, вычисленные вершинным шейдером интерполируются и передаются через varying-переменные фрагментному шейдеру Фрагментшый шейдер вычисляет интенсивность диффузного освещения по формуле Ламберта, используя значения переданных varying-переменных Компьютерная графика. Лекция 7

Ф УНКЦИИ ВЕРШИННОГО ШЕЙДЕРА Выполняет трансформацию вершин Вычисляет векторы s и m в вершинах примитива Вычисленные векторы передаются через varying- переменные фрагментному шейдеру Нововведения: gl_ModelViewMatrix – матрица моделирования-вида gl_LightSource – массив структур, определяющих характеристики встроенных источников света gl_NormalMatrix – матрица 3x3 для преобразования нормалей – получается из glModelViewMatrix gl_Normal – вектор нормали, связанный с вершиной Компьютерная графика. Лекция 7

И СХОДНЫЙ КОД ВЕРШИННОГО ШЕЙДЕРА // Varying-переменные, передаваемые от вершинного шейдера во фрагментный varying vec3 L;// направление на источник света varying vec3 N;// направление вектора нормали void main(void) { // вычисляем координаты вершины в системе координат наблюдателя // там же задается и положение источника света vec3 p = vec3(gl_ModelViewMatrix * gl_Vertex); // вычисляем направление на источник света L = normalize(gl_LightSource[0].position.xyz - p); // трансформируем вектор нормали в систему координат наблюдателя N = normalize(gl_NormalMatrix * gl_Normal); // вычисляем позицию вершины – обязательный этап работы вершинного шейдера gl_Position = ftransform(); } Компьютерная графика. Лекция 7

Ф УНКЦИИ ФРАГМЕНТНОГО ШЕЙДЕРА Нормализация вектора нормали и направления на источник света Необходимо, т.к. при интерполяции векторов нормали и источника света они перестают быть единичными Используется функция встроенная функция normalize() Вычисление диффузной составляющей освещения по формуле Ламберта Используется встроенная функция dot() для вычисления скалярного произведения и функция max() для определения максимального из 2-х значений Формирование цвета фрагмента Компьютерная графика. Лекция 7

И СХОДНЫЙ КОД ФРАГМЕНТНОГО ШЕЙДЕРА /* векторы нормали и направления на источник света, изменяющиеся при растеризации примитива */ varying vec3 L; varying vec3 N; void main (void) { // нормируем вектора, т.к. при интерполяции они перестают быть единичными vec3 N2 = normalize(N); vec3 L2 = normalize(L); // вычисление диффузной составляющей освещения vec4 Idiff = vec4 ( 1.0, 1.0, 1.0, 1.0 ) * max(dot(N2,L2), 0.0); // необходимый шаг – формирование цвета фрагмента gl_FragColor = Idiff; } Компьютерная графика. Лекция 7

Р ЕЗУЛЬТАТ Компьютерная графика. Лекция 7

Д АЛЬНЕЙШИЕ УЛУЧШЕНИЯ Наложение текстуры для детализации поверхности цветом Вычисление зеркальной составляющей освещения Можно использовать формулу Фонга Применение более одного источника света Компьютерная графика. Лекция 7