Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебник по GLScene.doc
Скачиваний:
255
Добавлен:
16.12.2018
Размер:
7.18 Mб
Скачать

Глава 36. Шейдеры glsl. Введение.

GLSL (The OpenGL Shading Language) - шейдерный язык OpenGL. GLSL основан на языке ANSI C. Большинство возможностей языка ANSI C сохранено, к ним добавлены векторные и матричные типы данных, часто применяющиеся при работе с трехмерной графикой. В отличие от HLSL/Cg язык создавался в расчете на будущее железо, поэтому теоретически он намного мощнее. В частности, GLSL много взял от RenderMan Shading Language.

Для программ на GLSL требуется поддержка следующих расширений:

  • GL_ARB_shader_objects;

  • GL_ARB_shading_language_100;

  • GL_ARB_vertex_shader;

  • GL_ARB_fragment_shader.

Следует отметить, что в OpenGL и, следовательно, в GLSL нет геометрических шейдеров.

Нижеследующие статьи посвящены использованию GLSL без каких-либо компонентов и с использованием компонента GLSLShader. Сейчас я попробую рассказать о плюсах обоих способов.

С GLSLShader.

1. Лёгкость в настройке параметров.

2. Лёгкость при работе с весьма малым количеством шейдеров.

Без GLSLShader.

1. Контролировать работу шейдера гораздо проще.

2. Вам не понадобится при каждом новом шейдере заводить на форме очередной компонент GLSLShader, что уменьшает рутину и экономит память.

3. Если вы используете много шейдеров, не придётся перебирать множество окон и искать, какой компонент за какой шейдер отвечает.

4. При использовании Turbo Delphi код модифицировать не придётся.

Частично материал последующих глав позаимствован отсюда: http://wingman.org.ru/glsl

Глава 37. Шейдеры glsl. Использование без компонентов. Самый примитивный шейдер.

Сейчас мы сделаем, пожалуй, самый примитивный шейдер. Мы покрасим сферу в красный цвет. Итак, приступим. Поместите на форму GLScene1 (инспектор объектов сцены), GLSceneViewer. В инспекторе объектов создайте камеру, свойству GLCamera.Position.Z присвойте значение 2; свойству GLSceneViewer.Camera присвойте GLCamera. Так же в инспекторе объектов создайте GLDirectOpenGL. Последний нужен, поскольку мы будем использовать прямой доступ к OpenGL. Для того чтобы увидеть результат действия шейдера, создадим сферу.

И подключите модуль GLContext, иначе компилятор не будет знать о TGLProgramHandle. Так же нужно подключить модуль OpenGL1x. Теперь объявите в программе две константы типа string для хранения вершинного (vp) и фрагментного (fp) шейдера. Учтите, что текст любого шейдера это всегда константа т.к. шейдер нельзя изменять в runtime. Сейчас оба текста мы поместим в код программы для облегчения редактирования. Но учтите, часто их помещают в виде отдельных файлов.

const _vp:string=

'void main(void){'+

'gl_Position = ftransform();'+

'}';

Прежде, чем мы сможем работать с вершинами нам необходимо их трансформировать с учётом глобальной (мировой) матрицы. Вот это и выполняется командой gl_Position = ftransform(). По сути, эта команда должна присутствовать во всех вершинных шейдерах, хотя вместо неё можно использовать более очевидную функцию: gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;. То есть перемножение матрицы вида на координаты текущей вершины.

_fp:string=

'void main(void){'+

'gl_FragColor = vec4(4,0,0.1,0);'+

'}';

vec4 - это вектор, состоящий из 4-х компонентов - x,y,z,w.

Тут требуется пояснение касательно кода шейдеров вообще.

В коде шейдера обязательно должна быть функция main(). Это касается всех типов шейдеров. Так же пользователь может объявлять свои функции. Ещё всегда помните, что GLSL различает маленькие и большие буквы.

В GLSL существует возможность рендинга сразу в несколько цветовых буферов – это называется Multiple Render Targets. Тогда в шейдерной программе вместо GL_FragColor пишется GL_FragData[]. Обратите внимание, что не допускается одновременная работа с gl_FragColor и glFragData. Подробнее о MRT можете прочитать здесь: http://steps3d.narod.ru/tutorials/mrt-tutorial.html.

Возвращаемся в Delphi. Объявите переменную glsl типа TGLProgramHandle. Она нужна для управления шейдером.

GLSLHandle:TGLProgramHandle;

И переменную для проверки успешности запуска. Значение задаётся в зависимости от результата инициализации шейдера и будет записано один раз, что избавит программу от лишних проверок и значительно повысит быстродействие.

InitDGL:boolean;

Теперь в событие OnRender объекта GLDirectOpenGL добавим сам код инициализации шейдера.

if not InitDGL=true then begin

if not(GL_ARB_shader_objects and GL_ARB_vertex_program and GL_ARB_vertex_shader and GL_ARB_fragment_shader)then begin

ShowMessage('Ваша видеокарта не поддерживает GLSL шейдеры!');

Halt;

end;

GLSLHandle:=TGLProgramHandle.CreateAndAllocate; GLSLHandle.AddShader(TGLVertexShaderHandle, _vp); //Добавляем вершинный шейдер

GLSLHandle.AddShader(TGLFragmentShaderHandle, _fp); //Добавляем фрагментный шейдер

{два оператора ниже – проверка, запущен ли шейдер}

if not GLSLHandle.LinkProgram then raise Exception.Create(GLSLHandle.InfoLog);

if not GLSLHandle.ValidateProgram then raise Exception.Create(GLSLHandle.InfoLog);

CheckOpenGLError;

InitDGL:=True;

end;

if InitDGL then

with GLSLHandle do begin

UseProgramObject;

GLSphere.Render(rci);

EndUseProgramObject;

end;

Небольшое замечание – вы можете иметь столько программ-шейдеров, прилинкованных и готовых к употреблению, сколько хотите, но не больше чем это позволяет GPU.

Разберём использованные свойства класса TGLProgramHandle и его потомка – класса GLSLHandle.

Свойство

Описание

CreateAndAllocate

Каждая программа хранится как дескриптор. А это свойство создаёт и распределяет дескриптор.

AddShader

Добавление шейдера. Первый параметр – тип шейдера. Может быть TGLVertexShaderHandle (вершинный шейдер) либо TGLFragmentShaderHandle (фрагментный шейдер), но никак иначе. Второй параметр – константа, содержащая текст шейдера.

LinkProgram

Линкует шейдер. Перед вызовом этого оператора шейдер уже должен быть откомпилирован.

ValidateProgram

Проверяет правильность программы шейдера.

InfoLog

Хранит информацию о последней произведённой операции. И по требованию выводит её. К сожалению, для сообщений InfoLog нет никакой спецификации, так что разные драйвера и видеокарты могут выдавать разный текст.

UseProgramObject

Функция для загрузки и использования шейдера.

EndUseProgramObject

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

Ну, собственно и всё. Запускайте проект и смотрите на работу самого примитивного GLSL шейдера. Внизу на картинке результат выполнения программы. Думаю, вас удивило то, что шар превратился в круг. Всё дело в том, что чтобы вернуть “шару” шарообразный вид, нужно учитывать освещение, что у нас не делается. Но в этой главе делать мы этого и не будем. Этому посвящена глава 33.