Android OpenGL ES 2, рисовые квадраты
РЕДАКТИРОВАТЬ: проблема решена!
Поэтому я прошел официальные обучающие программы OpenGL ES 2 для Android, и я попал в ту часть, которая включает в себя рисование фигур, но я не могу заставить квадрат работать. Вместо этого он рисует правый треугольник.
Я включил код, который я использую, чтобы определить и нарисовать фигуру, которая копируется почти точно из учебника. Класс Renderer просто создает экземпляр этой формы и вызывает метод draw.
По какой-то причине в учебнике не приводятся значения /declare для вершинногоStride и vertexCount, поэтому те, которые у меня есть, являются образованными догадками. Я пробовал несколько значений для vertexCount (от 1 до 12), и никто не работает.
Спасибо заранее.
public class Square {
private FloatBuffer vertexBuffer;
private ShortBuffer drawListBuffer;
// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 3;
static float squareCoords[] = { -0.5f, 0.5f, 0.0f, // top left
-0.5f, -0.5f, 0.0f, // bottom left
0.5f, -0.5f, 0.0f, // bottom right
0.5f, 0.5f, 0.0f }; // top right
private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices
float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };
private final String vertexShaderCode =
"attribute vec4 vPosition;" +
"void main() {" +
" gl_Position = vPosition;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
int mProgram;
static final int vertexStride = COORDS_PER_VERTEX * 4;
static final int vertexCount = 4;
public Square() {
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(squareCoords.length * 4); // (# of coordinate values * 4 bytes per float)
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(squareCoords);
vertexBuffer.position(0);
// initialize byte buffer for the draw list
ByteBuffer dlb = ByteBuffer.allocateDirect(drawOrder.length * 2); // (# of coordinate values * 2 bytes per short)
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(drawOrder);
drawListBuffer.position(0);
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
mProgram = GLES20.glCreateProgram(); // create empty OpenGL ES Program
GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program
GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
GLES20.glLinkProgram(mProgram); // creates OpenGL ES program executables
}
public static int loadShader(int type, String shaderCode){
// create a vertex shader type (GLES20.GL_VERTEX_SHADER)
// or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
int shader = GLES20.glCreateShader(type);
// add the source code to the shader and compile it
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
public void draw() {
// Add program to OpenGL ES environment
GLES20.glUseProgram(mProgram);
// get handle to vertex shader vPosition member
int mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
// Enable a handle to the triangle vertices
GLES20.glEnableVertexAttribArray(mPositionHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
// get handle to fragment shader vColor member
int mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
// Set color for drawing the triangle
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
}
Ответы
Ответ 1
vertexCount = squareCoords.length/COORDS_PER_VERTEX; //Vertex count is the array divided by the size of the vertex ex. (x,y) or (x,y,z)
vertexStride = COORDS_PER_VERTEX * 4; //4 are how many bytes in a float
Сообщите мне, если это сработало для вас, удачи.
Я думаю, что у вас также отсутствует матрица ModelViewProjection
, используемая для преобразования 3D-пространства в пространство 2D-экрана. mvpMatrix должен быть передан функцией draw draw(float[] mvpMatrix)
Забыв упомянуть, вы также должны использовать DrawElements(...)
(используется в примере), если вы не нуждаетесь в счетчике или шаге, просто длина массива idicies и буфер рисования.
// Get handle to shape transformation matrix
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
// Draw the square
GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
Ответ 2
В учебнике отсутствуют некоторые шаги: окончательный код для квадрата здесь.
В качестве примера использовался glDrawElements
вместо glDrawArrays
, который обозначается наличием строки: private short drawOrder[] = { 0, 1, 2, 0, 2, 3 }; // order to draw vertices
.
Этот массив задает нужные вершины из двух треугольников. 0, 1 и 2 для первого. Тогда 0, 2 и 3 для второго. GL_TRANGLE_FAN
просто работает, потому что он будет рисовать следующий треугольник, используя первую вершину в буфере, последнюю вершину, используемую в предыдущем треугольнике и следующую вершину. Для второго треугольника это 0, 2 и 3. Тогда 0, 3 и 4 и т.д. Если бы вершина 2 была 5, 5 и вершина 3 была -5, 5, то полученный вентилятор не был бы квадратом.
Заменить эти строки:
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
При этом:
// Draw the square
GLES20.glDrawElements(
GLES20.GL_TRIANGLES, drawOrder.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
Ответ 3
@Jon W
Я думаю, что разница между GL_TRIANGLES и GL_TRIANGLE_FAN объясняется на картинке:
http://www.google.fr/imgres?imgurl=http://www.naturewizard.com/Tutorials/Tutorial01/images/image009.jpg&imgrefurl=http://www.naturewizard.com/tutorial0104.html&h=719&w=604&sz=55&tbnid=15KBWSk5xZO7YM:&tbnh=90&tbnw=76&zoom=1&usg=__o554PpZhRv8TM8JTmLC9FpU7_ko=&docid=ELETRFsqMmNrvM&sa=X&ei=F0hnUcK9BMPA0QWn2oDABw&ved=0CEIQ9QEwAQ&dur=255