繁体   English   中英

OpenGL ES 1.1奇怪的照明问题

[英]OpenGL ES 1.1 strange lighting problems

我正在研究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中)和每次我绘制一个正方形的材质时,我都会在开始时设置灯光。

在第二个示例中(带有正方形)的效果是由于OpenGL使用的默认非本地查看器。 默认情况下,仅将眼睛空间视图矢量(从顶点到相机的矢量,用于镜面高光计算)取为(0,0,1)-矢量,而不是归一化的顶点位置。 仅当顶点位于屏幕中间时,这种近似才是正确的,但随着您移动到屏幕的边界,误差会越来越大。

要更改此设置并让OpenGL使用从顶点到相机的真实矢量,只需使用glLightModel函数,尤其是

glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);

我不确定这是否也是您遇到的第一个问题(与球体有关)的原因,但也许可以尝试一下。

编辑:似乎您不能在OpenGL ES中使用GL_LIGHT_MODEL_LOCAL_VIEWER 当然,在这种情况下,除了切换到OpenGL ES 2.0并自己进行所有光照计算外,没有其他方法可以解决此问题。

当您移动物体时,灯光可能正在移动。

看看这个答案http://www.opengl.org/resources/faq/technical/lights.htm#ligh0050

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM