Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Глава 36. Шейдеры GLSL. Использование Без компонентов. Самый примитивный шейдерСодержание книги
Поиск на нашем сайте
Все шейдеры в этой главе соответствуют стандартам GLSL 1.00 — 1.20. Это важно.
Сейчас мы сделаем, пожалуй, самый примитивный шейдер — покрасим сферу в красный цвет. Итак, приступим. Поместите на форму GLScene1 (инспектор объектов сцены), GLSceneViewer. В инспекторе объектов создайте камеру, ее свойству Position.Z присвойте 2; свойству GLSceneViewer. Camera присвойте GLCamera. Также в инспекторе объектов создайте GLDirectOpenGL. Последний нужен, поскольку мы будем использовать прямой доступ к OpenGL. Подключите модуль GLContext, иначе компилятор не будет знать о TGLProgramHandle. Так как мы будем тестировать шейдер на сфере, подключите модуль GLObjects. Также нужно подключить OpenGLTokens. Теперь объявите в программе две константы для хранения вершинного (_vp) и фрагментного (_fp) шейдера. Сейчас оба текста мы поместим в код программы для облегчения редактирования. Но учтите, часто их помещают в виде отдельных файлов. const _vp = ‘void main(void)’+ ‘{‘+ ‘gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;’+ ‘}’; Тут требуется пояснение касательно кода шейдеров вообще. В коде шейдера обязательно должна быть функция main(). Это касается всех типов шейдеров. Так же пользователь может объявлять свои функции. Слово void, стоящее в скобках, означает, что эта функция ничего не принимает, перед именем функции — ничего не возвращает (т.е. процедура). float MyMain(float value) { return clamp(value, 0.0, 1.0); }; Возвращаемся к нашему простому шейдеру. Прежде, чем мы сможем работать с вершинами, нам необходимо их трансформировать с учётом глобальной (мировой) матрицы. Это и выполняется командой gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;. По сути, эта команда должна присутствовать во всех вершинных шейдерах, хотя вместо неё иногда можно увидеть и устаревшую запись gl_Position = ftransform(). Ей пользоваться мы не рекомендуем, а при использовании в шейдерах с версией выше 1.20 вообще можно получить ошибку от драйвера. const _fp = ‘void main(void)’+ ‘{‘+ ‘gl_FragColor = vec4(1.0, 0.0, 0.1, 1.0);’+ ‘}’; vec4 — это вектор, состоящий из 4-х компонентов — x,y,z,w. Есть еще vec3 и vec2. Ещё всегда помните, что GLSL различает маленькие и большие буквы.
Иногда программисты задают версию шейдерной программы через зарезервированное в GLSL слово; вот как мы укажем, что будем использовать версию 1.10: ‘#version 110 ‘+#10#13+ ‘void main(void){‘+ … Обритите внимание, что в шейдерной программе версия указывается без точки. Разные версии имеют некоторые отличия и ограничения по железу. Но об этом вы прочитаете много позже. Команда GL_FragColor задаёт цвет пикселя в цветовом буфере (единственном). Возможно, при знакомстве с сложными шейдерами вы не увидите это слово, но встретите вместо него GL_FragData[]. В таком случае это будет называться Multiple Render Targets. Нельзя одновременная работать с gl_FragColor и glFragData. Подробнее о MRT можете потом почитать здесь: steps3d.narod.ru/tutorials/mrt-tutorial.html. Возвращаемся в Delphi. Объявите глобальную переменную GLSLHandle типа TGLProgramHandle. Она нужна для управления шейдером. Также создадим экземпляр сферы: GLSphere: TGLSphere. Создайте у формы событие OnCreate и запишите в нем GLSphere:=TGLSphere.Create(nil); Читатель меня не простит, если я не расскажу, почему в скобках написано nil, а не GLScene1.Objects и почему мы используем Create, а не CreateAsChild. Дело в том, что инспектор объектов сцены, в который мы наш объект заботливо не поместили, визуализирует свои объекты когда ему и только ему захочется; нам же нужно визуализировать сферу именно после команды UseProgramObject и именно перед EndUseProgramObject. Поэтому мы и не воспользовались инспектором, чтобы не рендить объект дважды. Пришло время задействовать GLDirectOpenGL. Мы будем практиковать нашу очень интересную находку: будем иметь для этого компонента два варианта события OnRender. Первое событие будет называться GLDirectOpenGLInit; второе GLDirectOpenGLRender. Откройте инспеткор объектов сцены, выберите там GLDirectOpenGL; перейдите на вкладку Events; щёлкнув дважды в инспекторе объектов напротив текста OnRender вы создадите второе событие GLDirectOpenGLRender. Теперь создайте первое событие: перейдите в окно редактора кода и в месте объявления формы пропишите рядом с объявлением GLDirectOpenGLRender точно такую же по параметрам процедуру GLDirectOpenGLInit: procedure GLDirectOpenGLRender(Sender: TObject; var rci: TRenderContextInfo); procedure GLDirectOpenGLInit(Sender: TObject; var rci: TRenderContextInfo); Теперь поместите в программу пустое «тело», как говорят, процедуры GLDirectOpenGLInit. В итоге у вас должно получиться:
procedure TForm1.GLDirectOpenGLInit(Sender: TObject; var rci: TRenderContextInfo); begin
end;
procedure TForm1.GLDirectOpenGLRender(Sender: TObject; var rci: TRenderContextInfo); begin
end; В GLDirectOpenGLInit будем проводить всё, что касается инициализации шейдеров, а именно: // Будем проверять поддержку необходимых расширений. Эти // расширения есть даже на весьма старых компьютерах. 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); Gl.CheckError; // Инициализация закончена, пришло время перейти // к рендингу объекта с шейдером. GLDirectOpenGL.OnRender:=GLDirectOpenGLRender; // Без этой строчки рендинг объекта всё-таки наступит, но только если // на форме есть каденсер и в нём записано GLSceneViewer.Invalidate, // или если опустить форму за край экрана и вытащить обратно. GLDirectOpenGL.BuildList(rci);
Теперь назначьте данное событие как текущее событие OnRender компонента GLDirectOpenGL, прописав в FormCreate: GLDirectOpenGL.OnRender:=GLDirectOpenGLInit; или сделав то же самое в design time. Теперь зададим GLDirectOpenGLRender, где будет проходить применение шейдера к объекту — самая интересная часть: procedure TForm1.GLDirectOpenGLRender(Sender: TObject; var rci: TRenderContextInfo); begin with GLSLHandle do begin UseProgramObject; MySphere.Render(rci); EndUseProgramObject; end; end; Описание вызываемых тут команд потом посмотрите внизу главы. Я лишь скажу, что если вам понадобится когда-нибудь потом использовать шейдер не только для MySphere, но и для каких-то других объектов, вызовите их метод Render рядом с таким же методом MySphere. Например: with GLSLHandle do begin UseProgramObject; MySphere.Render(rci); MyCube.Render(rci); MyFreeForm.Render(rci); EndUseProgramObject; end; Построение примера закончено. Ну, собственно и всё. Запускайте проект и смотрите на работу самого примитивного GLSL шейдера. Думаю, вас удивило то, что шар превратился в круг. Всё дело в том, что чтобы вернуть шару «шарообразный» вид, нужно учитывать освещение, что у нас не делается. Но в этой главе делать мы этого и не будем — этому посвящена другая глава. Небольшое замечание — вы можете иметь столько программ-шейдеров, прилинкованных и готовых к употреблению, сколько хотите, но не больше чем это позволяет GPU. Обычно это очень большое число. Разберём использованные свойства класса TGLProgramHandle.
Многие программисты после курса изучение шейдеров с лёгкостью могут использовать в своих проектах уже написанные кем-то другим шейдеры. Да, такие люди имеют о шейдерах представления, но они так их и не освоили. Они берут шейдерную программу и вставляют её методом «copy-past». Я очень надеюсь, что уважаемый читатель был внимателен к самому языку шейдеров, а не только к тому, как же этот шейдер вставить в программу. После прочтения ещё пары глав по GLSL его ждёт задание по написанию шейдера.
Готовый пример берите здесь: http://www.glscene.ru/download.php?view.545
|
||||||||||||||||||||
Последнее изменение этой страницы: 2016-04-19; просмотров: 534; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.118.253.171 (0.008 с.) |