Показаны сообщения с ярлыком шейдер. Показать все сообщения
Показаны сообщения с ярлыком шейдер. Показать все сообщения

21 февраля 2013 г.

OpenGL ES 2.0. Урок 5. Шейдер преломления света

В предыдущем уроке мы рисовали гладкую поверхности в виде бегущей волны. В этом уроке мы попробуем превратить нашу поверхность в настоящую воду. Луч света проходящий, через границу двух сред, немного изменяет свое направление. Этот эффект называют преломлением света. Пусть на глубине y=ybottom расположено дно, покрытое текстурой. Над поверхностью воды находится глаз наблюдателя, т.е. камера. Нужно выяснить, какую точку текстуры дна увидит наблюдатель. Для этого изменим направление хода луча света на обратное. Луч света будет выходить из глаза наблюдателя, преломляться на поверхности воды и попадать на дно. Точка пересечения преломленного луча и дна и будет видна наблюдателю.







13 октября 2012 г.

OpenGL ES 2.0. Урок третий-Двумерные текстуры

Загрузка текстуры из файла.
Создадим класс, который загружает двумерную текстуру из графического файла. Нам достаточно разместить какой-нибудь графический файл в папку ресурсов (например, в res/drawable-hdpi), чтобы система присвоила ему идентификатор. Идентификатор ресурса - это целое число, которое является ссылкой на данный ресурс. Идентификаторы ресурсов хранятся в  файле R.java, который система создает автоматически. Если известно имя графического файла ресурса, например picture.png , можно получить его идентификатор как R.drawable.picture.
Итак, приступим к созданию класса. Я думаю, что из комментариев будет все понятно.
public class Texture {
        //создаем поле для хранения имени текстуры
        private int name;
        // конструктор двумерной текстуры из ресурса
        //передаем в качестве аргументов контекст 
        //и идентификатор ресурса графического файла
        public Texture(Context context, int idpicture) {
                //создаем пустой массив из одного элемента
                //в этот массив OpenGL ES запишет свободный номер текстуры, 
                // который называют именем текстуры
                int []names = new int[1];
                // получаем свободное имя текстуры, которое будет записано в names[0]
                GLES20.glGenTextures(1, names, 0);
                //запомним имя текстуры в локальном поле класса
                name = names[0];
                //теперь мы можем обращаться к текстуре по ее имени name
                //устанавливаем режим выравнивания по байту
                GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1);
                //делаем текстуру с именем name текущей
                GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, name);
                //устанавливаем фильтры текстуры
                GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
                        GLES20.GL_TEXTURE_MIN_FILTER, 
                        GLES20.GL_LINEAR_MIPMAP_LINEAR);
                GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
                        GLES20.GL_TEXTURE_MAG_FILTER,
                        GLES20.GL_LINEAR);
               //устанавливаем режим повтора изображения 
                //если координаты текстуры вышли за пределы от 0 до 1
                GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
                        GLES20.GL_TEXTURE_WRAP_S,
                        GLES20.GL_REPEAT);
                GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
                        GLES20.GL_TEXTURE_WRAP_T,
                        GLES20.GL_REPEAT);
                // загружаем картинку в Bitmap из ресурса
                Bitmap bitmap = 
                        BitmapFactory.decodeResource(context.getResources(), idpicture);
                //переписываем Bitmap в память видеокарты
                GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
                // удаляем Bitmap из памяти, т.к. картинка уже переписана в видеопамять
                bitmap.recycle();
                // Важный момент ! 
                // Создавать мипмапы нужно только
                // после загрузки текстуры в видеопамять
                GLES20.glGenerateMipmap(GLES20.GL_TEXTURE_2D);
        }// конец конструктора двумерной текстуры

        //нам будет нужен метод, который возвращает имя текстуры
        public int getName() {
                return name;
        }
}// конец класса
Создать текстурный объект mTexture для картинки picture.png можно следующим образом:
Texture mTexture=new Texture(context, R.drawable.picture);
а получить его имя можно так:
int  mTextureName=mTexture.getName();

8 октября 2012 г.

OpenGL ES 2.0. Урок второй-Освещение в шейдере

В отличие от OpenGL ES 1 в OpenGL ES 2.0 не предусмотрено специальных команд (glLightfv и glMaterialfv) для управления освещением и материалами. Вместе с тем,  OpenGL ES 2.0 обладает более широкими возможностями по сравнению с OpenGL ES 1.
OpenGL ES 1 автоматически рассчитывает освещение вершин и далее интерполирует их освещенность в цвет пикселя. Вмешаться в процесс расчета цвета пикселя в классическом OpenGL ES 1 мы не можем. Поэтому, чтобы получить плавные переходы в освещенности объекта нужно увеличивать количество вершин. В OpenGL ES 2.0 все проще. Расчет освещенности можно перенести в фрагментный шейдер, в котором все операции производятся с конкретным пикселем.
Поговорим немного об видах освещения.
Фоновое (ambient) освещение.
Фоновое освещение освещает объекты одинаково со всех сторон. Оно не зависит от положения источника света и глаза наблюдателя. Задается константой.
Диффузное (diffuse) или рассеянное освещение.
Яркость объекта, освещенного диффузным светом, зависит от положения объекта и от положения источника света. Диффузный свет отражается от поверхности одинаково во все  стороны. Поэтому положение глаза наблюдателя на диффузное освещение не влияет. Яркость диффузного освещения определяют по фактору Ламберта. Вычисляется косинус угла между вектором нормали и вектором, указывающим из точки на источник света. Чем этот угол меньше, тем ярче освещена точка. Если угол = 0, получаем максимальную яркость. Если угол=90 градусов - яркость будет равна нулю. Покажу это на рисунке: 

3 октября 2012 г.

OpenGL ES 2.0. Урок первый-Шейдеры

Введение в шейдеры.
OpenGL ES 2.0 использует шейдеры языка GLSL. Шейдеры бывают двух типов - вершинный и фрагментный. В вершинном шейдере производятся расчеты над вершинами, а в фрагментном - над пикселями. Рассмотрим простой вершинный шейдер:
uniform mat4 u_modelViewProjectionMatrix;
attribute vec3 a_vertex;
attribute vec3 a_normal;
attribute vec4 a_color;
varying vec3 v_vertex;
varying vec3 v_normal;
varying vec4 v_color;
void main() {
         v_vertex=a_vertex;
         vec3 n_normal=normalize(a_normal);
         v_normal=n_normal;
         v_color=a_color;
        gl_Position = u_modelViewProjectionMatrix * vec4(a_vertex,1.0);
} 
и соответствующий ему фрагментный шейдер:
precision mediump float;
varying vec3 v_vertex;
varying vec3 v_normal;
varying vec4 v_color;
void main() {
        vec3 n_normal=normalize(v_normal);
        gl_FragColor = v_color;
}
Теперь разберем по косточкам, какие процессы происходят в этих шейдерах.