Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
OpenGL ES 1и2.docx
Скачиваний:
8
Добавлен:
01.07.2025
Размер:
4.8 Mб
Скачать

1.4 OpenGl es 1. Освещение и материалы

Освещение очень важно для правильного отображения трёхмерных объектов. Например, без освещения сфера будет выглядеть как круг, а цилиндр как прямоугольник. Чтобы использовать освещение нужно обязательно включить его командой glEnable(GL10.GL_LIGHTING), иначе все источники света будут игнорированы. В OpenGL ES допускается одновременно использовать восемь источников света, которые пронумерованы специальными параметрами состояния GL10.GL_LIGHT0, GL10.GL_LIGHT1, GL10.GL_LIGHT2, и.т.д. до GL10.GL_LIGHT7. Чтобы включить источник света нужно вызвать команду glEnable(номер источника света). Например, чтобы включить первый источник света вводим glEnable(GL10.GL_LIGHT1). По умолчанию включен источник света GL10.GL_LIGHT0. Аналогично можно выключить источник света командой glDisable(номер источника света). Каждый источник света имеет свои атрибуты, которые настраиваются независимо от других источников.

Важнейшим из атрибутов источника являются его координаты в пространстве, которые устанавливаются следующей командой:

gl.glLightfv(номер источника, GL10.GL_POSITION, буфер координат источника);

Продемонстрируем это на примере. Например, нам требуется установить источник c номером  GL10.GL_LIGHT0 в точку с координатами X=1, Y=1, Z=1. Сначала подготовим буфер для координат источника света длиной в 16 байт:

ByteBuffer bb = ByteBuffer.allocateDirect(16); bb.order(ByteOrder.nativeOrder()); positionlightBuffer = bb.asFloatBuffer();

Почему 16 байт ? Для источника света достаточно трёх координат, каждая из которых занимает 4 байта. Однако, у источника света есть четвертая координата W, которую мы рассматривать не будем и примем равной нулю. Далее создаём массив с координатами и записываем его в буфер:

float [] positionlightArray={1,1,1};

positionlightBuffer.position(0); positionlightBuffer.put(positionlightArray); positionlightBuffer.position(0);

Буфер координат источника света передаем в OpenGL:

gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, positionlightBuffer);

Свет, излучаемый источником, содержит в себе три составляющие - фоновую(ambient), рассеянную(diffuse), зеркальную(specular). 

Фоновая составляющая освещает трёхмерные объекты одинаково со всех сторон. Фоновый свет отражается во все стороны с одинаковой интенсивностью. Яркость фонового излучения не зависит от ориентации освещаемой поверхности и не зависит от положения глаза наблюдателя и как следствие, одинакова для всех поверхностей.

Рассеянный свет, падая на поверхность, отражается от неё во всех направлениях. Яркость отраженного рассеянного света зависит от ориентации поверхности по отношению к источнику света. В зависимости от направления нормали поверхность может казаться более или менее яркой. Однако, яркость рассеянного света не зависит от положения глаза наблюдателя, т.к. отражение рассеянной составляющей происходит с одинаковой интенсивностью во все стороны.

Зеркальная составляющая отражается от поверхности преимущественно в одном направлении, которое определяется законом отражения. Поэтому её яркость зависит как от ориентации поверхности по отношению к источнику света, так и от положения глаза наблюдателя. 

Для каждой составляющей света задаются отдельно четыре компоненты: красная, зелёная, синяя и альфа. Каждая компонента спектра может иметь собственную яркость. Спектральные компоненты источника света передаются в OpenGL при помощи команды:

gl.glLightfv(номер источника света, составляющая света, буфер цветов);

Приведу пример:

// Создадим массивы и буферы для хранения цветов источника света // Запишем спектральные компоненты в буферы

// цвета фоновой составляющей света float [] ambientlightArray={0.5f, 0.5f, 0.5f, 1}; FloatBuffer ambientlightBuffer; ByteBuffer b1 = ByteBuffer.allocateDirect(16); b1.order(ByteOrder.nativeOrder()); ambientlightBuffer = b1.asFloatBuffer(); ambientlightBuffer.position(0); ambientlightBuffer.put(ambientlightArray); ambientlightBuffer.position(0);

// цвета рассеянной составляющей света float [] diffuselightArray={0.8f, 0.8f, 0.8f, 1}; FloatBuffer diffuselightBuffer; ByteBuffer b2 = ByteBuffer.allocateDirect(16); b2.order(ByteOrder.nativeOrder()); diffuselightBuffer = b2.asFloatBuffer(); diffuselightBuffer.position(0); diffuselightBuffer.put(diffuselightArray); diffuselightBuffer.position(0);

// цвета зеркальной составляющей света float [] specularlightArray={0.8f, 0.8f, 0.8f, 1}; FloatBuffer specularlightBuffer; 

ByteBuffer b3 = ByteBuffer.allocateDirect(4 * 4); b3.order(ByteOrder.nativeOrder()); specularlightBuffer = b3.asFloatBuffer(); specularlightBuffer.position(0); specularlightBuffer.put(specularlightArray); specularlightBuffer.position(0); 

Теперь передадим цвета в OpenGL:

// цвета фоновой составляющей света

gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, ambientlightBuffer);

// цвета рассеянной составляющей света  gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, diffuselightBuffer);

// цвета зеркальной составляющей света  gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPECULAR, specularlightBuffer);

Цвета источника света установлены. Их нужно рассматривать как способность источника света излучать фоновую, рассеянную и зеркальную составляющую света какой-либо цветовой гаммы. Способность отражать ту или иную составляющую света относится к свойствам материала, из которого сделана поверхность. Способность излучать и способность отражать разные свойства. Например, источник света может излучать рассеянную составляющую зеленого цвета с максимальной яркостью, равной 1. Однако, поверхность может быть сделана из такого материала, который вообще не отражает зелёный цвет. В этом случае, зелёный цвет не дойдёт до нашего глаза. Поэтому в OpenGL вводится понятие материала и задаются ряд его свойств связанных с отражением света, которые аналогичны свойствам источника света. Задаются они командой glMaterialfv. Формат команды такой:

gl.glMaterialfv(освещаемая поверхность, составляющая света, буфер);

Первый параметр  принимает следующие значения:

GL10.GL_FRONT_AND_BACK - команда применяется для обратной и лицевой стороны поверхности,

GL10.GL_FRONT - команда применяется только для лицевой стороны поверхности,

GL10.GL_BACK -  команда применяется только для обратной стороны поверхности.

Второй параметр определяет составляющую света:

GL10.GL_AMBIENT - команда применяется для отраженного поверхностью фонового света,

GL10.GL_DIFFUSE - команда применяется для отраженного поверхностью рассеянного света,

GL10.GL_SPECULAR - команда применяется для отраженного поверхностью зеркального света.

Третий параметр - это буфер в котором содержатся компоненты цветовой гаммы, т.е.яркость красной, зелёной и синей компоненты отраженного света, а также альфа-компонента, т.е степень непрозрачности материала.  Применение команды glMaterialfv покажу на примере: // массивы для хранения цветов материала // цвета фонового освещения float [] ambientmaterial={0.2f, 0.2f, 0.2f, 1f}; // цвета рассеянного света float [] diffusematerial={0.8f, 0.8f, 0.8f, 1f}; // цвета зеркального света float [] specularmaterial={0.5f, 0.5f, 0.5f,1f};

// соответствующие им буферы цветов материала private FloatBuffer ambientmaterialBuffer,diffusematerialBuffer,specularmaterialBuffer;

ByteBuffer b1 = ByteBuffer.allocateDirect(16); b1.order(ByteOrder.nativeOrder()); ambientmaterialBuffer = b1.asFloatBuffer(); ambientmaterialBuffer.put(ambientmaterial); ambientmaterialBuffer.position(0);

ByteBuffer b2 = ByteBuffer.allocateDirect(16); b2.order(ByteOrder.nativeOrder()); diffusematerialBuffer = b2.asFloatBuffer(); diffusematerialBuffer.put(diffusematerial); diffusematerialBuffer.position(0); ByteBuffer b3 = ByteBuffer.allocateDirect(16); b3.order(ByteOrder.nativeOrder()); specularmaterialBuffer = b3.asFloatBuffer(); specularmaterialBuffer.put(specularmaterial); specularmaterialBuffer.position(0); // передаем данные о цветах материала в OpenGL gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, ambientmaterialBuffer); gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, diffusematerialBuffer); gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_SPECULAR, specularmaterialBuffer);

С зеркальной составляющей тесно связано понятие блеска. Чем больше блеск, тем меньше размер отраженного "зайчика" и тем больше его яркость. Показатель блеска может меняться от 0 до 128. Блеск действует только на зеркальную составляющую и управляется командой:

gl.glMaterialf(GL10.GL_FRONT_AND_BACK, GL10.GL_SHININESS, shine);

где shine - число от 1 до 128.

Если включено освещение собственные цвета вершин игнорируются. Чтобы в режиме освещения включить цвета вершин нужно выполнить команду:

gl.glEnable(GL10.GL_COLOR_MATERIAL);

Однако, при этом исчезнет эффект освещения. Совмещение собственных цветов вершин и цветов отраженного материалом света в OpenGL ES не выполняется. Если нужно вернуться от отображения цветов вершин в режим освещения выполняем команду:

gl.glDisable(GL10.GL_COLOR_MATERIAL);

Мы можем выбрать модель освещения, при которой освещена будет только лицевая сторона полигона, либо другую модель, в которой освещены обе стороны - лицевая и обратная. Установка модели производится командами:

// освещаются обе стороны полигона gl.glLightModelx(GL10.GL_LIGHT_MODEL_TWO_SIDE, GL10.GL_TRUE); // освещается только лицевая сторона gl.glLightModelx(GL10.GL_LIGHT_MODEL_TWO_SIDE, GL10.GL_FALSE);

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]