Home Articles Tutorials Resources About
LogLuv floating point encoding in 32 bpp formats   Last update: 2008-07-09 19:43:39 by Rim van Wersch

The LogLuv encoding turns out to be quite useful when doing HDR rendering in XNA, because there are some downsides to the available native floating point formats, most notably on the 360. After some discussion we pieced together the following HLSL implementation, which works out quite nicely.

// M matrix, for encoding
const static float3x3 M = float3x3(
    0.2209, 0.3390, 0.4184,
    0.1138, 0.6780, 0.7319,
    0.0102, 0.1130, 0.2969);

// Inverse M matrix, for decoding
const static float3x3 InverseM = float3x3(
	6.0013,	-2.700,	-1.7995,
	-1.332,	3.1029,	-5.7720,
	.3007,	-1.088,	5.6268);	



float4 LogLuvEncode(in float3 vRGB) 
{		 
    float4 vResult; 
    float3 Xp_Y_XYZp = mul(vRGB, M);
    Xp_Y_XYZp = max(Xp_Y_XYZp, float3(1e-6, 1e-6, 1e-6));
    vResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;
    float Le = 2 * log2(Xp_Y_XYZp.y) + 127;
    vResult.w = frac(Le);
    vResult.z = (Le - (floor(vResult.w*255.0f))/255.0f)/255.0f;
    return vResult;
}

float3 LogLuvDecode(in float4 vLogLuv)
{	
	float Le = vLogLuv.z * 255 + vLogLuv.w;
	float3 Xp_Y_XYZp;
	Xp_Y_XYZp.y = exp2((Le - 127) / 2);
	Xp_Y_XYZp.z = Xp_Y_XYZp.y / vLogLuv.y;
	Xp_Y_XYZp.x = vLogLuv.x * Xp_Y_XYZp.z;
	float3 vRGB = mul(Xp_Y_XYZp, InverseM);
	return max(vRGB, 0);
}

Below you'll also find a simple test project which does a RGB -> LogLuv -> RGB conversion to check if everything works as intended. You can press t to toggle between the test conversion and the original RGB image, which should look exactly the same. If you're getting unexpected results, such as banding or other artifacts, please let us know (include some info on your graphics card model and add a screenshot if possible).



Files for this resource

Filename Size
  LogLuv.zip 702.0 KB


Further reading

 
XNA info is sponsored by vector4. All content is copyright © 2005-2010 by its respective authors | About XNA info | Terms of Use | RSS feed