1.1k likes | 1.73k Views
Компьютерная графика. Лекция 7. Введение в использование шейдеров OpenGL. Необходимость программирования графических адаптеров. Компьютерная графика. Лекция 7. Программируемое графическое аппаратное обеспечение существует почти столько же времени, сколько и обычное.
E N D
Компьютерная графика. Лекция 7 Введение в использование шейдеров OpenGL
Необходимость программирования графических адаптеров Компьютерная графика. Лекция 7 Программируемое графическое аппаратное обеспечение существует почти столько же времени, сколько и обычное. Акселераторы разрабатываютсянесколько лет, а устаревают за год. Единственный способ гарантировать поддержу современных API – внести программируемость
Компьютерная графика. Лекция 7 Проблемы программирования графических адаптеров • Несмотря на поддержу программируемости на уровне аппаратуры ей нельзя было воспользоваться, т.к. ни один графический API ее не поддерживал! • Раскрытие возможностей программируемости требовало дорогостоящего обученияразработчиков и поддержки пользователей • Но принципы разработки графической аппаратуры изменились. Разработчики требовали все новых и новых возможностей, чтобы создавать захватывающие эффекты и аппаратура стала более программируемой, чем когда либо ранее
Компьютерная графика. Лекция 7 Развитие графических API • Одновременно с совершенствованием графической аппаратуры совершенствовались графические API. • Первоначально разработчикам были доступны подобные ассемблеру языки для обработки графики, однако со временем появились удобные и надежные языки высокого уровня. • Сегодня GPU стали универсальными процессорами для параллельной обработки чисел с плавающей запятой и могут быть использованы для решения огромного числа задач, даже не имеющих прямого отношения к графике
Компьютерная графика. Лекция 7 Языки для разработки шейдеров • Интерактивные шейдерные языки стали доступны всем! • Для желающего воспользоваться программируемостью графического аппаратного обеспечения существует множество вариантов: • HLSL (Microsoft) • Cg (NVidia) • GLSL (ARB)
Что такое шейдер? Компьютерная графика. Лекция 7 • Шейдер (англ. – shader) – целостный кусок кода на языке шейдеров, предназначенный для выполнения на одном из программируемых процессоров • В OpenGL 2.0 введены два типа шейдеров • Вершинные шейдеры • Фрагментные шейдеры
Для чего нужны шейдеры? Компьютерная графика. Лекция 7 • OpenGL предоставляет программистам гибкий, но статический интерфейс для рисования графики • Шейдеры позволяют приложению переопределить стандартный способ обработки графики на некоторых этапах рендеринга • С помощью шейдеров стало возможным применение продвинутых технологий рендеринга в реальном времени
Язык шейдеров в Open GL 2.0 Компьютерная графика. Лекция 7 • В 2004 году опубликован OpenGL2.0, основное нововведение – высокоуровневой язык шейдеров GLSL (OpenGL Shading Language), предоставляющих приложениям возможность реализации собственных механизмов рендеринга при помощи замены стандартных обработчиков вершин и фрагментов • Отличительная особенность GLSL в том, что он тщательно анализировался и оценивался многими производителями аппаратного обеспечения. Основная цель при его создании – достижение кроссплатформенности, надежности и стандартизации
Отличительные особенности GLSL Компьютерная графика. Лекция 7 • Тесная интеграция с OpenGL API • GLSL был спроектирован для совместного использования с OpenGL. Специально предусмотрено, чтобы приложения можно было легко модифицировать для поддержки шейдеров. GLSL имеет встроенные возможности доступа к состоянию OpenGL • Открытый межплатформенный стандарт • За исключением языка шейдеров OpenGL, нет других шейдерных языков, являющихся частью межплатформенного стандарта. GLSL может быть реализован разными производителями на произвольных платформах
Отличительные особенности GLSL Компьютерная графика. Лекция 7 • Компиляция во время выполнения • Исходный код хранится в первоначальном, легко поддерживаемом виде и компилируется при необходимости • Независимость от языка ассемблера различных производителей • Проектировщики аппаратуры не ограничены языком ассемблера и имеют больше шансов получить выигрыш в производительности
Отличительные особенности GLSL Компьютерная графика. Лекция 7 • Неограниченные возможности по оптимизации компилятора под различные платформы • Усовершенствовать компиляторы можно с каждой новой версией драйвера OpenGL и приложения не придется модифицировать или перекомпилировать • Отсутствие дополнительных библиотек и программ • Все необходимое – язык шейдеров, компилятор и компоновщик – определены как часть OpenGL
различие между языками OpenGL и HLSL: Компьютерная графика. Лекция 7 • Код на языке GLSL компилируется в машинный код непосредственно внутри драйвера графического ускорителя • Код на HLSL транслируется в язык ассемблера внутри DirectX, а затем переводится в машинный код внутри драйвера Шейдер HLSL Шейдер GLSL ЯВУ Транслятор HLSL Программа D3D Драйвер OpenGL Ассемблер Компилятор GLSL Драйвер Direct3D Аппаратура Аппаратура
Конвейеропераций OpenGL Компьютерная графика. Лекция 7 • Вплоть до версии 2.0 OpenGL предоставлял программистам статичный или фиксированный интерфейс для рисования графики • На функционирование OpenGL можно смотреть как на стандартную последовательность операций, применяемую к геометрическим данным для вывода их на экран • На различных этапах обработки графики разработчик может изменять массу параметров и получать различные результаты. Однако нельзя изменить ни сами фундаментальные операции, ни их порядок • Рассмотрим стандартный конвейер операций OpenGL подробнее
Диаграмма работы стандартного конвейера OpenGL Компьютерная графика. Лекция 7 • Основные этапы работы стандартногографического конвейера OpenGL • Обработка вершин • Трансформация вершин и нормалей • Расчет освещения в вершинах • Генерирование текстурных координат • Обработка примитивов • Сборка примитивов • Отсечение • Проецирование вершин • Обработка фрагментов • Растеризация примитивов, наложение текстур • Операции над пикселями
Конвейеропераций OpenGL Компьютерная графика. Лекция 7
Программируемая функциональность Компьютерная графика. Лекция 7 • Самое большое изменение OpenGL со времени его создания – внедрение программируемых вершинных и фрагментных процессоров • С введением программируемости, если она используется приложением, стандартная (или фиксированная) функциональность выключается • Часть процесса обработки вершин и фрагментов заменяется программируемой функциональностью. Потоки данных идут от приложения к вершинному процессору, потом к фрагментному и в итоге попадают в буфер кадров • Рассмотрим конвейер операций с программируемыми процессорами
Конвейеропераций OpenGL Компьютерная графика. Лекция 7
Вершинный процессор Компьютерная графика. Лекция 7 • Это программируемый модуль, который выполняет операции над входными значениями вершин и другими связанными с ними данными. • Вершинный процессор выполняет: • Преобразование вершин • Преобразование и нормализация нормалей • Генерирование и преобразование текстурных координат • Настройка освещения • Наложение цвета на материал Шейдеры, предназначенные для выполнения на этом процессоре, называются вершинными
Входные и выходные данные вершинного процессора Компьютерная графика. Лекция 7 Встроенные переменные атрибутов: gl_Color, gl_Normal, gl_Vertex, gl_MultiTexCoord0и др. Определенные пользователем переменные атрибутов: StartColor, Velocity, Elevation, Tangentи т.п. Определенные пользователем uniform-переменые: Time, EyePosition, LightPositionи т.п. Встроенные uniform-переменые: gl_ModelViewMatrix, gl_FrontMaterial, gl_LightSource[0..n], gl_Fogи т.п. Вершинный процессор Карты текстур Встроенные varying-переменные: gl_FrontColor, gl_BackColor, gl_FogFragCoordи др. Специальные выходные переменные: gl_Position, gl_PointSize, gl_ClipVertex Определенные пользователем varying-переменные: Normal, ModelCoord, RefractionIndex, Density и т.п.
квалификаторы типов Компьютерная графика. Лекция 7 • Для управления входными и выходными данными вершинного шейдера используются квалификаторы типов, определенные как часть языка шейдеров OpenGL: • Переменные-атрибуты (attribute) • Однообразные переменные (uniform) • Разнообразные переменные (varying)
Attribute-переменные вершинного шейдера Компьютерная графика. Лекция 7 • Представляют собой данные, передаваемые вершинному шейдеру от приложения • Могут задавать значения атрибутов либо между glBegin()/glEnd(), либо при помощи функций, работающих с вершинными массивами • OpenGL поддерживает как встроенные, так и определенные пользователем attribute-переменные • gl_Normal, gl_Vertex, gl_Color
Uniform-переменные Компьютерная графика. Лекция 7 • Используются для передачи редко изменяемых данных как вершинному, так и фрагментному шейдеру • Uniform-переменные не могут задаваться между вызовами glBegin() и glEnd() • OpenGL поддерживает как встроенные, так и определенные пользователем uniform-переменные • Для передачи значения uniform-переменной приложение должно сначала определить расположение данной переменной (индекс) по имени
Varying-переменные Компьютерная графика. Лекция 7 • Данные в varying-переменных передаются из вершинного шейдера в фрагментный • Бывают как встроенными, так и определенными пользователем • Для каждой вершины значение соответствующей varying-переменной будет своим • В процессе растеризации происходит интерполяция значений varying-переменных с учетом перспективы
Фрагментный процессор Компьютерная графика. Лекция 7 • Это программируемый модуль, выполняющий операции над фрагментами и другими связанными с ними данными • ФП выполняет следующие стандартные операции: • Операции над интерполируемыми значениями • Доступ к текстурам • Наложение текстур • Создание эффекта тумана • Смешивание цветов Шейдеры, предназначенные для выполнения на этом процессоре, называются фрагментными
Входные и выходные данные фрагментного процессора Встроенные varying-переменные: gl_Color, gl_SecondaryColor, gl_TexCoord[0..n], gl_FogFragCoord Специальные входные переменные: gl_FragCoord gl_FrontFacing Определенные пользователем varying-переменные: Normal, ModelCoord, RefractionIndex, Density и т.п. Определенные пользователем uniform-переменные: ModelScaleFactor, AnimationPhase, WeightingFactorи т.п. Фрагментный процессор Карты текстур Встроенные uniform-переменые: gl_ModelViewMatrix, gl_FrontMaterial, gl_LightSource[0..n], gl_Fogи т.п. Специальные выходные переменные: gl_FragColor gl_FragDepth
Фрагментный процессор не заменяет следующие операции: Компьютерная графика. Лекция 7 • Покрытие • Проверка на видимость • Отсечение по прямоугольнику (scissors test) • Тест трафарета • Тест прозрачности • Тест глубины • Отсечение по трафарету • Смешивание цветов • Логические операции • Dithering • Определение видимости плоскостей
Входные данные фрагментного процессора Компьютерная графика. Лекция 7 • Встроенные varying-переменные • Определенные разработчиком varying-переменные • Имена и типы должны совпадать с именами varying-переменных, определенных в вершинном шейдере • Встроенные uniform-переменные • Определенные разработчиком uniform-переменные
Цели, преследуемые языком шейдеровOpenGL Компьютерная графика. Лекция 7 • Обеспечение хорошей совместимости с OpenGL • Использование гибкости графических ускорителей ближайшего будущего • Предоставление независимости от графического ускорителя • Увеличение производительности • Легкость использования • Обеспечение актуальности языка в будущем • Невмешательство в более высокие уровни параллельной обработки • Легкость разработки программ
Совместимость с OpenGL Компьютерная графика. Лекция 7 • Язык GLSL разработан для использования совместно с OpenGL • Предоставляются программируемые альтернативы стандартной функциональности OpenGL • Язык и программируемые им процессоры имеют как минимум ту же функциональность, какую они заменяют • Доступ к текущим состояниям OpenGL
Использование гибкости акселераторов ближайшего будущего Компьютерная графика. Лекция 7 • Язык предоставляет необходимый уровень абстракции для данной предметной области • Поддержка большого количества операций над скалярными и векторными величинами • Исчезла необходимость развитие частичных расширений функциональности OpenGL
Независимость от графического ускорителя Компьютерная графика. Лекция 7 • Предшествующие расширения закончились созданием интерфейсов на языке ассемблера • Ухудшает переносимость программ • Высокоуровневой язык обеспечивает уровень абстракции, достаточный для переносимости • Производители ускорителей используют гибкость языка для внедрения новейших архитектур и технологий компиляции
Увеличение производительности Компьютерная графика. Лекция 7 • Современные компиляторы высокоуровневых языков генерируют код, практически не уступающий по производительности вручную написанному коду • Высокоуровневой код может с легкостью компилироваться в более компактный и быстрый код, учитывающий возможности современных графических процессоров • Для кода на языке ассемблера может потребоваться переписывание кода
Легкость использования Компьютерная графика. Лекция 7 • Легкость освоения языка программистами, знакомыми с Си и Си++ • Язык для программируемых процессоров (в т.ч. и будущих) должен быть один и очень простой
Актуальность языка в будущем Компьютерная графика. Лекция 7 • При разработке GLSL были приняты во внимание особенности ранее созданных языков, таких как C и RenderMan • Язык тщательно стандартизован • Ожидается, что ранее написанные программы будут актуальны и через 10 лет
Невмешательство в более высокие уровни параллельной обработки Компьютерная графика. Лекция 7 • Современные графические ускорители выполняют параллельную обработку вершин и фрагментов • Язык проектировался с учетом возможного распараллеливания обработки на более высоких уровнях
Легкость разработки программ Компьютерная графика. Лекция 7 • Язык шейдеров GLSL не поддерживает указатели и ссылки, параметры передаются по значению • Нет проблемы с алиасингом • Облегчается работа оптимизирующего компилятора
Связь с языком C Компьютерная графика. Лекция 7 • Точка входа в шейдерную программу – функция void main(),с кодом внутри фигурных скобок • Константы, идентификаторы, операторы, выражения и предложения имеют много общего с языком C • Циклы, ветвление, вызовы функций также аналогичны с языком C • Многострочные комментарии
Дополнение к языку C Компьютерная графика. Лекция 7 • Векторные типы данных для чисел с плавающей запятой, целых и булевых значений • 2-х, 3-х и 4-х мерные векторы • Матричные типы данных для чисел с плавающей запятой • Матрицы 2x2, 3x3 и 4x4 • Дискретизаторы (sampler-ы) для доступа к текстурам • Спецификаторы attribute, uniform и varying входных и выходных переменных • Встроенные переменные состояния OpenGL • Начинаются с префикса gl_- gl_FragColor, gl_Position • Множество встроенных функций
Дополненияк языку из C++ Компьютерная графика. Лекция 7 • Перегрузка функций • Конструкторы • Объявление переменных в произвольном месте программы, а не только в начале блока • Тип bool • Однострочные комментарии • Функции должны быть объявлены до их первого использования одним из следующих способов • Определением тела функции • Объявлением прототипа
Не поддерживаемые возможности C Компьютерная графика. Лекция 7 • Отсутствие неявного приведения типов • 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; }
Загрузка, компиляция и компоновка шейдерных программ
Модель подготовки OpenGL-шейдеров Компьютерная графика. Лекция 7 Приложение Исходный код шейдера OpenGL API Компилятор Объектный код шейдера Компоновщик Объектный код программы Графический ускоритель
Шаг 1 – создание шейдерного объекта Компьютерная графика. Лекция 7 • Для начала необходимо создать шейдерный объект (структура данных драйвера OpenGL для работы с шейдером) • Для создания шейдерного объекта служит функция glCreateShaderObjectARB • Возвращенный данной функцией объект имеет тип GLhandleARBи используется приложением для дальнейшей работы с шейдерным объектом
Пример создания шейдера Компьютерная графика. Лекция 7 // создание вершинного шейдера GLhandleARBvertexShader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); // создание фрагментного шейдера GLhandleARBfragmentShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
Шаг 2 – загрузка исходного кода шейдера в шейдерный объект Компьютерная графика. Лекция 7 • Исходный код шейдера – массив строк, состоящих из символов • Каждая строка может состоять из нескольких обычных строк, разделенных символом конца строки • Для передачи исходного кода приложение должно передать массив строк в OpenGL при помощи glShaderSourceARB
Пример загрузки исходного кода в шейдерный объект Компьютерная графика. Лекция 7 constGLcharARB shaderSource1[] = “исходный код шейдера - начало”; constGLcharARB shaderSource2[] = “исходный код шейдера - окончание”; GLcharARBconst * shaderSources[] = { shaderSource1, shaderSource2 }; glShaderSourceARB(vertexShader, 2, shaderSources, NULL); В случае, когда исходный код находится в одной строке, задача слегка упрощается: const GLcharARB shaderSource1[] = “исходный код шейдера - начало”; const GLcharARB** pShaderSource = &shaderSource; glShaderSourceARB(vertexShader, 1, pShaderSource, NULL);