Программируемость, появившаяся с созданием языка шейдеров OpenGL, позволяет пользоваться текстурами более широко. Используя программируемые шейдеры, приложение может считывать значения с любого количества текстур к применять их как угодно. Можно работать по сложным алгоритмам, в которых результаты обращения к одной текстуре используются для определения параметров доступа к другой текстуре. Также можно хранить в текстурах промежуточные результаты рендеринга, использовать их как таблицы для поиска (представление сложных функций), для хранения нормалей, их отклонений, значений блеска, информации о видимости, полиномиальных коэффициентов и многих других данных. Делать это, конечно, не так легко, как работать с текстурами обычным способом, и такая гибкость обозначает также, что текстурные карты в некотором смысле уже являются памятью общего назначения, в которой можно хранить что угодно. (Фильтрация и наложение все еще отличают доступ к текстурной карте от доступа к обычной памяти.)
В этой главе описано несколько шейдеров, которые читают значения из текстурной памяти и используют их для формирования интересных эффектов. Начнем с разговора о том, как обратиться к текстуре из шейдера, а потом рассмотрим несколько примеров шейдеров, которые обращаются к текстурной памяти с целью не только наложения текстуры на трехмерный объект.
10.1. Обращение к текстуре из шейдера
Приложения должны правильно инициализировать текстуры перед выполнением шейдера, который работает е ними. Для инициализации текстуры приложение должно выполнить следующие действия.
1. Выбрать текстурный модуль и сделать его активным функцией gl Acti veTexture.
2. Создать текстурный объект и связать его с активным текстурным модулем функцией gl Bi ndTexture.
3. Установить различные параметры (наложение, фильтрация и т. д.) текстурного объекта функцией glTexParameter,
4. Определить текстуру функцией gl Тeximage.
При использовании стандартной функциональности OpenGL необходимы еще два дополнительных шага: разблокирование нужной текстуры, входящей в текстурный модуль, функцией gl Enabl е и установка текстурной функции для текстурного модуля (модулирование, шаблон, замена и т. д.) функцией glTexEnv. (Эти шаги не нужны для шейдера, так как блокирование/разблокирование текстур игнорируется, а текстурная функция содержится в самом коде шейдера.) Когда эти шаги выполнены, текстуру можно использовать в OpenGL-шейдере.
К текстурам можно обращаться из шейдера сразу же, как только состояние текстуры задано приложением. Для этого у языка шейдеров OpenGL есть встроенные типы данных (см. раздел 3.2.4) и встроенные функции (см. раздел 5.7).
Uniform-переменная типа sampler используется для обращения к текстуре из шейдера. Как структурная единица шейдера sampler считается закрытым типом данных, содержащим значение для обращения к конкретной текстуре. Шейдер должен объявить такую uniform-переменную для каждой текстуры, которая ему нужна. Приложение должно задать семплеру значение перед выполнением шейдера, как описано в разделе 7.8.