const float epsilon = 0.0001; const vec3 lumConv = vec3(0.27, 0.67, 0.06); float HDR_GetLum(in vec3 color){ return dot(color, lumConv); } vec4 HDR_EncodeLum(in float lum){ float Le = 2.0 * log2(lum + epsilon) + 127.0; vec4 result = vec4(0.0); result.a = fract(Le); result.rgb = vec3((Le - (floor(result.a * 255.0)) / 255.0) / 255.0); return result; } float HDR_DecodeLum(in vec4 logLum){ float Le = logLum.r * 255.0 + logLum.a; return exp2((Le - 127.0) / 2.0); } const mat3 rgbToXyz = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969); const mat3 xyzToRgb = mat3( 6.0013, -2.700, -1.7995, -1.332, 3.1029, -5.7720, .3007, -1.088, 5.6268); vec4 HDR_LogLuvEncode(in vec3 rgb){ vec4 result; vec3 Xp_Y_XYZp = rgb * rgbToXyz; Xp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6)); result.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z; float Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0; result.w = fract(Le); result.z = (Le - (floor(result.w * 255.0)) / 255.0) / 255.0; return result; } vec3 HDR_LogLuvDecode(in vec4 logLuv){ float Le = logLuv.z * 255.0 + logLuv.w; vec3 Xp_Y_XYZp; Xp_Y_XYZp.y = exp2((Le - 127.0) / 2.0); Xp_Y_XYZp.z = Xp_Y_XYZp.y / logLuv.y; Xp_Y_XYZp.x = logLuv.x * Xp_Y_XYZp.z; vec3 rgb = Xp_Y_XYZp * xyzToRgb; return max(rgb, 0.0); } vec3 HDR_ToneMap(in vec3 color, in float lumAvg, in float a, in float white){ white *= white; float lumHDR = HDR_GetLum(color); float L = (a / lumAvg) * lumHDR; float Ld = 1.0 + (L / white); Ld = (Ld * L) / (1.0 + L); return (color / lumHDR) * Ld; //return color * vec3(Ld); } vec3 HDR_ToneMap2(in vec3 color, in float lumAvg, in float a, in float white){ float scale = a / (lumAvg + 0.001); return (vec3(scale) * color) / (color + vec3(1.0)); }