【问题标题】:Using NV_depth_nonlinear extension on Tegra Devices在 Tegra 设备上使用 NV_depth_nonlinear 扩展
【发布时间】:2012-07-03 23:45:17
【问题描述】:

有人成功使用过这个扩展吗? 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(...);

【问题讨论】:

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


    【解决方案1】:

    为了开始使用任何 GPU 的非线性 Z-Buffer,您需要启用扩展(就像您在代码中所做的那样),仅此而已。

    非线性 Z-Buffer 由 GPU 本身处理,而且我们经常没有意识到,它被大多数现代 GPU 使用。

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

    Z 的分辨率。

    人们经常没有意识到的是,在几乎所有机器中, Z 缓冲区是非线性的。 Z缓冲区中存储的实际数字 内存以这种方式与对象的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,正如我在此回复中所建议的那样,因此,我可以说它按说明工作。

    【讨论】:

    • 感谢您的详细回答。现在我手上没有 Tegra 设备。我将在大约 3 周后测试我的 z 缓冲区的行为。
    • 您好 Maurizio,我正在尝试在 Nexus 7 (Tegra 3) 平板电脑上启用此功能,但将其放入 eglChooseConfig() 时发现没有可用的配置。根据您的经验,您知道这是否可行吗?谢谢
    • 嗨,克里斯,我检查了我的代码以记住我这样做的方式,我发现,对于 TEGRA,我在选择配置中设置了一个附加参数,如下所示:EGL_DEPTH_ENCODING_NV,EGL_DEPTH_ENCODING_NONLINEAR_NV ,其中 EGL_DEPTH_ENCODING_NV 是“私有静态最终 int EGL_DEPTH_ENCODING_NV = 0x30E2;”而 EGL_DEPTH_ENCODING_NONLINEAR_NV 是:“私有静态最终 int EGL_DEPTH_ENCODING_NONLINEAR_NV = 0x30E3;”
    【解决方案2】:

    在 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 中定义。

    【讨论】:

      猜你喜欢
      • 2012-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-01
      • 1970-01-01
      • 2021-05-24
      • 2012-03-07
      • 1970-01-01
      相关资源
      最近更新 更多