我最近开始研究Android上的OpenGL。在T尝试使用WebGL之后,我尝试在Android上使用它,遇到了一个奇怪的问题,经过数小时的谷歌搜索和试用后,我无法解决。
我的代码应该绘制一个立方体。但是,它似乎没有正确使用我的元素缓冲区并始终绘制黑色/绿色三角形。即使我删除了一些索引,它仍会绘制相同的黑色/绿色三角形,这暗示我OpenGL会提取错误的数据。
我已经阅读了谷歌代码教程,该代码在每次绘制调用之前写入缓冲区,但由于内存开销,我真的想避免这种情况。
这是我的渲染器的代码。我希望我的错误在这里:
package test.slikey.opengl_test;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import static android.opengl.GLES20.*;
public class OpenGLRenderer implements GLSurfaceView.Renderer {
private final String vertexShaderCode = "" +
"precision mediump float;" +
"" +
"attribute vec3 aVertexPosition;" +
"attribute vec4 aVertexColor;" +
"" +
"uniform mat4 uMatWorld;" +
"uniform mat4 uMatView;" +
"uniform mat4 uMatProj;" +
"" +
"varying vec4 vFragColor;" +
"" +
"void main()" +
"{" +
" gl_Position = uMatProj * uMatView * uMatWorld * vec4(aVertexPosition, 1.0);" +
" vFragColor = aVertexColor;" +
"}";
private final String fragmentShaderCode = "" +
"precision mediump float;" +
"" +
"varying vec4 vFragColor;" +
"" +
"void main()" +
"{" +
" gl_FragColor = vFragColor;" +
"}";
private final float[] positions = new float[]{
-1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
1.0f, -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, -1.0f, 1.0f, 0.5f, 0.0f, 1.0f,
-1.0f, 1.0f, -1.0f, 1.0f, 0.5f, 0.0f, 1.0f,
-1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f
};
private final byte[] indices = new byte[]{
0, 4, 5,
0, 5, 1,
1, 5, 6,
1, 6, 2,
2, 6, 7,
2, 7, 3,
3, 7, 4,
3, 4, 0,
4, 7, 6,
4, 6, 5,
3, 0, 1,
3, 1, 2
};
private int shaderProgram;
private int attribVertexPosition;
private int attribVertexColor;
private int uniformMatWorld;
private int uniformMatView;
private int uniformMatProj;
private float[] matrixWorld;
private float[] matrixView;
private float[] matrixProj;
private int vertexBufferPointer;
private int indexBufferPointer;
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
glClearColor(0.2f, 0.6f, 0.8f, 1.0f);
shaderProgram = initShaderProgram();
attribVertexPosition = glGetAttribLocation(shaderProgram, "aVertexPosition");
attribVertexColor = glGetAttribLocation(shaderProgram, "aVertexColor");
uniformMatWorld = glGetUniformLocation(shaderProgram, "uMatWorld");
uniformMatView = glGetUniformLocation(shaderProgram, "uMatView");
uniformMatProj = glGetUniformLocation(shaderProgram, "uMatProj");
matrixWorld = new float[16];
matrixView = new float[16];
matrixProj = new float[16];
initBuffers();
}
private int initShaderProgram() {
int vertexShader = loadShader(GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = loadShader(GL_FRAGMENT_SHADER, fragmentShaderCode);
int program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
int[] linkStatus = new int[1];
glGetProgramiv(program, GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] != GL_TRUE) {
glDeleteProgram(program);
throw new RuntimeException("Could not link program: "
+ glGetProgramInfoLog(program));
}
return program;
}
private int loadShader(int type, String shaderCode) {
int shader = glCreateShader(type);
glShaderSource(shader, shaderCode);
glCompileShader(shader);
int[] compiled = new int[1];
glGetShaderiv(shader, GL_COMPILE_STATUS, compiled, 0);
if (compiled[0] == 0) {
glDeleteShader(shader);
throw new RuntimeException("Could not compile program: "
+ glGetShaderInfoLog(shader) + " | " + shaderCode);
}
return shader;
}
private void initBuffers() {
int[] buffers = new int[2];
glGenBuffers(2, buffers, 0);
vertexBufferPointer = buffers[0];
indexBufferPointer = buffers[1];
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferPointer);
glBufferData(GL_ARRAY_BUFFER, positions.length, ByteBuffer.allocateDirect(positions.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer().put(positions).position(0), GL_STATIC_DRAW);
glVertexAttribPointer(attribVertexPosition, 3, GL_FLOAT, false, 7 * 4, 0);
glVertexAttribPointer(attribVertexColor, 4, GL_FLOAT, false, 7 * 4, 3 * 4);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferPointer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.length, ByteBuffer.allocateDirect(indices.length).order(ByteOrder.nativeOrder()).put(indices).position(0), GL_STATIC_DRAW);
glEnableVertexAttribArray(attribVertexPosition);
glEnableVertexAttribArray(attribVertexColor);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
glViewport(0, 0, width, height);
Matrix.perspectiveM(matrixProj, 0, 45, (float) width / height, 0.01f, 1000.0f);
}
@Override
public void onDrawFrame(GL10 gl) {
glUseProgram(shaderProgram);
Matrix.setIdentityM(matrixWorld, 0);
Matrix.setLookAtM(matrixView, 0,
0, 0, -8,
0, 0, 0,
0, 1, 0
);
glUniformMatrix4fv(uniformMatWorld, 1, false, matrixWorld, 0);
glUniformMatrix4fv(uniformMatView, 1, false, matrixView, 0);
glUniformMatrix4fv(uniformMatProj, 1, false, matrixProj, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, indices.length, GL_UNSIGNED_BYTE, 0);
}
}
我希望它是一个非常小的东西,比如我缺少的默认设置,这是特定于Android的。一个类似的代码适用于WebGL。 希望有人有个主意。
谢谢!