OpenGL奇怪的渲染行为(闪烁的面孔)

Posted

技术标签:

【中文标题】OpenGL奇怪的渲染行为(闪烁的面孔)【英文标题】:OpenGL strange Rendering behaviour (flickering faces) 【发布时间】:2013-06-19 10:08:16 【问题描述】:

PRE:我正在使用 Assimp(开放资产导入)库来导入 .3ds 文件。网格使用法线和材质进行渲染。使用 Qt。我们尝试过的所有计算机上的驱动程序都是最新的。

POST:当我使用相机围绕对象旋转时,我可以看到一些网格的面在闪烁。

使用 Assimp 的 render() 方法也会发生同样的情况(从 A. wsite 下载的示例代码)。

1)奇怪的是,它通常发生在小尺寸的 .3ds 上,而从来没有发生在大尺寸的 .3ds 上。

2)如果我真的很近,就没有伪影。我离得越远,我看到的伪影就越多。

这是 .3ds 的问题还是我的问题?

大 .3ds (20MB) 示例

小 .3ds (3MB) 示例

我在这里粘贴了我的 Draw() 函数(使用 glLists 但我无法摆脱它们):

void Preview::BuildObjectsLists(Scene *sc,GLenum mode)             
QHash<QString, SceneObject*>& hash=sc->getObj();
int counter =0;

for (QHash<QString,SceneObject*>::ConstIterator i = hash.begin();i!=hash.end();++i) 
    glNewList(index-counter, GL_COMPILE);                       
    Mesh* p = dynamic_cast<Mesh*>(i.value());
    if(p)
        Matrix4x4& a=p->getTrasformation();
        a.transpose();
        if(mode==GL_SELECT)                                  
            glPushName(counter);
        
        glPushMatrix();
        glMultMatrixf((float*) &(a.values));
        applyMaterial(p->getMat());
        QList<Face>& faccie=p->getFaces();
        int numerofacce=faccie.count();
        QList<Vector3D>& normals =p->getNormals();
        bool hasNormals=(!(normals.isEmpty()));
        if(hasNormals)  glEnable(GL_LIGHTING);
        else glDisable(GL_LIGHTING);
        for (int t = 0; t < numerofacce; ++t) 
            Face& f = faccie[t];
            GLenum face_mode;
            Vector3D* lista=f.arrayVertici;
            int* listaNorm=f.normalIndex;
            switch(f.numVertici) 
            case 1:
                face_mode = GL_POINTS;
                glBegin(face_mode);
                if(hasNormals)
                    glNormal3fv(&((normals[listaNorm[0]]).pos[0]));
                glVertex3fv(&lista[0].pos[0]);
                break;
            case 2:
                face_mode = GL_LINES;
                glBegin(face_mode);
                if(hasNormals)
                    glNormal3fv(&((normals[(f.normalIndex)[0]]).pos[0]));
                    glVertex3fv(&lista[0].pos[0]);
                    glNormal3fv(&((normals[(f.normalIndex)[1]]).pos[0]));
                    glVertex3fv(&lista[1].pos[0]);
                
                else
                    glVertex3fv(&lista[0].pos[0]);
                    glVertex3fv(&lista[1].pos[0]);
                
                break;
            case 3:
                face_mode = GL_TRIANGLES;
                glBegin(face_mode);
                if(hasNormals)
                    glNormal3fv(&normals[(f.normalIndex)[0]].pos[0]);
                    glVertex3fv(&lista[0].pos[0]);
                    glNormal3fv(&normals[(f.normalIndex)[1]].pos[0]);
                    glVertex3fv(&lista[1].pos[0]);
                    glNormal3fv(&normals[(f.normalIndex)[2]].pos[0]);
                    glVertex3fv(&lista[2].pos[0]);
                
                else
                    glVertex3fv(&lista[0].pos[0]);
                    glVertex3fv(&lista[1].pos[0]);
                    glVertex3fv(&lista[2].pos[0]);
                
                break;
            default: face_mode = GL_POLYGON; break;
            
            glEnd();
        
        glPopMatrix();
    
    if(mode==GL_SELECT) glPopName();
    glEndList();
    counter++;



【问题讨论】:

【参考方案1】:

12.040 深度缓冲似乎有效,但多边形似乎会通过它们前面的多边形流血。发生了什么事?

您可能以严重限制深度缓冲区精度的方式配置了 zNear 和 zFar 剪裁平面。通常,这是由过于接近 0.0 的 zNear 裁剪平面值引起的。

http://www.opengl.org/archives/resources/faq/technical/depthbuffer.htm

【讨论】:

gluPerspective(fov,ratio,0.1f,20000);到 gluPerspective(fov,ratio,5.0f,20000);解决了问题,非常感谢 @nicolagenesin:我建议您也减少您的200000,这似乎是一个相当高的价值,但当然这取决于您的对象在 OpenGL 单位中的大小。您必须回答的问题是:“在您的应用程序中看到这么远是否有用?” 我从互联网上下载了一些 .3ds 文件,其中 2 个像 10k 一样大。所以,如果我想完整地看到它们,我必须离原点 15k 远。但是什么你说的是一件聪明的事情:我可以在场景加载期间动态地安排 zFar(我知道模型有多大 -> 用一些算法设置 zFar)。谢谢

以上是关于OpenGL奇怪的渲染行为(闪烁的面孔)的主要内容,如果未能解决你的问题,请参考以下文章

是否可以确保对于远处的物体,在 OpenGL 中至少渲染 1 个像素?

Opengl 未定义行为

iPhone 应用程序中奇怪的 OpenGL ES 行为

优化流媒体vbo openg

opengl vbo建议[关闭]

Three.JS:奇怪的闪烁/渲染与透明的MeshPhongMaterial