Omnidirectional shadows and VSDCT on OpenGL ES 3

Recently we have ported all the parts of our shading pipeline to OpenGL ES 3. The last piece of the puzzle was a decent implementation of omnidirectional shadow maps. We used a Virtual Shadow Depth Cube Texture (VSDCT) described in ShaderX3.

Here is a simple code snipped I wrote to convert cube map vec3 into a virtual texture vec2:

vec2 GetShadowTC( vec3 Dir )
{
	float Sc;
	float Tc;
	float Ma;
	float FaceIndex;

	float rx = Dir.x;
	float ry = Dir.y;
	float rz = Dir.z;

	vec3 adir = abs(Dir);
	Ma = max( max( adir.x, adir.y ), adir.z );

	if ( adir.x > adir.y && adir.x > adir.z )
	{
		Sc = ( rx > 0.0 ) ? rz : -rz;
		Tc = ry;
		FaceIndex = ( rx > 0.0 ) ? 0.0 : 1.0;
	}
	else if ( adir.y > adir.x && adir.y > adir.z )
	{
		Sc = rx;
		Tc = ( ry > 0.0 ) ? rz : -rz;
		FaceIndex = ( ry > 0.0 ) ? 2.0 : 3.0;
	}
	else
	{
		Sc = ( rz > 0.0 ) ? -rx : rx;
		Tc = ry;
		FaceIndex = ( rz > 0.0 ) ? 4.0 : 5.0;
	}

	float s = 0.5 * ( Sc / Ma + 1.0 );
	float t = 0.5 * ( Tc / Ma + 1.0 );

	s = s / 3.0;
	t = t / 2.0;

	float Flr = floor(FaceIndex / 3.0);
	float Rmd = FaceIndex - (3.0 * Flr);

	s += Rmd / 3.0;
	t += Flr / 2.0;

	return vec2( s, t );
}

The distance from the light source is packed into a 8-bit RGBA texture using this trick. Everything else is pretty straightforward.

Android demo (requires OpenGL ES 3).

Leave a Reply