PDA

View Full Version : Packing a float into a GL_RGB texture



nicolasbol
10-03-2009, 08:38 PM
Guys,

Trying to pack a float into a GL_RGB ( I'm doing this because iPhone 3GS does not support render to depth texture).

I'm aiming for 24bits precision, creating the texture as follow:




glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 320, 480, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);



packing with the following:

Fragment shader



precision highp float;
varying vec4 position;

void main(void)
{
float normalizedDistance = position.z / position.w;
normalizedDistance = (normalizedDistance + 1.0) / 2.0;

const vec3 multCoef = vec3(1.0, 255.0, 255.0 * 255.0 );

vec3 packedFloat = multCoef * normalizedDistance;

gl_FragColor = vec4(fract(packedFloat),1.0);
}


Where position is the screen space position of the vertex from light POV.

Unpacking as follow:



float unpack(vec3 packedZValue)
{
const vec3 multCoef = vec3(1.0,1.0/255.0, 1.0/(255.0 * 255.0));
return dot(packedZValue,multCoef);
}

float getShadowFactor(vec3 lightZ)
{
vec3 packedZValue = texture2D(s_shadowpMap, lightZ.st).rgb;
float unpackedZValue = unpack(packedZValue);

return float(unpackedZValue > lightZ.z);
}

void main(void)
[..]
vec3 lightZ = lightPOVPosition.xyz / lightPOVPosition.w;
lightZ = (lightZ + 1.0) /2.0;
float shadowFactor = getShadowFactor(lightZ);
[...]
}


Where lightPOVPosition is the screen space position of the vertex from light POV.

Unpacking is getting me garbage. It works OK if I don't pack/unpack and only create the shadowmap using one channel of the texture (If not for the unaccuracy).

I wonder if GL_RGB is actually 24 bits on iPhone (can it be different if I set the screen rendering surface as kEAGLColorFormatRGB565 ? Even though I'm rendering to a FBO ?

Is my packing/unpacking algo flawded ?

nicolasbol
10-03-2009, 11:41 PM
So after further reading, I found this:



float4 FloatToFloat4( float rawValue )
{
float4 packFactors = float4( 256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0);
float4 bitMask = float4(1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);

float4 packedValue = float4(frac(packFactors*rawValue));
packedValue -= packedValue.xxyz * bitMask;
return packedValue;
}

float Float4ToFloat(float4 encodedValue)
{
float4 unpackFactors = float4( 1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0, 1.0 );

return dot(encodedValue,unpackFactors);
}



It is working great....but I don't understand the line:



packedValue -= packedValue.xxyz * bitMask;




Ok, get it: We need to remove the value about to be inserted in a channel from the previous value....