在Tegra设备上使用NV_depth_nonlinear扩展

时间:2012-07-03 23:45:18

标签: java android opengl-es-2.0 nvidia tegra

有没有人成功使用此扩展程序? Khronos规范可以在这里阅读:NV_depth_nonlinear extension

我已通过EGL配置选择成功检查扩展名:

public class CustomEGLConfigChooser implements EGLConfigChooser {
    private static final int EGL_DEPTH_ENCODING_NV      = 0x30E2;
    private static final int EGL_DEPTH_ENCODING_NONLINEAR_NV = 0x30E3;
    private int[] mValue = new int[1];


    public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
        // request configs
        EGLConfig[] configs = egl.eglChooseConfig(...);
        // ...

        EGLConfig bestConfig = null;        
        for(EGLConfig config : configs){
            // check for EGL_DEPTH_ENCODING_NV
            egl.eglGetConfigAttrib(display, config, EGL_DEPTH_ENCODING_NV, 0);
            int hasDepthNonLinear = findConfigAttrib(egl, display, config, EGL_DEPTH_ENCODING_NV, 0);
            if(hasDepthNonLinear == EGL_DEPTH_ENCODING_NONLINEAR_NV) {
                // what to do now ???...
            }
        }
        return bestConfig;
    }

    private int findConfigAttrib (EGL10 egl, EGLDisplay display, EGLConfig config, int attribute, int defaultValue) {
        if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
            return mValue[0];
        }
        return defaultValue;
    }
}

但是如何使用非线性深度扩展?我必须使用:

glBindRenderbuffer(...);
glRenderbufferStorage(...);

2 个答案:

答案 0 :(得分:1)

为了开始使用任何GPU的非线性Z缓冲区,您需要启用扩展(就像您在代码中所做的那样)而不是其他内容。

非线性Z缓冲区由GPU本身处理,并且我们通常没有意识到,它被大多数现代GPU使用。

正如这篇有趣的文章(http://www.sjbaker.org/steve/omniv/love_your_z_buffer.html)所述:

  

Z的决议。

     

人们经常没有意识到的是,在几乎所有的机器中,   Z缓冲区是非线性的。存储在Z缓冲区中的实际数字   memory以这种方式与对象的Z坐标相关:

     

z_buffer_value =(1<      

其中:

 N = number of bits of Z precision
 a = zFar / ( zFar - zNear )
 b = zFar * zNear / ( zNear - zFar )
 z = distance from the eye to the object
     

...和z_buffer_value是一个整数。

     

这意味着Z(因而Z的精度)与之成正比   z_buffer_value的倒数 - 因此有很多   精度接近眼睛,精度很低   距离。这种互惠行为有点有用,因为你   需要靠近眼睛的物体才能非常细致地渲染    - 对于详细的物体,你需要更好的Z精度。

     

然而,这种不良后果是你的很多Z.   缓冲区的位被浪费 - 将精细的细节存储在靠近的位置   在平面附近。如果你将近夹子拉近眼睛,那么   越来越多的比特专注于渲染事物的任务   靠近你的地方,精确度要高得多   进行。

     

因此,在大多数情况下,闪烁可以大大减少 - 或   甚至通过将近夹片平面从您的眼睛移开来消除。

在我的谦逊经历中,我已经在TEGRA中成功使用了非线性ZBuffer,正如我在此回复中所建议的那样,因此,我可以说它的工作原理如此。

答案 1 :(得分:0)

在Nexus 7上进行测试,我可以通过添加eglChooseConfig电话来实现此目的:

EGL_DEPTH_ENCODING_NV, EGL_DEPTH_ENCODING_NONLINEAR_NV,

并使用

DEPTH_COMPONENT16_NONLINEAR_NV代替我GL_DEPTH_COMPONENT16来电glRenderbufferStorage

编辑:实际上我们不会为主要的egl表面使用深度缓冲区,因此只需要GL_DEPTH_COMPONENT16_NONLINEAR_NV。还将DEPTH_COMPONENT16_NONLINEAR_NV更改为GL_DEPTH_COMPONENT16_NONLINEAR_NV,因为它在NDK中已定义。