OpenGL ES 1. Как наложить несколько текстур на один полигон
Иногда бывает необходимо нанести последовательно несколько текстур на один полигон в виде слоёв с регулируемой прозрачностью. Делается это с помощью смешивания цветов различных текстур. Для решения этой задачи нужно определить несколько материалов с различным значением альфа компоненты отраженного света и загрузить в память несколько текстур. Рассмотрим пример. Предположим, у нас загружены в память три текстуры с именами name1, name2, name3. Изображение первой текстуры представляет из себя красные вертикальные полосы, второй-зелёные горизонтальные полосы, а третьей - синий круг.
Определим три материала для текстурирования. Первый материал сделаем непрозрачным с альфа-компонентой диффузного света = 1. Подготовим буфер для этого материала: ByteBuffer b1 = ByteBuffer.allocateDirect(16);
Аналогично зададим ещё два полупрозрачных материала с альфа=0.5: ByteBuffer b2 = ByteBuffer.allocateDirect(16); ByteBuffer b3 = ByteBuffer.allocateDirect(16); Текстуры будем наносить текстуры на квадрат, лежащий в плоскости Z=-3 и имеющий координаты угловых точек A (x=-1,y=-1), B (x=1,y=-1), C(x=1,y=1), D(-1,1):
Порядок обхода вершин квадрата выберем от точки A до точки D против часовой стрелки, т.е. A-B-C-D. Заполним буфер координат вершин, соответствующий правилу обхода: ByteBuffer b4 = ByteBuffer.allocateDirect(48); Вспомним, что направления осей S и T текстурных координат отсчитываются от левого верхнего угла картинки текстуры. Заполним буфер координат текстур по выбранному правилу обхода: ByteBuffer b5 = ByteBuffer.allocateDirect(32); // разрешим использовать освещение // по умолчанию он находится в начале координат // разрешим использование двумерных текстур // для регулировки прозрачности с помощью альфа-компоненты // включаем использование массивов (буферов) координат вершин // включаем использование массивов (буферов) координат текстур gl.glTexCoordPointer(2,GL10.GL_FLOAT,0,texcoordBuffer);
Нарисуем наш квадрат три раза. Сначала включим диффузный свет первого материала: gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, diffusematerialBuffer1); Затем сделаем активной первую текстуру (вертикальные красные полосы): gl.glBindTexture(GL10.GL_TEXTURE_2D, name1); gl.glDrawArrays(GL10.GL_TRIANGLE_FAN,0,4); Повторим процедуру для второго материала и второй текстуры (горизонтальные зелёные полосы): gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, diffusematerialBuffer2);
Получим такое изображение: Теперь нарисуем поверх этой картинки третью текстуру (синий круг) с использованием третьего материала: gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, Результат будет такой: Интенсивность каждой текстуры можно регулировать путем изменения альфа-компоненты соответствующего материала. Для примера, уменьшим альфа-компоненту второго материала с 0.5 до 0.2, т.е. сделаем второй слой более прозрачным: diffusematerialArray2={0.8f, 0.8f, 0.8f, 0.2f}; При этом яркость второй текстуры, содержащей зелёные полосы заметно уменьшится:
Главным преимуществом данного подхода является его простота и гибкость, позволяющая наложить на один полигон сколько угодно текстур. Заметьте, что мы просто выполняем несколько раз рисование одного и того же полигона переключаясь между текстурами и материалами. При этом не требуется многократная загрузка координат вершин и текстур в буферы и повторная передача их в OpenGL командами glVertexPointer и glTexCoordPointer. Существует другая, более сложная для понимания, техника наложения нескольких текстур на один полигон и называется она "мультитекстура". Она позволяет отобразить множество текстур на одном полигоне за один цикл рисования, т.е. за один вызов команды glDrawArrays. Однако, по сравнению с одиночной текстурой, мультитекстура занимает в несколько раз больше видеопамяти. Кроме того, эффект освещения при использовании мультитекстуры значительно ослабевает. На практике я применял обе техники на поверхности, состоящей из нескольких тысяч вершин, и не заметил заметного преимущества мультитекстуры в части скорости рендинга. Поэтому мультитекстура здесь рассматриваться не будет.
|