以下是我在实际项目中遇到的问题的一个小演示。
我的显示方法如下:
@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
)按照预期点亮,而左侧的两个小墙(wall1
)和右侧(wall3
)似乎获得了对我来说似乎不太现实的最大光线。
如何解决此问题?
提前致谢!
答案 0 :(得分:2)
OpenGL中不推荐使用的标准灯光模型非常简陋。它将使用距离和角度来减少表面从光源接收的光量。在这种情况下,较大表面的远端比较小的表面接收的光线少,因为光线的角度更清晰。
另一个问题是OpenGL将计算每个顶点的光照值,然后为每个像素插值,根据面的大小和布局及其顶点给出不同的结果。
是的,这看起来不切实际,这是您不应该使用过期和弃用功能的众多原因之一。如果您仍然坚持使用已弃用的OpenGL功能,那么您就会遇到如此糟糕的灯光。
您可以使用GL_CONSTANT_ATTENUATION
,GL_LINEAR_ATTENUATION
和GL_QUADRATIC_ATTENUATION
来获得特定渲染场景的最佳效果,或者您可以尝试使用聚光灯而不是位置灯,但是可能永远不会得到完美的解决方案。请参阅docs for glLight。
您还可以尝试更改面/顶点的大小和布局,以便将插值结果更多地推向您想要的位置。
但是,正确的解决方案是使用着色器实现您自己的基于像素的照明,或使用提供适当照明的第三方库。