0

我不知道着色器,但我对它们的概念有一个基本的了解。

我需要实现深度剥离,所以我想知道是否首先应该深入到着色器世界,或者它可以在没有着色器的情况下实现,只需巧妙地使用 glDepthFunc..

4

1 回答 1

1

是的,如果你有 GL_ARB_depth_texture 和 GL_ARB_shadow,你就可以做到,尽管它很繁琐。

GL_ARB_occlusion_query 也非常有用,因为它允许您决定何时停止剥离。如果你没有这个,那么你仍然可以这样做,但需要通过你的循环进行固定数量的迭代。太高会浪费时间和内存,太低可能会引入视觉伪影。

这段代码是从我不久前用来调试一些深度剥离算法的一些测试代码中破解出来的。我已经删除了所有系统特定的东西,用伪代码替换它并进行了一些重组,所以不要指望它能够编译。希望你应该能够得到这个想法。

对于使用这种方法的顺序无关透明度,您可能会创建一个深度纹理列表,然后以相反的顺序遍历。

[代码] bool DrawNthSurface(size_t pass) { GLboolean cached_stencil_test_enabled; GLboolean cached_alpha_test_enabled; GLboolean cached_depth_test_enabled; GLboolean cached_face_cull_enabled;

    glGetBooleanv(GL_STENCIL_TEST, &cached_stencil_test_enabled);
    glGetBooleanv(GL_ALPHA_TEST, &cached_alpha_test_enabled);
    glGetBooleanv(GL_DEPTH_TEST, &cached_depth_test_enabled);
    glGetBooleanv(GL_CULL_FACE, &cached_face_cull_enabled);

    if(HasShadow()) // Checks GL_ARB_shadow
    {
        return false; 
    }
    else
    {
        GLuint depthTexture(0);

        bool status(true);

        glEnable(GL_DEPTH_TEST);
        glDepthFunc(GL_LEQUAL);
        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);

        // Draw geometry into the depth buffer.  No textures, shaders etc.
        //
        // This could easily be folded into next part by restructuring into 
        // do...while()
        status&= DrawSimpleGeometry();

        if(status)
        {
            // for transparency etc. you would build a list of these inside the 
            // loop.  For finding the nth surface we can recycle one.
            glGenTextures(1, &depthTexture);

            if(depthTexture)
            {
                glBindTexture(GL_TEXTURE_2D, depthTexture);

                glTexImage2D(GL_TEXTURE_2D, 0,
                             GL_DEPTH_COMPONENT, 
                             ctx->GetViewportWidth(), 
                             ctx->GetViewportHeight(), 0,
                             GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);


                // Set up texture unit.
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 
                                GL_NEAREST);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 
                                GL_NEAREST);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 
                                GL_CLAMP);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 
                                GL_CLAMP); 

                glEnable(GL_TEXTURE_2D);

                // Set up texture coord generation.  Should get bias from depth buffer 
                // precision.
                SetupTexGen(-0.004);

                // Set up shadow test.

                glTexParameteri(GL_TEXTURE_2D, 
                                GL_TEXTURE_COMPARE_MODE_ARB, 
                                        GL_COMPARE_R_TO_TEXTURE_ARB);

                glTexParameteri(GL_TEXTURE_2D, 
                                GL_TEXTURE_COMPARE_FUNC_ARB, 
                                GL_GREATER);

                glTexParameteri(GL_TEXTURE_2D, 
                                GL_DEPTH_TEXTURE_MODE_ARB, 
                                GL_ALPHA);

                glAlphaFunc(GL_GREATER, 0.5f);
                glEnable(GL_ALPHA_TEST); 

                for(size_t n=0;(n<passes) && status;n++)
                {
                    // Update depth texture.
                    glBindTexture(GL_TEXTURE_2D, depthTexture);
                    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 
                                        ctx->GetViewportWidth(), 
                                        ctx->GetViewportHeight());


                    glClear(GL_DEPTH_BUFFER_BIT);

                    status&= DrawSimpleGeometry();
                }

                // deactivate shadow test.
                {
                    // Texgen
                    glDisable(GL_TEXTURE_GEN_S);
                    glDisable(GL_TEXTURE_GEN_T);
                    glDisable(GL_TEXTURE_GEN_R);
                    glDisable(GL_TEXTURE_GEN_Q);

                    // Texture unit
                    glDisable(GL_TEXTURE_2D);

                    // Shadow comparison
                    glDisable(GL_ALPHA_TEST); 
                }

                glDeleteTextures(1, &depthTexture);
            }
            else
            {
                status = false;
            }
        }

        // Restore some of the rendering state.
        if(cached_face_cull_enabled)
        {
            glEnable(GL_CULL_FACE);
            glCullFace(GL_BACK);
        }
        else
        {
            glDisable(GL_CULL_FACE);
        }

        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);

        if(cached_face_cull_enabled)
        {
            glEnable(GL_CULL_FACE);
            glCullFace(GL_BACK);
        }
        else
        {
            glDisable(GL_CULL_FACE);
        }

        if(!cached_stencil_test_enabled)
        {
            glDisable(GL_STENCIL_TEST);
        }
        else
        {
            glEnable(GL_STENCIL_TEST);
        }

        if(!cached_alpha_test_enabled)
        {
            glDisable(GL_ALPHA_TEST);
        }
        else
        {
            glEnable(GL_ALPHA_TEST);
        }

        if(!cached_depth_test_enabled)
        {
            glDisable(GL_DEPTH_TEST);
        }
        else
        {
            glEnable(GL_DEPTH_TEST);
        }

        // FINALLY: Draw everything.
        if(status)
        {
            glDepthFunc(GL_EQUAL);
            status&= DrawAllGeometry();
        }

        glDepthFunc(GL_LEQUAL);

        return status;
    }
}

[/代码]

恕我直言,最棘手的一点是正确设置 texgen。代码非常简单。我已经包含了一个偏差参数来避免 z 战斗伪影。

[代码] Matrix CreateTextureMatrix(double bias) { 矩阵投影, cmay;

    double tmp[16];

    glGetDoublev(GL_PROJECTION_MATRIX, tmp);

    projection = Matrix(tmp);

    Matrix bias_matrix(0.5, 0.0, 0.0,        0.0,
                       0.0, 0.5, 0.0,        0.0,
                       0.0, 0.0, 0.5,        0.0,
                       0.5, 0.5, 0.5 + bias, 1.0);


    return (projection * bias_matrix);
}

void SetupTexGen(double bias)
{
    Matrix texmat;
    Matrix mv, imv;

    {
        double tmp[16];
        glGetDoublev(GL_MODELVIEW_MATRIX, tmp);
        mv = Matrix(tmp);

        imv = mv.GetInverse();
    }

    glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
    glTexGendv(GL_S, GL_EYE_PLANE, imv.Row(0));
    glEnable(GL_TEXTURE_GEN_S);

    glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
    glTexGendv(GL_T, GL_EYE_PLANE, imv.Row(1));
    glEnable(GL_TEXTURE_GEN_T);

    glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
    glTexGendv(GL_R, GL_EYE_PLANE, imv.Row(2));
    glEnable(GL_TEXTURE_GEN_R);

    glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
    glTexGendv(GL_Q, GL_EYE_PLANE, imv.Row(3));
    glEnable(GL_TEXTURE_GEN_Q);

    texmat = CreateTextureMatrix(bias);

    glMatrixMode(GL_TEXTURE);
    glLoadIdentity();

    glMultMatrixd(texmat);
    glMatrixMode(GL_MODELVIEW);
}

[/代码]

HTH。

于 2014-05-30T17:55:40.533 回答