Daskie
Daskie

Reputation: 445

Android Emulator Color Banding with Hardware Acceleration OpenGL ES 3.0

I seem to be loosing considerable precision toward the lower end of the color spectrum only when using hardware accelerated rendering on my Android emulator.

With hardware acceleration (ANGLE D3D11 or Desktop Native OpenGL): enter image description here

Without hardware acceleration (SwiftShader): enter image description here

The banding is clearly non linear and becomes quite obtrusive when trying to render smooth lighting.

I've set getWindow().setFormat(PixelFormat.RGBA_8888); and am using precision highp float; in my fragment shader.

This us using Android Studio 3.1.1, Windows 10, OpenGL ES 3.0.

*Edit: Here's a side by side with increased brightness and contrast enter image description here

Upvotes: 2

Views: 928

Answers (1)

Krzysztof Kosiński
Krzysztof Kosiński

Reputation: 4325

This looks like sRGB colors are being stored in a linear 8-bit format at some point, then are converted back to sRGB. It would lead to exactly the kind of low-brightness imprecision you are observing.

When calling eglCreateWindowSurface, try passing {EGL_COLORSPACE_KHR, EGL_COLORSPACE_SRGB_KHR, EGL_NONE} in the attrib_list parameter. If you are using GLSurfaceView, this will require implementing EGLWindowSurfaceFactory and calling setEGLWindowSurfaceFactory. This requires the EGL_KHR_gl_colorspace extension to be present.

public class EGLFactory implements GLSurfaceView.EGLWindowSurfaceFactory {
  private static final int EGL_GL_COLORSPACE_KHR = 0x309D;
  private static final int EGL_GL_COLORSPACE_SRGB_KHR = 0x3089;
  public EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display,
                                        EGLConfig config, Object nativeWindow) {
    final int[] attribList = {
      EGL_GL_COLORSPACE_KHR,
      EGL_GL_COLORSPACE_SRGB_KHR,
      EGL10.EGL_NONE
    };
    return egl.eglCreateWindowSurface(display, config, nativeWindow, attribList);
  }
  public void destroySurface(EGL10 egl, EGLDisplay display, EGLSurface surface) {
    egl.eglDestroySurface(display, surface);
  }
}

Here is a good post if you want to learn more about sRGB: http://blog.johnnovak.net/2016/09/21/what-every-coder-should-know-about-gamma/

Upvotes: 1

Related Questions