【发布时间】:2010-11-15 23:19:08
【问题描述】:
我已经用 OpenGL 玩了一整周或同等时间。
在 2D 之后,我现在正在尝试 3D。我想重现您在http://johnnylee.net/projects/wii/ 的第三个视频中看到的 3D 场景。
我很难让纹理和深度的一切都正常工作。
我最近遇到了 2 个在视觉上具有相同影响的问题:
- 使用我为 2D 找到的技术,纹理在 3D 中无法很好地融合。
- 一个对象出现在顶部上方的底部。 喜欢这里暴露的问题:Depth Buffer in OpenGL
我已经解决了这两个问题,但我想知道我是否做对了,尤其是第二点。
第一个,我想我明白了。 我有一个圆形目标的图像,圆盘外的任何东西都带有 alpha。它在 OpenGL 中加载得很好。 它后面的一些(由于我的 z 排序问题)其他目标被我用来绘制它的自然正方形四边形的透明区域所隐藏。
这样做的原因是纹理的每个部分都被假定为对于深度缓冲区是完全不透明的。
使用 glEnable(GL_ALPHA_TEST) 和 glAlphaFunc(GL_GREATER, 0.5f) 测试会使纹理的 alpha 层充当每像素(布尔)不透明度指示器,从而使混合变得毫无用处(因为我的图像具有布尔透明度)。
补充问题:顺便说一句,是否有一种方法可以为 alpha 测试指定一个不同于用于混合的 alpha 层的来源?
第二,我找到了解决问题的方法。
在清除颜色和深度缓冲区之前,我已将默认深度设置为 0 glClearDepth(0.0f),并且我使用了“更大”深度函数 glDepthFunc(GL_GREATER)。
让我觉得奇怪的是深度是 1.0,深度函数默认是“更少”GL_LESS。
我基本上是在反转它,这样我的对象就不会倒置显示...
我在任何地方都没有看到过这样的 hack,但另一方面,我也没有看到任何地方以错误的顺序系统地绘制对象,无论我绘制它们的顺序是什么!
好的,下面是现在按我想要的方式工作的代码(精简了,我不希望太多):
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(600, 600); // Size of the OpenGL window
glutCreateWindow("OpenGL - 3D Test"); // Creates OpenGL Window
glutDisplayFunc(display);
glutReshapeFunc(reshape);
PngImage* pi = new PngImage(); // custom class that reads well PNG with transparency
pi->read_from_file("target.png");
GLuint texs[1];
glGenTextures(1, texs);
target_texture = texs[0];
glBindTexture(GL_TEXTURE_2D, target_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, pi->getGLInternalFormat(), pi->getWidth(), pi->getHeight(), 0, pi->getGLFormat(), GL_UNSIGNED_BYTE, pi->getTexels());
glutMainLoop(); // never returns!
return 0;
}
void reshape(int w, int h) {
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(-1, 1, -1, 1);
gluPerspective(45.0, w/(GLdouble)h, 0.5, 10.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void display(void) {
// The stared *** lines in this function make the (ugly?) fix for my second problem
glClearColor(0, 0, 0, 1.00);
glClearDepth(0); // ***
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glEnable(GL_DEPTH_FUNC); // ***
glDepthFunc(GL_GREATER); // ***
draw_scene();
glutSwapBuffers();
glutPostRedisplay();
}
void draw_scene() {
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(1.5, 0, -3, 0, 0, 1, 0, 1, 0);
glColor4f(1.0, 1.0, 1.0, 1.0);
glEnable(GL_TEXTURE_2D);
// The following 2 lines fix the first problem
glEnable(GL_ALPHA_TEST); // makes highly transparent parts
glAlphaFunc(GL_GREATER, 0.2f); // as not existent/not drawn
glBindTexture(GL_TEXTURE_2D, target_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Drawing a textured target
float x = 0, y = 0, z = 0, size = 0.2;
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(x-size, y-size, z);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(x+size, y-size, z);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(x+size, y+size, z);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(x-size, y+size, z);
glEnd();
// Drawing an textured target behind the other (but drawn after)
float x = 0, y = 0, z = 2, size = 0.2;
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(x-size, y-size, z);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(x+size, y-size, z);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(x+size, y+size, z);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(x-size, y+size, z);
glEnd();
}
【问题讨论】:
标签: opengl transparency textures z-order depth-buffer