Question

Has anyone used this extension successfully? The Khronos spec can be read here: NV_depth_nonlinear extension

I have successfully check the extension via EGL config choosing:

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;
    }
}

But how do I use the non linear depth extension? Must I use:

glBindRenderbuffer(...);
glRenderbufferStorage(...);
Was it helpful?

Solution

in order to start using the non-linear Z-Buffer of any GPU, you need to enable the extension (as you did in your code) and nothing else.

The non-linear Z-Buffer is handled by the GPU itself and, as often we do not realize, it is used by most of the modern GPUs.

As reported in this interesting article (http://www.sjbaker.org/steve/omniv/love_your_z_buffer.html):

The Resolution of Z.

What people often fail to realise is that in nearly all machines, the Z buffer is non-linear. The actual number stored in the Z buffer memory is related to the Z coordinate of the object in this manner:

z_buffer_value = (1<

Where:

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

...and z_buffer_value is an integer.

This means that Z (and hence the precision of Z) is proportional to the reciprocal of the z_buffer_value - and hence there is a LOT of precision close to the eye and very little precision off in the distance. This reciprocal behaviour is somewhat useful because you need objects that are close to the eye to be rendered in great detail - and you need better Z precision for detailed objects.

However, an undesirable consequence of this is that many of your Z buffer's bits are wasted - storing insanely fine detail close to the near clip plane. If you pull the near clip closer to your eye, then ever more bits are dedicated to the task of rendering things that are that close to you, at considerable cost to the precision a bit further out.

It follows that in most cases, flimmering can be greatly reduced - or even eliminated by moving the near clip plane further from your eye.

In my humble experience, I have used successfully the non-linear ZBuffer on TEGRA as I have suggested in this response, hence, I can say it works as stated.

OTHER TIPS

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 .

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top