我正在开发一个简单的程序,它在屏幕上显示一个带照明的立方体。我在 Android 设备上使用 OpenGL ES 2.0。但只有立方体的底面是不透明的。其他表面看起来是透明的(我认为这是因为照明。当我停止使用照明时,看起来所有表面都是不透明的),以便您可以看到它后面的表面。
这是我的立方体的顶点:
static float vertexs[] = { // in counterclockwise order:
// front
-0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
// back
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
-0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
// left
-0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, -0.5f,
// right
0.5f, -0.5f, 0.5f,
0.5f, -0.5f, -0.5f,
0.5f, 0.5f, 0.5f,
0.5f, 0.5f, -0.5f,
// up
-0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
// bottom
-0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f
};
这是我正在使用的法线(这里有问题吗?):
static float normals[] = {
// front
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
// back
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
// left
-1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
// right
1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
// up
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
// bottom
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f
};
着色器如下:
private final String vertexShaderCode =
// Light
"uniform vec4 u_LightAmbient;\n" +
"uniform vec4 u_LightDiffuse;\n" +
"uniform vec4 u_LightSpecular;\n" +
"uniform vec4 u_LightPos;\n" +
//Material
"uniform vec4 u_MaterialAmbient;\n" +
"uniform vec4 u_MaterialDiffuse;\n" +
"uniform vec4 u_MaterialSpecular;\n" +
"uniform float u_MaterialShininess;\n" +
// Matrices
"uniform mat4 u_ModelViewMatrix;\n" +
"uniform mat4 u_ProjectionMatrix;\n" +
"uniform mat4 u_NormalMatrix;\n" +
// vertecies
"attribute vec4 a_Position;\n" +
"attribute vec3 a_Normal;\n" +
"varying vec4 v_Color;\n" +
"void main() {\n" +
"vec4 ambient = u_LightAmbient * u_MaterialAmbient;\n" +
"vec3 P = vec3(u_ModelViewMatrix * a_Position);\n" +
"vec3 L = normalize(vec3(u_LightPos) - P);\n" +
"vec3 N = normalize(mat3(u_NormalMatrix) * a_Normal);\n" +
"vec4 diffuseP = vec4(max(dot(L, N), 0.0));\n" +
"vec4 diffuse = diffuseP * u_LightDiffuse * u_MaterialDiffuse;\n" +
"vec3 S = normalize(L + vec3(0.0, 0.0, 1.0));\n" +
"float specularP = pow(max(dot(N,S), 0.0), u_MaterialShininess);\n" +
"vec4 specular = specularP * u_LightSpecular * u_MaterialSpecular;\n" +
//hyouji sareru iro
"v_Color = ambient + specular + diffuse;\n" +
//position
"gl_Position = u_ProjectionMatrix * u_ModelViewMatrix * a_Position;\n" +
"}\n";
private final String fragmentShaderCode =
"precision mediump float;\n" +
"varying vec4 v_Color;\n" +
"void main() {\n" +
"gl_FragColor = v_Color;\n" +
"}\n";
绘图功能如下:
public Cube() {
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(vertexs.length * 4);
ByteBuffer nb = ByteBuffer.allocateDirect(normals.length * 4);
// use the device hardware's native byte order
bb.order(ByteOrder.nativeOrder());
nb.order(ByteOrder.nativeOrder());
// create a floating point buffer from the ByteBuffer
vertexBuffer = bb.asFloatBuffer();
normalBuffer = nb.asFloatBuffer();
// add the coordinates to the FloatBuffer
vertexBuffer.put(vertexs);
float div = (float)Math.sqrt(3);
for(int i = 0; i < normals.length; i++){
normals[i] /= div;
}
normalBuffer.put(normals);
// set the buffer to read the first coordinate
vertexBuffer.position(0);
normalBuffer.position(0);
// prepare shaders and OpenGL program
int vertexShader = MyRenderer.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = MyRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
mProgram = GLES20.glCreateProgram(); // create empty OpenGL Program
GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program
GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
GLES20.glLinkProgram(mProgram); // create OpenGL program executables
}
public void draw(float[] mvMatrix, float[] pMatrix) {
// Add program to OpenGL environment
GLES20.glUseProgram(mProgram);
// get handle to vertex shader's aPosition member
positionHandle = GLES20.glGetAttribLocation(mProgram, "a_Position");
normalHandle = GLES20.glGetAttribLocation(mProgram, "a_Normal");
GLES20.glEnableVertexAttribArray(positionHandle);
GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer);
GLES20.glEnableVertexAttribArray(normalHandle);
GLES20.glVertexAttribPointer(normalHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, normalBuffer);
modelViewMatrixHandle = GLES20.glGetUniformLocation(mProgram, "u_ModelViewMatrix");
GLES20.glUniformMatrix4fv(modelViewMatrixHandle, 1, false, mvMatrix, 0);
projectionMatrixHandle = GLES20.glGetUniformLocation(mProgram, "u_ProjectionMatrix");
GLES20.glUniformMatrix4fv(projectionMatrixHandle, 1, false, pMatrix, 0);
normalMatrixHandle = GLES20.glGetUniformLocation(mProgram, "u_NormalMatrix");
float[] tmp = new float[16];
float[] normalMatrix = new float[16];
Matrix.invertM(tmp, 0, mvMatrix, 0);
Matrix.transposeM(normalMatrix, 0, tmp, 0);
GLES20.glUniformMatrix4fv(normalMatrixHandle, 1, false, normalMatrix, 0);
lightAmbientHandle = GLES20.glGetUniformLocation(mProgram, "u_LightAmbient");
GLES20.glUniform4f(lightAmbientHandle, 0.2f, 0.2f, 0.2f, 1.0f);
lightDiffuseHandle = GLES20.glGetUniformLocation(mProgram, "u_LightDiffuse");
GLES20.glUniform4f(lightDiffuseHandle, 0.5f, 0.5f, 0.5f, 1.0f);
lightSpecularHandle = GLES20.glGetUniformLocation(mProgram, "u_LightSpecular");
GLES20.glUniform4f(lightSpecularHandle, 0.0f, 0.0f, 0.0f, 1.0f);
lightPosHandle = GLES20.glGetUniformLocation(mProgram, "u_LightPos");
materialAmbientHandle = GLES20.glGetUniformLocation(mProgram, "u_MaterialAmbient");
materialDiffuseHandle = GLES20.glGetUniformLocation(mProgram, "u_MaterialDiffuse");
materialSpecularHandle = GLES20.glGetUniformLocation(mProgram, "u_MaterialSpecular");
materialShininessHandle = GLES20.glGetUniformLocation(mProgram, "u_MaterialShininess");
// Front
setMaterial(0.0f, 1.0f, 0.0f, 1.0f);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
// Back
setMaterial(0.0f, 1.0f, 0.0f, 1.0f);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 4, 4);
// Left
setMaterial(0.0f, 1.0f, 0.0f, 1.0f);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 8, 4);
// Right
setMaterial(0.0f, 1.0f, 0.0f, 1.0f);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 12, 4);
// Top
setMaterial(0.0f, 1.0f, 0.0f, 1.0f);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 16, 4);
// Bottom
setMaterial(0.0f, 1.0f, 0.0f, 1.0f);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 20, 4);
// Disable vertex array
GLES20.glDisableVertexAttribArray(positionHandle);
}
private void setMaterial(float r, float g, float b, float a){
GLES20.glUniform4f(materialAmbientHandle, r, g, b, a);
GLES20.glUniform4f(materialDiffuseHandle, r, g, b, a);
GLES20.glUniform4f(materialSpecularHandle, r, g, b, a);
GLES20.glUniform4f(materialShininessHandle, r, g, b, a);
}
}
结果图片如下