簡體   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