I want to render a simple cube in opengl es 3.0 on my android device but it doesn't render. This is my SurfaceView setup:
public GLContextView(Context context){
super(context);
setEGLContextClientVersion(3);
setRenderer(renderer);
}
Render Code:
public void onSurfaceCreated(javax.microedition.khronos.opengles.GL10 unused, javax.microedition.khronos.egl.EGLConfig p2){
GLES30.glEnable(GLES30.GL_DEPTH_TEST);
GLES30.glEnable(GLES30.GL_BLEND);
GLES30.glEnable(GLES30.GL_CULL_FACE);
GLES30.glDepthFunc(GLES30.GL_LEQUAL);
GLES30.glCullFace(GLES30.GL_BACK);
GLES30.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
cubeProgram = RenderHelper.createShaderProgram(Shader.CubeVertexShader, Shader.CubeFragmentShader);
int[] array = new int[2];
GLES30.glGenVertexArrays(1, array, 0);
vaId = array[0];
GLES30.glBindVertexArray(vaId);
GLES30.glGenBuffers(2, array, 0);
vbId = array[0];
ibId = array[1];
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbId);
GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, RenderCube.vertices.length * 4, RenderCube.vBuffer, GLES30.GL_STATIC_DRAW);
GLES30.glVertexAttribPointer(0, 3, GLES30.GL_FLOAT, false, 0, 0);
GLES30.glEnableVertexAttribArray(positionHandle);
GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, ibId);
GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER, RenderCube.indices.length * 4, RenderCube.iBuffer, GLES30.GL_STATIC_DRAW);
colorHandle = GLES30.glGetUniformLocation(cubeProgram, "in_color");
GLES30.glBindVertexArray(0);
}
public void onDrawFrame(GL10 p1){
GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT | GLES30.GL_DEPTH_BUFFER_BIT);
GLES30.glUseProgram(cubeProgram);
GLES30.glBindVertexArray(vaId);
GLES30.glUniform4f(colorHandle, 1.0f, 1.0f, 1.0f, 1.0f);
GLES30.glDrawElements(GLES30.GL_TRIANGLES, RenderCube.indices.length, GLES30.GL_UNSIGNED_INT, 0);
}
public void onSurfaceChanged(GL10 p1, int p2, int p3){
GLES30.glViewport(0, 0, p2, p3);
}
RenderCube class with vertex and index data:
class RenderCube{
public static float[] vertices = {
0.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
0.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
};
public static int[] indices = {
0, 3, 1, 0, 2, 3, //Bottom
4, 7, 5, 4, 6, 7, //Top
0, 5, 1, 0, 4, 5, //Back
2, 7, 3, 2, 6, 7, //Front
0, 6, 2, 0, 4, 6, //Left
1, 7, 3, 1, 5, 7 //Right
};
public static FloatBuffer vBuffer = RenderHelper.createFloatBuffer(vertices.length * 4, vertices);
public static IntBuffer iBuffer = RenderHelper.createIntBuffer(indices.length * 4, indices);
};
Shaders:
final class Shader{
public static final String CubeVertexShader =
"#version 300 es\n" +
"layout (location = 0) in vec3 pos;" +
"void main(){" +
" gl_Position = vec4(pos, 1.0f);" +
"}";
public static final String CubeFragmentShader =
"#version 300 es\n" +
"precision mediump float;" +
"uniform vec4 in_color;" +
"out vec4 color;" +
"void main(){" +
" color = in_color;" +
"}";
}
It compiles fine and no opengl errors are printed. What am I doing wrong?
I think you simply have no visible triangles.
The triangles of the bottom, top, left, and right faces are invisible because they're orthogonal to the viewing plane. So you're looking at them edge on, and they end up as degenerate triangles (i.e. triangles with zero area).
The way you defined them, the triangles of the back and front face all have clockwise winding order. Expanding the indices of those 4 triangles, and showing just the x and y coordinates of the corresponding vertices:
0, 5, 1 -> (0.0f, 0.0f), (1.0f, 1.0f), (1.0f, 0.0f)
0, 4, 5 -> (0.0f, 0.0f), (0.0f, 1.0f), (1.0f, 1.0f)
2, 7, 3 -> (0.0f, 0.0f), (1.0f, 1.0f), (1.0f, 0.0f)
2, 6, 7 -> (0.0f, 0.0f), (0.0f, 1.0f), (1.0f, 1.0f)
As you can see, these triangles are all clockwise. Since you chose to enable culling of back faces:
GLES30.glEnable(GLES30.GL_CULL_FACE);
GLES30.glCullFace(GLES30.GL_BACK);
and the default winding order for front faces is counter-clockwise, meaning that the winding of back faces is clockwise, all these triangles will be culled.
In addition, since the front face is at z = 1.0, it's also exactly on the front clip plane. The way I read the spec, geometry that is exactly on a clipping plane should still be visible. But it's probably safer to place it clearly inside the clip volume.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments