影子卷 - 最后阶段

Posted

技术标签:

【中文标题】影子卷 - 最后阶段【英文标题】:Shadow volumes - final stage 【发布时间】:2010-11-23 14:45:03 【问题描述】:

我继续在 OpenGL 中处理阴影体积,在 finishing with volume itself 之后,我需要使用模板缓冲区绘制阴影,这就是我卡住的地方 :) 我渲染了这个场景:http://prntscr.com/17lyr 如您所见,球体代表光源,一个蘑菇的体积直接绘制到屏幕上,而一个没有(我希望看到阴影)。它们是绝对相等的,可以在 X 轴上平移一个模型的一些单位。这是我正在使用的代码:

 void Display()
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    glLoadIdentity();
    glLightfv(GL_LIGHT1,GL_POSITION,light_position[0]);

    cam.SetPrespective();

    DrawDebugObject(true);
    glTranslatef(15,0,0);
    DrawDebugObject(false);

    glFinish();
    glutSwapBuffers();


void DrawDebugObject(bool draw_sil)
    glPushMatrix();
    glTranslatef(light_position[1][0],light_position[1][1],light_position[1][2]);
    glColor3ub(255,255,0);
    gluSphere(gluNewQuadric(),0.5,10,10);
    glPopMatrix();

    glDisable(GL_LIGHTING);
    glBegin(GL_QUADS);
        glColor3f(1,1,1);
        glVertex3f(-100,0,-100);
        glVertex3f(-100,0,100);
        glVertex3f(100,0,100);
        glVertex3f(100,0,-100);
        glEnd();
    glEnable(GL_LIGHTING);
    pModel->draw();
    if(draw_sil)
        pModel->markSilouette(light_position[1]);
    castShadow(pModel,light_position[1]);   


void castShadow(Model* model,float* lp)
        glDisable(GL_LIGHTING);
        glDepthMask(GL_FALSE);
        glDepthFunc(GL_LEQUAL);

        pModel->markVisible(lp);

        glEnable(GL_STENCIL_TEST);
        glColorMask(0, 0, 0, 0);
        glStencilFunc(GL_ALWAYS, 1, 0xffffffff);

        // first pass, stencil operation decreases stencil value
        glFrontFace(GL_CCW);
        glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
        pModel->markSilouette(lp);

        // second pass, stencil operation increases stencil value
        glFrontFace(GL_CW);
        glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
        pModel->markSilouette(lp);

        glFrontFace(GL_CCW);
        glColorMask(1, 1, 1, 1);

        //draw a shadowing rectangle covering the entire screen
        glColor4f(1.0f, 0.0f, 0.0f, 0.4f);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glStencilFunc(GL_NOTEQUAL, 0, 0xffffffff);
        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
        glPushMatrix();
        glLoadIdentity();
        glBegin(GL_QUADS);
        glVertex3f(-0.1f, 0.1f,-0.10f);
        glVertex3f(-0.1f,-0.1f,-0.10f);
        glVertex3f( 0.1f, 0.1f,-0.10f);
        glVertex3f( 0.1f,-0.1f,-0.10f);
        glEnd();
        glPopMatrix();
        glDisable(GL_BLEND);

        glDepthFunc(GL_LEQUAL);
        glDepthMask(GL_TRUE);
        glEnable(GL_LIGHTING);
        glDisable(GL_STENCIL_TEST);

这是我的 GL 初始化函数:

void InitGL()
    glEnable(GL_NORMALIZE);
    glEnable(GL_LIGHTING);
    glEnable(GL_TEXTURE_2D);
    glShadeModel(GL_SMOOTH);
    glClearDepth(1.0f);                                 // Depth Buffer Setup
    glClearStencil(0);                                  // Stencil Buffer Setup
    glEnable(GL_DEPTH_TEST);                            // Enables Depth Testing
    glDepthFunc(GL_LEQUAL);                             // The Type Of Depth Testing To Do

    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  // Really Nice Perspective Calculations
    glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
    glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
    glHint(GL_FOG_HINT, GL_NICEST);
...nothing important after that

在我的主要功能中:

glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_RGB|GLUT_DEPTH|GLUT_DOUBLE|GLUT_STENCIL|GLUT_ACCUM);
    glutInitWindowSize(Width,Height);
    glutCreateWindow("Spheres");

    glutDisplayFunc(Display);
    glutReshapeFunc(Reshape);
    glutKeyboardFunc(Keyboard);
    glutKeyboardUpFunc(KeyboardUp);
    glutTimerFunc(TIMEOUT,Timer,TIMEOUT);
    glutPassiveMotionFunc(MouseMove);

我的代码一切正常吗?因为我看不到阴影,甚至不知道如何检查模板值是否设置正确。

【问题讨论】:

获取 OpenGL 上下文的代码在哪里?您可能不会要求模板缓冲区,如果您不这样做,某些系统可能不会给您。 编辑了我的问题。我告诉 GL 和 GLUT 都给我模板缓冲,为什么他们仍然抗拒?) 这可能是因为您第二次调用DrawDebugObject 时将false 作为draw_sil 的值传递,所以MarkSilouette 没有被调用? 【参考方案1】:

没有办法检查模板 afaik。我将假设您正在使用深度失败。我建议像这样使用 glStencilOpSeperate。

    glClear(GL_STENCIL_BUFFER_BIT);
    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
    glEnable(GL_STENCIL_TEST);
    glEnable(GL_POLYGON_OFFSET_FILL);
    glDisable(GL_CULL_FACE);
    glStencilFunc(GL_ALWAYS, 0x00, 0xFF);
    glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_KEEP);
    glStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR_WRAP, GL_KEEP);
    glPolygonOffset(0.0f, 5.0f);
    glDepthFunc(GL_LESS);

然后,当您绘制实际几何图形时,请确保您正在替换模板值,如下所示:

    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
    glEnable(GL_CULL_FACE);
    glDisable(GL_POLYGON_OFFSET_FILL);
    glCullFace(GL_BACK);
    glDepthFunc(GL_GEQUAL);
    glStencilFunc(GL_EQUAL, 0x00, 0xFF);
    glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);

【讨论】:

以上是关于影子卷 - 最后阶段的主要内容,如果未能解决你的问题,请参考以下文章

用户配置文件-影子文件

Tensorflow中的滑动平均模型

用户和用户组管理-影子文件shadow

用户和用户组管理-影子文件shadow

影子文件

ShardingSphere实践——影子库