簡體   English   中英

如何在JOGL中正確使用照明?

[英]How do I use lighting correctly in JOGL?

以下是我在實際項目中也遇到的問題的一些演示。

我的顯示方法如下:

@Override
public void display(GLAutoDrawable drawable) {
    gl2.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);

    gl2.glEnable(GL2.GL_DEPTH_TEST);
    gl2.glEnable(GL2.GL_LIGHTING);

    gl2.glMatrixMode(GL2.GL_MODELVIEW);
    gl2.glLoadIdentity();

    gl2.glMatrixMode(GL2.GL_PROJECTION);
    gl2.glLoadIdentity();

    gl2.glMatrixMode(GL2.GL_MODELVIEW);
    glu.gluLookAt(10, 10, 11, 10, 10, 9, 0, 1, 0);
    gl2.glMatrixMode(GL2.GL_PROJECTION);
    glu.gluPerspective(90, 1, 0.1, 1000.1);
    gl2.glMatrixMode(GL2.GL_MODELVIEW);

    gl2.glRotated(angle++, 0, 1, 0);

    light();

    wall1();
    wall2();
    wall3();

    gl2.glFlush();
}

光線被放置在風景的中間:

private void light() {
    float[] position = { 10, 10, 20, 1 };
    gl2.glLightfv(GL2.GL_LIGHT0, GL2.GL_POSITION, position, 0);

    gl2.glEnable(GL2.GL_LIGHT0);
}

風景由三堵牆組成:

private void wall1() {
    float[] colors = { 0, 1, 0, 1 };
    gl2.glMaterialfv(GL2.GL_FRONT_AND_BACK, GL2.GL_AMBIENT_AND_DIFFUSE, colors, 0);

    gl2.glBegin(GL2.GL_QUADS);

    for (int i = 0; i < 20; i++) {
    for (int j = 0; j < 20; j++) {
        gl2.glNormal3d(0, 0, 1);
        gl2.glVertex3d(i, j, 0);

        gl2.glNormal3d(0, 0, 1);
        gl2.glVertex3d(i + 1, j, 0);

        gl2.glNormal3d(0, 0, 1);
        gl2.glVertex3d(i + 1, j + 1, 0);

        gl2.glNormal3d(0, 0, 1);
        gl2.glVertex3d(i, j + 1, 0);
    }
    }

    gl2.glEnd();
}

private void wall2() {
    float[] colors = { 0, 1, 0, 1 };
    gl2.glMaterialfv(GL2.GL_FRONT_AND_BACK, GL2.GL_AMBIENT_AND_DIFFUSE, colors, 0);

    gl2.glBegin(GL2.GL_QUADS);

    for (int i = 0; i < 20; i++) {
    for (int j = 0; j < 40; j++) {
        gl2.glNormal3d(-1, 0, 0);
        gl2.glVertex3d(20, i, j);

        gl2.glNormal3d(-1, 0, 0);
        gl2.glVertex3d(20, i + 1, j);

        gl2.glNormal3d(-1, 0, 0);
        gl2.glVertex3d(20, i + 1, j + 1);

        gl2.glNormal3d(-1, 0, 0);
        gl2.glVertex3d(20, i, j + 1);
    }
    }

    gl2.glEnd();
}

private void wall3() {
    float[] colors = { 0, 1, 0, 1 };
    gl2.glMaterialfv(GL2.GL_FRONT_AND_BACK, GL2.GL_AMBIENT_AND_DIFFUSE, colors, 0);

    gl2.glBegin(GL2.GL_QUADS);

    for (int i = 0; i < 20; i++) {
    for (int j = 0; j < 20; j++) {
        gl2.glNormal3d(0, 0, -1);
        gl2.glVertex3d(20 - i, j, 40);

        gl2.glNormal3d(0, 0, -1);
        gl2.glVertex3d(20 - i - 1, j, 40);

        gl2.glNormal3d(0, 0, -1);
        gl2.glVertex3d(20 - i - 1, j + 1, 40);

        gl2.glNormal3d(0, 0, -1);
        gl2.glVertex3d(20 - i, j + 1, 40);
    }
    }

    gl2.glEnd();
}

最后,結果如下所示:

結果

您會看到,中間的大牆( wall2wall2預期照亮了,而左側( wall1 )和右側( wall3 )的兩個小牆似乎獲得了最大的光線,這似乎並不現實。我。

我該如何解決這個問題?

提前致謝!

OpenGL中已棄用的標准光源模型是非常基本的。 它將同時使用距離和角度來減少表面從光源接收的光量。 在這種情況下,較大表面的遠端接收的光線少於較小表面,因為光線的角度更大。

另一個問題是OpenGL將計算每個頂點的照明值,然后對每個像素進行插值,從而根據面及其頂點的大小和布局為您提供不同的結果。

是的,這看起來不切實際,這是為什么您不應該使用過時和過時的功能的眾多原因之一。 如果您堅持使用不推薦使用的OpenGL功能,那么您將陷入如此糟糕的照明環境。

您可以使用GL_CONSTANT_ATTENUATIONGL_LINEAR_ATTENUATIONGL_QUADRATIC_ATTENUATION來獲得特定渲染場景的最佳效果,或者可以嘗試使用聚光燈代替位置光,但是您可能永遠無法獲得完美的解決方案。 有關glLight的信息,請參閱文檔

您也可以嘗試更改面/頂點的大小和布局,以使插值結果更符合您的期望。

但是,適當的解決方案是使用着色器實現您自己的基於像素的照明,或者使用提供適當照明的第三方庫。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM