我正在研究我在 Android 上使用 OpenGL 照明时遇到的一个有趣问题。我正在开发一个 3D 查看器,您可以在其中添加和操作 3D 对象。您还可以设置具有不同属性的灯光。我的查看器面临的问题是来自灯光(它是点光源)的 3D 对象上的高光表现异常。如果光源与相机位于完全相同的点,则高光将向您预期的相反方向移动。(因此,如果您将对象移动到左侧,突出显示也会移动到对象的左边缘,而不是我所期望的右侧。)
因此,为了进一步缩小问题范围,我创建了一个仅渲染正方形的小型示例应用程序,然后我围绕相机位置(原点)旋转该正方形,这也是放置灯光的位置。这应该会导致所有方块都直接面向相机,这样它们就会被完全突出显示。结果看起来像这样:
会不会是因为投影导致边框变形而出现这些伪影?
在第一张图像中,球体和相机之间的距离约为 20 个单位,球体的大小约为 2。如果我将光线移近物体,高光看起来会好很多,正如我所期待的那样. 在第二幅图像中,正方形所在的半径为 25 个单位。我在 Android 3.1 上使用 OpenGL ES 1.1(因为我一直在努力让它与 ES 2.0 中的着色器一起工作)
这是我正在使用的一些代码:
public void onDrawFrame(GL10 gl) {
// Setting the camera
GLU.gluLookAt(gl, 0, 0, 0, 0f, 0f, -1f, 0f, 1.0f, 0.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
for (int i = 0; i < 72; i++) {
gl.glPushMatrix();
gl.glRotatef(5f * i, 0, 1, 0);
gl.glTranslatef(0, 0, -25);
draw(gl);
gl.glPopMatrix();
}
}
public void draw(GL10 gl) {
setMaterial(gl);
gl.glEnable(GL10.GL_NORMALIZE);
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glFrontFace(GL10.GL_CCW);
// Enable the vertex and normal state
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);
gl.glNormalPointer(GL10.GL_FLOAT, 0, mNormalBuffer);
gl.glDrawElements(GL10.GL_TRIANGLES, mIndexBuffer.capacity(), GL10.GL_UNSIGNED_SHORT, mIndexBuffer);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
}
// Setting the light
private void drawLights(GL10 gl) {
// Point Light
float[] position = { 0, 0, 0, 1 };
float[] diffuse = { .6f, .6f, .6f, 1f };
float[] specular = { 1, 1, 1, 1 };
float[] ambient = { .2f, .2f, .2f, 1 };
gl.glEnable(GL10.GL_LIGHTING);
gl.glEnable(GL10.GL_LIGHT0);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glLightfv(GL10.GL_LIGHT0, GL_POSITION, position, 0);
gl.glLightfv(GL10.GL_LIGHT0, GL_DIFFUSE, diffuse, 0);
gl.glLightfv(GL10.GL_LIGHT0, GL_AMBIENT, ambient, 0);
gl.glLightfv(GL10.GL_LIGHT0, GL_SPECULAR, specular, 0);
}
private void setMaterial(GL10 gl) {
float shininess = 30;
float[] ambient = { 0, 0, .3f, 1 };
float[] diffuse = { 0, 0, .7f, 1 };
float[] specular = { 1, 1, 1, 1 };
gl.glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse, 0);
gl.glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient, 0);
gl.glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular, 0);
gl.glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
}
我在开始时设置灯光,当活动开始时(在 onSurfaceCreated 中)以及每次我绘制正方形时的材质。