![]() Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь 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; просмотров: 440; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 52.15.183.154 (0.01 с.) |