没有任何着色器可以实现深度剥离吗?

时间:2013-06-10 09:58:28

标签: opengl transparency depth

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

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

1 个答案:

答案 0 :(得分:1)

是的,如果你有GL_ARB_depth_texture& GL_ARB_shadow,虽然它很繁琐。

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

这个代码被我用来调试一些深度剥离算法的一些测试代码破解了。我已经删除了所有系统特定的东西,用pseudocode&做了一些重组,所以不要期望它编译。希望你能够得到这个想法。

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

[代码]     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(双偏)     {         矩阵投影,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。