0

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

2 回答 2

1

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

非线性 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,正如我在此回复中所建议的那样,因此,我可以说它按所述工作。

于 2012-07-04T12:58:34.583 回答
0

Testing on Nexus 7, I was able to get this to work by adding to the eglChooseConfig call:

EGL_DEPTH_ENCODING_NV, EGL_DEPTH_ENCODING_NONLINEAR_NV,

and by using

DEPTH_COMPONENT16_NONLINEAR_NV in place of GL_DEPTH_COMPONENT16 for our glRenderbufferStorage call.

Edit: Actually we don't use a depth buffer for our main egl surface, so only GL_DEPTH_COMPONENT16_NONLINEAR_NV was needed. Also changed DEPTH_COMPONENT16_NONLINEAR_NV to GL_DEPTH_COMPONENT16_NONLINEAR_NV as it's defined in the NDK .

于 2013-07-16T17:25:25.243 回答