Page 1 of 1

RGB into a single float16

Posted: Sun Oct 17, 2010 1:58 pm
by mkultra333
I considered putting this in the "Ogre in Practice" forum, but it's more a shader thing than a strictly Ogre thing.

I needed two more slots in my GBuffer but it was already packed tight, so something had to give. I decided that instead of a full 3 float16 RGB specular I'd squeeze the whole specular into a single float16. There's also another float16 for specular exponent with remains untouched.

AFAIK a float16 gives you 12 bits of mantissa accuracy (technically 11 plus 1 implied bit that's always there unless the float is zero.) So I figure I can get roughly 12 bit colour accuracy, which is 16 levels each for red, green and blue. While that wouldn't do for diffuse, I figure I can get away with it on specular.

I use the following code to write the colour to the GBuffer.

Code: Select all

	// we compress the specular colour into a single float16, so it's equivalent to 12 bit colour.	
	float4 Specular=tex2D(SpecularMap,IN.uv.xy).rgba ;
	float2 SpecComp ;
	SpecComp.y=Specular.a ;
	SpecComp.x= floor(Specular.r*15.99)*256.0 + floor(Specular.g*15.99)*16.0 + floor(Specular.b*15.99) ;
	colour3=float4(0,0,SpecComp) ;
The deferred code reconstructs the colour like this:

Code: Select all

	/////////////////////////////////////////////////////////////
	// convert single float16 RGB (12bit-ish) to float3 (24bit-ish) RGB 

		float4 SpecTemp =  tex2D(SpecularMap,screenUV.xy).rgba ;
		
		float4 SpecColor ;
		SpecColor.a=SpecTemp.a ;
		SpecColor.r=floor(SpecTemp.z/256.0f) ;
		SpecColor.g=floor((SpecTemp.z-SpecColor.r*256.0f)/16.0f) ;
		SpecColor.b=floor(SpecTemp.z-SpecColor.r*256.0f-SpecColor.g*16.0f) ;
		SpecColor.rgb/=16.0f ;
	///////////////////////////////////////////////////////////
Seems to work as intended on my Nvidia GT7950. I'm a little worried though, because I wonder how stable and reliable float16 numbers are across graphics cards and drivers. Any floating point noise would seriously mess up the above.

What do you think? Should it hold up ok, or are float16s, drivers and cards so variable that it'd probably break?