[英]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();
}
最后,結果如下所示:
您會看到,中間的大牆( wall2
) wall2
預期照亮了,而左側( wall1
)和右側( wall3
)的兩個小牆似乎獲得了最大的光線,這似乎並不現實。我。
我該如何解決這個問題?
提前致謝!
OpenGL中已棄用的標准光源模型是非常基本的。 它將同時使用距離和角度來減少表面從光源接收的光量。 在這種情況下,較大表面的遠端接收的光線少於較小表面,因為光線的角度更大。
另一個問題是OpenGL將計算每個頂點的照明值,然后對每個像素進行插值,從而根據面及其頂點的大小和布局為您提供不同的結果。
是的,這看起來不切實際,這是為什么您不應該使用過時和過時的功能的眾多原因之一。 如果您堅持使用不推薦使用的OpenGL功能,那么您將陷入如此糟糕的照明環境。
您可以使用GL_CONSTANT_ATTENUATION
, GL_LINEAR_ATTENUATION
和GL_QUADRATIC_ATTENUATION
來獲得特定渲染場景的最佳效果,或者可以嘗試使用聚光燈代替位置光,但是您可能永遠無法獲得完美的解決方案。 有關glLight的信息,請參閱文檔 。
您也可以嘗試更改面/頂點的大小和布局,以使插值結果更符合您的期望。
但是,適當的解決方案是使用着色器實現您自己的基於像素的照明,或者使用提供適當照明的第三方庫。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.