В этой статье, основанной на предыдущем примере показано как сделать грани пирамиды полупрозрачными, рассмотрен вопрос о сортировке полигонов для правильного отображения эффекта прозрачности. Для этих целей будем использовать режим смешивания цветов при помощи альфа-компоненты цвета материла. Всего у цвета есть четыре компонента: красный, зеленый, синий и альфа. Яркость каждой компоненты изменяется в диапазоне от 0 до 1. Альфа компонент-это четвертый компонент цвета. Он определяет степень непрозрачности объекта.
В заголовке класса MyClassRenderer изменим строку:
private float [] diffusematerialArray={0.8f, 0.8f, 0.8f, 1};
на float [] diffusematerialArray={0.8f, 0.8f, 0.8f, 0.5f};
т.е. установим альфа-компоненту рассеянного цвета материала равной 0.5.
Кроме того нужно в метод onSurfaceCreated класса MyClassRenderer добавить следующие настройки:
// включаем модель освещения внешних и внутренних сторон gl.glLightModelx(GL10.GL_LIGHT_MODEL_TWO_SIDE, GL10.GL_TRUE);
// отключаем отсечение невидимых граней
gl.glDisable(GL10.GL_CULL_FACE);
// включаем альфа-компонент цвета
gl.glEnable(GL10.GL_ALPHA);
// включаем смешивание цветов
gl.glEnable(GL10.GL_BLEND);
// устанавливаем режим смешивания цветов
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
------------------------------------------------------------------------------------------------------------
Запустив программу на исполнение, убедимся что эффект прозрачности появляется и исчезает при вращении пирамиды. Это происходит потому, что мы рисуем полигоны, из которых состоит пирамида, в определенном порядке без учета их удаленности от глаза наблюдателя.
Поэтому нам нужно рисовать полигоны от дальнего к ближнему, чтобы эффект прозрачности не пропадал при повороте пирамиды. Займемся сортировкой полигонов в пирамиде. Поскольку полигоны представляют объекты разных классов Triangle и Quadr нам нужен метод, который сортирует объекты разных типов по определенному индексу. В Java таким методом является метод compareTo интерфейса Comparable. Создадим абстрактный класс Polygon, реализующий интерфейс Comparable.
------------------------------------------------------------------------------------------------------------
package com.blogspot.andmonahov.pyramid;
import javax.microedition.khronos.opengles.GL10;
public abstract class Polygon implements Comparable<Object> {
// поле полигона, по которому производится сортировка
public float indexsort;
// у каждого полигона он свой
public abstract void draw(GL10 gl);
// сортировка выполняется по убыванию значения indexsort
public int compareTo(Object obj) {
Polygon tmp = (Polygon)obj;
if(this.indexsort < tmp.indexsort){
return 1;
}
else if(this.indexsort > tmp.indexsort){
return -1;
}
return 0;
}
}
------------------------------------------------------------------------------------------------------------
Наследуем классы Triangle и Quadr от общего предка Polygon следующим образом:
public class Triangle extends Polygon {............
public class Quadr extends Polygon{............
При этом полигоны наследуют поле indexsort, по которому будет производиться сортировка в методе compareTo. Теперь нужно определить значение indexsort для полигонов внутри пирамиды. Таким полем будет расстояние от камеры до центра полигона. Поскольку поля для координат камеры xposition, yposition, position объявлены в классе MyClassRenderer как public static мы можем получить доступ к ним из любого класса, в т.ч. из класса пирамиды. Перепишем метод draw класса Pyramid:
------------------------------------------------------------------------------------------------------------
public void draw (GL10 gl){
// координаты вектора от камеры до центра полигона
float dy;
float dz;
for (int i=0; i<4; i++){
dx=MyClassRenderer.xposition-triangle[i].getxcenter();
dy=MyClassRenderer.yposition-triangle[i].getycenter();
dz=MyClassRenderer.zposition-triangle[i].getzcenter();
triangle[i].indexsort=dx*dx+dy*dy+dz*dz;
}
dx=MyClassRenderer.xposition-quadr.getxcenter();
dy=MyClassRenderer.yposition-quadr.getycenter();
dz=MyClassRenderer.zposition-quadr.getzcenter();
quadr.indexsort=dx*dx+dy*dy+dz*dz;
Polygon [] polygon =new Polygon[5];
for (int i=0; i<4; i++){
polygon[i]=triangle[i]; //записываем в массив полигонов треугольники
}
polygon[4]=quadr; // последний элемент массива-квадрат дна
Arrays.sort(polygon);
for (int i=0; i<5; i++){
polygon[i].draw(gl);
}
}
------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
Исходник можно скачать отсюда Ссылка
Исполняемый файл для телефона (apk) можно скачать отсюда Ссылка
Исполняемый файл для телефона (apk) можно скачать отсюда Ссылка
Здравствуйте, возник такой вопрос, написал приложение, на эмуляторе оно работает, на телефоне работает, но пирамиды без текстур, хотя прозрачные.
ОтветитьУдалитьРешил попробывать запустить ваше приложение по ссылке, но и оно так же плохо работает на телефоне. Подскажите, пожалуйста, в чем проблема, телефон jiayu g3 версия android 4.0.4
Переделайте размер текстур на степень двойки, т.е. 128х128, 256х256, 512х512, и.т.п.
УдалитьСкорее всего ваша видеокарта не поддерживает текстуры произвольного размера.
Попробывал как вы сказали, заработало на другом телефоне, на котором не работало до этого, но на моем все еще ни одна текстура не загружается, пробывал 64х64,128х128,256х256,512х512, 1024х 1024
УдалитьА другие программы с OpenGL ES на Вашем телефоне работают ?
УдалитьЯ правильно понимаю что большинство игр пишутся с ним? или нет? если да, то многие идут, пока не встречал не идущих, если нет, подскажите с помощью чего они пишутся. Или как можно по другому отобразить текстуры на экране
УдалитьПопробуйте изменить способ загрузки Bitmap в классе Texture
УдалитьВместо:
Bitmap bitmap =
BitmapFactory.decodeResource(context.getResources(), idpicture);
используйте такой код
InputStream is = context.getResources()
.openRawResource(idpicture);
Bitmap bitmap;
try {
bitmap = BitmapFactory.decodeStream(is);
} finally {
try {
is.close();
} catch(IOException e) {
}
}
Спасибо большое, подействовало, уроки действительно полезны, благодарен вам за ваш труд
Удалитьспасибо за уроки. все понятно и доходчиво.
ОтветитьУдалитьПодскажите пожалуйста как сделать чтобы прозрачной была не вся текстура, а только там где у самой текстуры альфа канал??
О, получилось сделать что бы альфа канал с текстуры работал в программе, если интересно скину код.
Удалитьдля загрузки альфа канала из текстуры применялся один из параметров texImage2D, но работает ли он на OpenGLES10 не знаю
ОтветитьУдалить