воскресенье, 10 апреля 2011 г.

OpenGL ES 2.0 на android. Простой и текстурированный квадрат

Вот такой пример создания простых фигур. Создаем простой квадрат, а потом еще один, но уже с текстурой.
Под катом как написать такое приложение


Для начала можно взять шаблон проекта для eclipse из предыдущего поста.
Исходный код проекта можно взять здесь

Чтобы в отображаемом приложении была перспектива, нужно создать три матрицы: матрица модели (Model matrix), матрица проекции (Projection matrix), и матрица вида (View matrix). Такой подход очень удобен тем, что матрица модели отвечает за расположение вершин (vertex) в виртуальном мире, матрица проекции отвечает за создание, например, перспективы (также можно в ней создать эффект fisheye), а матрица вида за положение камеры в пространстве. Получается, что можно независимо управлять камерой, например, нажатием тачскрина, и одновременно поворачивать наши модели (вершины) в пространстве. Обычно в матрице проекции скрываются отражаются детали экрана, физическое соотношение размеров экрана.


Класс Square, в нем мы создаем вершины. Мы создаем вершины и создаем массив indices, в котором будут индексы для создания 2ух треугольников, из которых состоит квадрат.

public class Square {
float vertices[] = { -1.0f, -1.0f, 0.0f, // 0, Top Left
1.0f, -1.0f, 0.0f, // 1, Bottom Left
1.0f, 1.0f, 0.0f, // 2, Bottom Right
-1.0f, 1.0f, 0.0f // 3, Top Right
};

short[] indices = { 0, 1, 2, 2, 3, 0 };

// Our vertex buffer.
private FloatBuffer vertexBuffer;
// Our index buffer.
private ShortBuffer indexBuffer;
public Square()
{
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
vbb.order(ByteOrder.nativeOrder());
vertexBuffer = vbb.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
// short is 2 bytes, therefore we multiply the number if
// vertices with 2.
ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);
ibb.order(ByteOrder.nativeOrder());
indexBuffer = ibb.asShortBuffer();
indexBuffer.put(indices);
indexBuffer.position(0);
}
FloatBuffer getVertexBuffer(){
return vertexBuffer;
}
ShortBuffer getIndexBuffer(){
return indexBuffer;
}
}




// Load the vertex data

//задаем соответствие вектора aPosition в шейдере и нашего буффера вершин квадрата
GLES20.glVertexAttribPointer(GLES20.glGetAttribLocation(program, "aPosition"), 3,GLES20.GL_FLOAT, false, 0, sq.getVertexBuffer());

//задаем параметр цвета для нашего шейдера
GLES20.glVertexAttrib4f(GLES20.glGetAttribLocation(program, "acolor"), 1f,1f,0f,0.5f);
GLES20.glEnableVertexAttribArray(0);

//производим перемножение матриц Вида, проекции и модели
Matrix.setIdentityM(mMMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);

//задаем соответствие матрицы uMVPMatrixв шейдере и нашего буффера вершин квадрата
GLES20.glUniformMatrix4fv(GLES20.glGetUniformLocation(program, "uMVPMatrix"), 1, false,mMVPMatrix, 0);

//отрисовываем наш квадрат
// GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 4);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_SHORT,sq.getIndexBuffer());


А вот шейдеры

Vertex shader:

uniform mat4 uMVPMatrix;
attribute vec4 aPosition;
attribute vec4 acolor;
varying vec4 vcolor;
void main() {
  gl_Position = uMVPMatrix * aPosition;
  vcolor=acolor;
}




Fragment shader:
precision mediump float;
varying vec4 vcolor;
void main() {
  vec4 color = vcolor; 
  gl_FragColor = color;



3 комментария:

  1. Код бы красивее оформить читать совсем не удобно. И подробное описание шейдеров то же не помешало бы.

    ОтветитьУдалить
  2. Прошло уже 4 года, но код так и остался нечитабельным

    ОтветитьУдалить