回 帖 发 新 帖 刷新版面

主题:[讨论]求助openGL中的消隐

最近在做一个可视化的网格,遇到一个消隐问题

首先我画网格的原理是画单个立方体,然后将他们累加起来
代码如下:
glColor4f(1, 1, 1, 1);
       glFrontFace(GL_CCW);
       glCullFace(GL_BACK);
       glEnable(GL_CULL_FACE);
       glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);


       for(k=0;k<m_public.NE;k++)
       {
         for(m=0;m<8;m++)
          for(n=0;n<3;n++)
           vertex_list[m][n]=m_public.IP[m_public.NEM[k][m+1]-1][n+1]; 
       glBegin(GL_QUADS);
       for(i=0; i<6; ++i)          
         for(j=0; j<4; ++j)      
         glVertex3fv(vertex_list[index_list[i][j]]);
       glEnd();
       }
    
对于单个立方体实现了消隐,但多个累加后一些应该消去的线仍旧看的见,如何解决(整体消隐)

回复列表 (共3个回复)

沙发

思路:如果一条线会被遮挡,则这条线就不应该被绘制。可以利用深度测试来解决此问题。
分两步走。第一步,用GL_FILL方式绘制所有的面,此时应该把颜色缓冲区设置为只读,这样既可以在深度缓冲区里面填入正确的深度值,同时又不影响任何一个像素的颜色。第二步,用GL_LINE方式绘制所有的面,此时,如果某一条边是被遮挡的,则它的各个像素都不会通过深度测试,于是不会被绘制,如果某一条边是不被遮挡的,则它的各个像素都(几乎)能通过深度测试,于是被绘制出来。
注意这个“几乎”,这个涉及到z-fighting的问题,可以使用多边形偏移来解决。具体的做法是,在第一步绘制的时候,让计算得到的深度值加上一个偏移,从而使第二步绘制的像素更加容易通过深度测试。

可能描述不是很清楚,还是看代码吧:
[code=c]#include <GL/glut.h>

GLfloat rotate = 0.0f;

void DrawObjects() {
    glPushMatrix();
    glRotatef(rotate, 0.0f, 1.0f, 0.0f);

        // 在(0, 0, 0)处,显示大小为50的立方体
        glPushMatrix();
        glTranslatef(0, 0, 0);
        glutSolidCube(50);
        glPopMatrix();

        // 在(30, 0, 20)处,显示大小为50的立方体
        glPushMatrix();
        glTranslatef(30, 0, 20);
        glutSolidCube(50);
        glPopMatrix();

        // 在(-20, 0, 30)处,显示大小为30的球
        glPushMatrix();
        glTranslatef(-20, 0, 30);
        glutSolidSphere(30, 10, 10);
        glPopMatrix();

        // 在(10, 25, 0)处,显示大小为20的茶壶
        glPushMatrix();
        glTranslatef(10, 25, 0);
        glutSolidTeapot(20.0);
        glPopMatrix();

    glPopMatrix();
}

void display() {
    // 清除颜色缓冲和深度缓冲
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // 设置可视范围
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0, 1.0, 1.0, 1000.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(0, 100, -300, 0, 0, 0, 0, 1, 0);

    // 第一遍绘制
    // 把颜色缓冲设置为只读,这样一来,只有深度缓冲区受到影响
    // 此时应该把绘制方式设置为GL_FILL
    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    DrawObjects();

    // 第二遍绘制
    // 把颜色缓冲区恢复为可写模式
    // 把绘制方式设置为GL_LINE
    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    DrawObjects();

    glutSwapBuffers();
}

void idle() {
    rotate += 1.0f;
    if (rotate >= 360.0f) {
        rotate = 0.0f;
    }

    glutPostRedisplay();
}

int main(int argc, char* argv[]) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(512, 512);
    glutCreateWindow("test");
    glutDisplayFunc(&display);
    glutIdleFunc(&idle);

    // 启用深度测试和多边形偏移
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_POLYGON_OFFSET_FILL);
    glPolygonOffset(1.0f, 1.0f);

    glutMainLoop();
    return 0;
}[/code]

[img]http://blog.pfan.cn/upfile/201008/20100821044836.gif[/img]

板凳


谢谢,按照你的方法已经做好了

3 楼

你好.我是全职网赚工作者.
如果你有时间有电脑.
想在网络上创业.请联系我..
项目绝对真实.详情QQ空间资料
加盟请联系 QQ908889846

我来回复

您尚未登录,请登录后再回复。点此登录或注册