Tag Archives: opengl

Rendering UI transitions on mobile

I was implementing a kind of defocus blur transition effect between two UI screens and came up with the following shader:

/// viewport resolution (in pixels) in .xy and inverse resolution in .zw
uniform vec4  u_Resolution;       
/// 0...1
uniform float u_TransitionValue;  
/// virtual pixel size
uniform float u_PixelSize;        
uniform sampler2D Texture0;      
uniform sampler2D Texture1;      
out vec4 out_FragColor;
void main(void)
{
	float T = u_TransitionValue;
	float S0 = 1.0;
	float S1 = u_PixelSize;
	float S2 = 1.0;
	// 2 segments, 1/2 each
	float Half = 0.5;
	float PixelSize = ( T < Half ) ? mix( S0, S1, T / Half ) : mix( S1, S2, (T-Half) / Half );
	vec2 D = PixelSize * u_Resolution.zw;
	vec2 UV = (gl_FragCoord.xy * u_Resolution.zw);
	// 12-tap Poisson disk coefficients:
	// https://github.com/spite/Wagner/blob/master/fragment-shaders/poisson-disc-blur-fs.glsl
	const int NumTaps = 12;
	vec2 Disk[NumTaps];
	Disk[0] = vec2(-.326,-.406);
	Disk[1] = vec2(-.840,-.074);
	Disk[2] = vec2(-.696, .457);
	Disk[3] = vec2(-.203, .621);
	Disk[4] = vec2( .962,-.195);
	Disk[5] = vec2( .473,-.480);
	Disk[6] = vec2( .519, .767);
	Disk[7] = vec2( .185,-.893);
	Disk[8] = vec2( .507, .064);
	Disk[9] = vec2( .896, .412);
	Disk[10] = vec2(-.322,-.933);
	Disk[11] = vec2(-.792,-.598);
	vec4 C0 = texture( Texture0, UV );
	vec4 C1 = texture( Texture1, UV );
	for ( int i = 0; i != NumTaps; i++ )
	{
		C0 += texture( Texture0, Disk[i] * D + UV );
		C1 += texture( Texture1, Disk[i] * D + UV );
	}
	C0 /= float(NumTaps+1);
	C1 /= float(NumTaps+1);
	out_FragColor = mix( C0, C1, T );
}

I get wrong results with this fragment shader on some mobile GPUs. For example, Andreno 330 on LG Nexus 5 gives just a series of shifted images instead of blur. Google Nexus 10 runs it just fine. Anyway, I will have to investigate it a bit later.

Vertex Array Object (VAO) on Android

Always wanted to put my hands on an OpenGL ES 3 Android device. Here are the results of testing VAO on Google Nexus 10 (Android 4.3 with OpenGL ES 3) and Samsung Galaxy Nexus (Android 4.3 with OpenGL ES 2 and OES_vertex_array_object extension).

1. First, the old Samsung Galaxy Nexus. 
The extensions list claims the OES_vertex_array_object extension is supported. So, I load the entry points:

#define BIND_EXT( VarName, Type, Bind1, Bind2 )\
        VarName = (Type)GetGLProc( API, Bind1 );\
        if ( !VarName ) VarName = (Type)GetGLProc( API, Bind2 );
BIND_EXT( API->glBindVertexArray,
          PFNGLBINDVERTEXARRAYPROC,
          "glBindVertexArray", "glBindVertexArrayOES" );
BIND_EXT( API->glDeleteVertexArrays,
          PFNGLDELETEVERTEXARRAYSPROC,
          "glDeleteVertexArrays", "glDeleteVertexArraysOES" );
BIND_EXT( API->glGenVertexArrays,
          PFNGLGENVERTEXARRAYSPROC,
          "glGenVertexArrays", "glGenVertexArraysOES" );

Just in case, I check for the presence of actual functions.

bool IsVAOSupported = API->glBindVertexArray &&
                      API->glDeleteVertexArrays &&
                      API->glGenVertexArrays;

It looks fine, so we start rendering using VAO in hope everything will go as expected. Nope, it doesn’t:

E/libEGL: called unimplemented OpenGL ES API.

Pfff, stop saying “Yes, we support VAO!”.

2. Here goes the Google Nexus 10 (with an awesome 2560×1600 10-inch touchscreen).

I/LEngine: OpenGL version   : OpenGL ES 3.0
I/LEngine: OpenGL vendor    : ARM
I/LEngine: OpenGL renderer  : Mali-T604
I/LEngine: GLSL version     : OpenGL ES GLSL ES 3.00

VAO just works using the same code path, which is used on a desktop OpenGL 3.2.