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 |
|
|
702.0 KB |
Further reading

