Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Глава 37. Шейдеры GLSL. ТекстурированиеСодержание книги
Поиск на нашем сайте
Все шейдеры в этой главе соответствуют стандартам GLSL 1.00 — 1.20.
Сначала немного поговорим о спецификации GLSL. Она такова, что работает только с текстурными координатами в пределах от 0 до 1. Рассмотрим вышесказанное на примере. Допустим, у нас есть текстура размером 1024/512. И на этой текстуре есть точка с координатами (300, 120). Тогда её текстурные координаты по формуле будут равны: x = 300/1024 = 0.29296875 y = 120/512 = 0.234375 Соответственно, если подставить сюда координаты левого угла, то получится 0/1024 = 0, если поставить координаты правого угла, то будет 1024/1024 = 1. То есть все координаты ложатся в диапазон от 0 до 1. Эта процедура называется нормализацией. Если мы запишем 0.16 или 1123.16, то это будет указывать на одну и ту же точку. Почему? Как было только что написано, текстурные координаты могут находиться только в интервале от 0 до 1, а число 1213234.16 выходит из этого интервала. Поэтому GPU (видеокарта) при расчете координат выполняет операцию x = fract(x), т.е. отсекает целую часть числа. Стоит отметить, что на самом деле расчёт координат производится на всех видеокартах по-разному. Но результат всё равно получается схожим с тем, что получается при использовании fract. А теперь что-нибудь затекстурируем. Подключите модуль GLContext, иначе компилятор не будет знать о TGLProgramHandle. Поскольку наш шейдер опять будет применяться к сфере, подключите к проекту GLObjects; так же нужно подключить OpenGL1x. Поместите на форму GLScene1 (инспектор объектов сцены), GLSceneViewer. В инспекторе объектов создайте камеру, ее Position.Z присвойте значение 2; свойству GLSceneViewer. Camera присвойте GLCamera. Также в инспекторе объектов создайте GLDirectOpenGL. Для того, чтобы увидеть результат действия шейдера, объявим MySphere:TGLSphere; Теперь самое главное для шейдерного текстурирования. Почти у всех визуальных объектов есть свойство Material.TextureEx. Мы уже рассказывали вам про него, вот что говорилось: «Это контейнер для дополнительных текстур, текстур, которые можно использовать как альфу, как текстуру деталей и т.п.» Вот и пришло время использовать этот контейнер. Создайте в нём один материал, в который мы будем загружать текстуру. Делать это будем в FormCreate, вот и код: procedure TForm1.FormCreate(Sender: TObject); begin MySphere:=TGLSphere.Create(nil); //Сначала нужно создать объект. MySphere.Material.TextureEx.Add; MySphere.Material.TextureEx.Items[0].Texture.Image.LoadFromFile(‘Texture.jpg’); MySphere.Material.TextureEx.Items[0].Texture.Disabled:=False; end;
Теперь объявите в программе две константы для хранения вершинного (_vp) и фрагментного (_fp) шейдеров. const _vp = ‘varying vec2 TexCoord;’+ ‘void main(void)’+ ‘{‘+ ‘gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;’+ ‘TexCoord = gl_MultiTexCoord0.xy;’+ ‘}’; Первая строка — gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex — нам уже знакома. Она производит трансформацию вершин с учётом мировой матрицы. А теперь разберёмся с TexCoord = gl_MultiTexCoord0.xy. Поскольку мы должны передать во фрагментный шейдер текстурные координаты текущей вершины (а сам фрагментный шейдер не может получить эту информацию), мы используем присваивание TexCoord = gl_MultiTexCoord0.xy. Индекс 0 отвечает за текстурную грань. Всего граней может быть 8. В начале вершинного шейдера мы объявили varying величину TexCoord. Тип varying означает, что к переменной будут иметь доступ и другие шейдеры (если там тоже объявлен TexCoord). Посмотрите на вторую строку фрагментного шейдера; поскольку мы также объявили там varying vec2 TexCoord, и этот шейдер сможет читать и перезаписывать переменную. После слова varying идёт задание типа переменной; у нас это вектор, который хранит x и y координаты. Третьим словом идёт имя переменной. texture2D(Tex, gl_TexCoord[0].xy): тут мы получаем из текстуры с именем «Tex» цвет точки с позицией gl_TexCoord[0].xy. x и y в конце вставлены так как в вершинном шейдере записывались только они. Теоретически, в вершинном шейдере мы можем записывать значение ещё и в z и w координат, но для двухмерных текстур это нам не нужно. сonst _fp = ‘uniform sampler2D Tex;’+ ‘varying vec2 TexCoord;’+ ‘void main (void)’+ ‘{‘+ ‘gl_FragColor = texture2D(Tex, TexCoord);’+ ‘}’; Здесь мы также использовали uniform переменную. Задание этой переменной начинается, как вы поняли, с зарезервированного слова uniform; второе слово задаёт тип; третье имя. Приложение через unifom передаёт шейдеру любые величины: текстуры, матрицы, структуры, вектора, int и float числа и т.д. Uniform-переменные могут быть прочитаны (но не перезаписаны) всеми шейдерами — вершинным, пиксельным и геометрическим. Также мы использовали специальный тип sampler2D для работы с текстурами. Возвращаемя в Delphi. Объявите переменную GLSLHandle типа TGLProgramHandle. Она нужна для управления шейдером. Как и в предыдущий раз, мы будем использовать два события OnRender у GLDirectOpenGL. Вот первое: procedure TForm1.GLDirectOpenGLInit(Sender: TObject; var rci: TRenderContextInfo); 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); GL.CheckError;
with GLSLHandle do begin UseProgramObject; Uniform1i[‘Tex’]:= 0; EndUseProgramObject; end; GLDirectOpenGL.OnRender:= GLDirectOpenGLRender; GLDirectOpenGL.BuildList(rci); end; Комментирую новое для вас. В строке Uniform1i[‘DirtTex’]:=0 мы указываем, что в шейдер, в переменную Tex, передается текстура с индексом 0, заданная в свойстве Material.TextureEx. Но перед тем как передать что-то в шейдерный объект, его нужно активировать (UseProgramObject), иначе OpenGL не будет знать куда передавать этот юниформ; после же передачи, шейдерный объект нужно деактивировать (EndUseProgramObject), чтобы не вызвать ошибок. А теперь моя любимая часть — использование шейдеров на объекте. Событие OnRender у GLDirectOpenGL и приведите к такому виду: procedure TForm1.GLDirectOpenGLRender(Sender: TObject; var rci: TRenderContextInfo); begin with GLSLHandle do begin UseProgramObject; MySphere.Render(rci); EndUseProgramObject; end; end;
Последний штрих — напишите в OnCreate формы GLDirectOpenGL.OnRender:=GLDirectOpenGLInit или сделайте то же самое в design time. В шейдер мы можем передавать разные данные, используя Uniform…. Ниже приведена таблица всех возможных свойств Uniform… и их значений.
Вот такой шарик получился с моей текстурой: Готовый пример берите здесь: http://narod.ru/...
|
||||||||||||||||||||||||||||||||
Последнее изменение этой страницы: 2016-04-19; просмотров: 425; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.22.248.100 (0.006 с.) |