影子卷 - 最后阶段

发布于 2024-10-04 03:44:49 字数 4003 浏览 10 评论 0原文

我继续在 OpenGL 中处理阴影体积,在完成体积本身之后,我需要使用模板缓冲区绘制阴影,这就是我被困的地方:)我渲染了这个场景: 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);

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

I continue to work on shadow volumes in OpenGL, after finishing with volume itself, i need to draw a shadow using stencil buffer, and thats where i'm stuck :) I rendered this scene: http://prntscr.com/17lyr
As you see, sphere represents light source, and one mushroom has its volume drawn directly to the screen, and one hasnt(i expect to see shadow instead). They are absolutely equal, made be translating one model some units on the X axis. Here is the code im working with:

 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);
}

Here is my GL initialization function:

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

And in my main function:

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);

Is everything ok with my code? Because i dont see shadow and dont even know how to check if stencil values are set correctly.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

命硬 2024-10-11 03:44:49

没有办法检查模板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);

There is no way to check stencils afaik. I am going to assume you are using depth fail. I recommend using glStencilOpSeperate like so.

    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);

Then when you draw the actual geometry make sure you are replacing stencil values like so:

    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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文