阴影体积 - 寻找剪影

发布于 2024-10-03 19:52:31 字数 3465 浏览 5 评论 0原文

我正在处理我的 OpenGL 任务,下一阶段是加载模型并使用阴影体积算法生成阴影。我分三个阶段进行 -

  1. setConnectivity - 寻找 每个三角形的邻居和 将它们的索引存储在 neigh 中 每个三角形的参数,

  2. markVisible(float* lp) - if lp 表示光的向量 位置,它将三角形标记为 visible = truevisible = false 取决于点的产生 其法向矢量和光的 位置,

  3. markSilhoutte(float *lp) - 标记轮廓边缘并构建体积本身,将轮廓沿与光线相反的方向无限延伸(100 个单位就足够了)。

我检查了所有阶段,并且可以肯定地说前两个阶段都没有问题,所以问题出在第三个函数中,我将其包含在我的问题中。我使用本教程中介绍的算法: http://www.3dcodingtutorial.com/Shadows/ Shadow-Volumes.html

简而言之,如果边同时属于可见三角形和不可见三角形,则该边包含在轮廓中。 这是一对屏幕截图,向您展示问题所在: http://prntscr.com/17dmg , http://prntscr.com/17dmq

正如你所看到的,绿色球体代表光的位置,而这些丑陋的绿蓝色多边形是“阴影体积”的面。您还可以看到,我将此函数应用于立方体模型,并且体积的一侧丢失了(它没有关闭,但我应该是)。有人可以建议我的代码有什么问题以及如何修复它吗?这是我承诺包含的代码(我想变量名称是不言自明的,但如果您不这么认为,我可以为每个变量添加描述):

void Model::markSilhouette(float* lp){
        glBegin(GL_QUADS);
        for ( int i = 0; i < m_numMeshes; i++ )
        {
            for ( int t = 0; t < m_pMeshes[i].m_numTriangles; t++ )
            {
                int triangleIndex = m_pMeshes[i].m_pTriangleIndices[t];
                Triangle* pTri = &m_pTriangles[triangleIndex];
                if (pTri->visible){

                    for(int j=0;j<3;j++){
                        int triangleIndex = m_pMeshes[i].m_pTriangleIndices[pTri->neigh[j]-1];
                        Triangle* pTrk = &m_pTriangles[triangleIndex];
                        if(!pTrk->visible){
                            int p1j=pTri->m_vertexIndices[j];
                            int p2j=pTri->m_vertexIndices[(j+1)%3];
                            float* v1=m_pVertices[p1j].m_location;
                            float* v2=m_pVertices[p2j].m_location;

                            float x1=m_pVertices[p1j].m_location[0];
                            float y1=m_pVertices[p1j].m_location[1];
                            float z1=m_pVertices[p1j].m_location[2];

                            float x2=m_pVertices[p2j].m_location[0];
                            float y2=m_pVertices[p2j].m_location[1];
                            float z2=m_pVertices[p2j].m_location[2];

                            t=100;

                            float xl1=(x1-lp[0])*t;
                            float yl1=(y1-lp[1])*t;
                            float zl1=(z1-lp[2])*t;

                            float xl2=(x2-lp[0])*t;
                            float yl2=(y2-lp[1])*t;
                            float zl2=(z2-lp[2])*t;
                            glColor3f(0,0,1);

                            glVertex3f(x1 + xl1,
                                y1 + yl1,
                                z1 + zl1);
                            glVertex3f(x1,
                                y1,
                                z1);
                            glColor3f(0,1,0);

                            glVertex3f(x2 + xl2,
                                y2 + yl2,
                                z2 + zl2);
                            glVertex3f(x2,
                                y2,
                                z2);
                        }
                    }

                }

            }
        }
        glEnd();
    }

Im working on my OpenGL task, and next stage is loading models and producing shadows using shadow volumes algorithm. I do it in 3 stages -

  1. setConnectivity - finding
    neighbours of each triangle and
    storing their indices in neigh
    parameter of each triangle,

  2. markVisible(float* lp) - if lp
    represents vector of light's
    position, it marks triangles as
    visible = true or visible =
    false
    depending on dot production
    of its normal vector and light
    position,

  3. markSilhoutte(float *lp) - marking silhouette edges and building the volume itself, extending silhouette to infinity(100 units is enough) in the direction opposite to light.

I checked all stages, and can definitely say that its all ok with first two, so the problem is in third function, which i included in my question. I use the algorithm introduced in this tutorial: http://www.3dcodingtutorial.com/Shadows/Shadow-Volumes.html

Briefly, edge is included in silhouette if it belongs to the visible triangle and non-visible triangle at the same time.
Here is a pair of screenshots to show you whats wrong:
http://prntscr.com/17dmg , http://prntscr.com/17dmq

As you can see, green sphere represents light's position, and these ugly green-blue polygons are faces of "shadow volume". You can also see, that im applying this function to the model of cube, and one of volume's side is missing(its not closed, but i should be). Can someone suggest whats wrong with my code and how can i fix it? Here goes the code i promised to include(variables names are self-explanatory, i suppose, but if you dont think so i can add description for each of them):

void Model::markSilhouette(float* lp){
        glBegin(GL_QUADS);
        for ( int i = 0; i < m_numMeshes; i++ )
        {
            for ( int t = 0; t < m_pMeshes[i].m_numTriangles; t++ )
            {
                int triangleIndex = m_pMeshes[i].m_pTriangleIndices[t];
                Triangle* pTri = &m_pTriangles[triangleIndex];
                if (pTri->visible){

                    for(int j=0;j<3;j++){
                        int triangleIndex = m_pMeshes[i].m_pTriangleIndices[pTri->neigh[j]-1];
                        Triangle* pTrk = &m_pTriangles[triangleIndex];
                        if(!pTrk->visible){
                            int p1j=pTri->m_vertexIndices[j];
                            int p2j=pTri->m_vertexIndices[(j+1)%3];
                            float* v1=m_pVertices[p1j].m_location;
                            float* v2=m_pVertices[p2j].m_location;

                            float x1=m_pVertices[p1j].m_location[0];
                            float y1=m_pVertices[p1j].m_location[1];
                            float z1=m_pVertices[p1j].m_location[2];

                            float x2=m_pVertices[p2j].m_location[0];
                            float y2=m_pVertices[p2j].m_location[1];
                            float z2=m_pVertices[p2j].m_location[2];

                            t=100;

                            float xl1=(x1-lp[0])*t;
                            float yl1=(y1-lp[1])*t;
                            float zl1=(z1-lp[2])*t;

                            float xl2=(x2-lp[0])*t;
                            float yl2=(y2-lp[1])*t;
                            float zl2=(z2-lp[2])*t;
                            glColor3f(0,0,1);

                            glVertex3f(x1 + xl1,
                                y1 + yl1,
                                z1 + zl1);
                            glVertex3f(x1,
                                y1,
                                z1);
                            glColor3f(0,1,0);

                            glVertex3f(x2 + xl2,
                                y2 + yl2,
                                z2 + zl2);
                            glVertex3f(x2,
                                y2,
                                z2);
                        }
                    }

                }

            }
        }
        glEnd();
    }

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

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

发布评论

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

评论(2

菊凝晚露 2024-10-10 19:52:31

我已经找到了。看起来如果你几天都没有看到明显的算法错误,那么你就犯了一个愚蠢的错误。

我的三角形索引变量称为 t。你猜怎么着?我的扩展向量长度也称为 t,它们在同一范围内,并且我在第一个可见三角形之后设置 t=100 :D 所以现在卷看起来像这样:
http://prntscr.com/17l3n 之外
里面 http://prntscr.com/17l40
它对于所有光线位置看起来都很好(当然,阴影体积算法可以接受)。因此绘制阴影体积的工作代码如下:

void Model::markSilouette(float* lp){
    glDisable(GL_LIGHTING);
    glPointSize(4.0);
    glEnable(GL_COLOR_MATERIAL);
    glColorMaterial(GL_FRONT_AND_BACK,GL_FILL);
    glBegin(GL_QUADS);
    for ( int i = 0; i < m_numMeshes; i++ )
    {
        for ( int t = 0; t < m_pMeshes[i].m_numTriangles; t++ )
        {
            int triangleIndex = m_pMeshes[i].m_pTriangleIndices[t];
            Triangle* pTri = &m_pTriangles[triangleIndex];

            if (pTri->visible){
                for(int j=0;j<3;j++){
                    Triangle* pTrk;
                    if(pTri->neigh[j]){
                        int triangleIndex = m_pMeshes[i].m_pTriangleIndices[pTri->neigh[j]-1];
                        pTrk = &m_pTriangles[triangleIndex];
                    }

                        if((!pTri->neigh[j]) || !pTrk->visible){

                            int p1j=pTri->m_vertexIndices[j];
                            int p2j=pTri->m_vertexIndices[(j+1)%3];
                            float* v1=m_pVertices[p1j].m_location;
                            float* v2=m_pVertices[p2j].m_location;

                            float x1=m_pVertices[p1j].m_location[0];
                            float y1=m_pVertices[p1j].m_location[1];
                            float z1=m_pVertices[p1j].m_location[2];

                            float x2=m_pVertices[p2j].m_location[0];
                            float y2=m_pVertices[p2j].m_location[1];
                            float z2=m_pVertices[p2j].m_location[2];

                            float f=100; // THE PROBLEM WAS HERE

                            float xl1=(x1-lp[0])*f;
                            float yl1=(y1-lp[1])*f;
                            float zl1=(z1-lp[2])*f;

                            float xl2=(x2-lp[0])*f;
                            float yl2=(y2-lp[1])*f;
                            float zl2=(z2-lp[2])*f;
                            glColor3f(0,0,0);
                            glVertex3f(x1 + xl1,
                                y1 + yl1,
                                z1 + zl1);
                            glVertex3f(x1,
                                y1,
                                z1);
                            glVertex3f(x2,
                                y2,
                                z2);
                            glVertex3f(x2 + xl2,
                                y2 + yl2,
                                z2 + zl2);
                        }
                    }
                }

        }
    }
    glEnd();
}

I've found it. It looks like if you dont see an obvious algorithm mistake for a few days, then you've made a f*cking stupid mistake.

My triangle index variable is called t. Guess what? My extending vector length is also called t, and they are in the same scope, and i set t=100 after FIRST visible triangle :D So now volumes look like this:
outside http://prntscr.com/17l3n
inside http://prntscr.com/17l40
And it looks good for all light positions(acceptable by shadow volumes aglorithm, of course). So the working code for drawing a shadow volume is the following:

void Model::markSilouette(float* lp){
    glDisable(GL_LIGHTING);
    glPointSize(4.0);
    glEnable(GL_COLOR_MATERIAL);
    glColorMaterial(GL_FRONT_AND_BACK,GL_FILL);
    glBegin(GL_QUADS);
    for ( int i = 0; i < m_numMeshes; i++ )
    {
        for ( int t = 0; t < m_pMeshes[i].m_numTriangles; t++ )
        {
            int triangleIndex = m_pMeshes[i].m_pTriangleIndices[t];
            Triangle* pTri = &m_pTriangles[triangleIndex];

            if (pTri->visible){
                for(int j=0;j<3;j++){
                    Triangle* pTrk;
                    if(pTri->neigh[j]){
                        int triangleIndex = m_pMeshes[i].m_pTriangleIndices[pTri->neigh[j]-1];
                        pTrk = &m_pTriangles[triangleIndex];
                    }

                        if((!pTri->neigh[j]) || !pTrk->visible){

                            int p1j=pTri->m_vertexIndices[j];
                            int p2j=pTri->m_vertexIndices[(j+1)%3];
                            float* v1=m_pVertices[p1j].m_location;
                            float* v2=m_pVertices[p2j].m_location;

                            float x1=m_pVertices[p1j].m_location[0];
                            float y1=m_pVertices[p1j].m_location[1];
                            float z1=m_pVertices[p1j].m_location[2];

                            float x2=m_pVertices[p2j].m_location[0];
                            float y2=m_pVertices[p2j].m_location[1];
                            float z2=m_pVertices[p2j].m_location[2];

                            float f=100; // THE PROBLEM WAS HERE

                            float xl1=(x1-lp[0])*f;
                            float yl1=(y1-lp[1])*f;
                            float zl1=(z1-lp[2])*f;

                            float xl2=(x2-lp[0])*f;
                            float yl2=(y2-lp[1])*f;
                            float zl2=(z2-lp[2])*f;
                            glColor3f(0,0,0);
                            glVertex3f(x1 + xl1,
                                y1 + yl1,
                                z1 + zl1);
                            glVertex3f(x1,
                                y1,
                                z1);
                            glVertex3f(x2,
                                y2,
                                z2);
                            glVertex3f(x2 + xl2,
                                y2 + yl2,
                                z2 + zl2);
                        }
                    }
                }

        }
    }
    glEnd();
}
多像笑话 2024-10-10 19:52:31

我认为一切都好,你只是渲染体积而不进行深度测试=)

I think everything is ok, you are just rendering volume without depth test =)

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