vec3 uncharted2Tonemap(const vec3 x) { const float A = 0.15; const float B = 0.50; const float C = 0.10; const float D = 0.20; const float E = 0.02; const float F = 0.30; return ((x * (A * x + C * B) + D * E) / (x * (A * x + B) + D * F)) - E / F; } vec3 tonemapUncharted2(const vec3 color) { const float W = 11.2; const float exposureBias = 2.0; vec3 curr = uncharted2Tonemap(exposureBias * color); vec3 whiteScale = 1.0 / uncharted2Tonemap(vec3(W)); return curr * whiteScale; } // Based on Filmic Tonemapping Operators http://filmicgames.com/archives/75 vec3 tonemapFilmic(const vec3 color) { vec3 x = max(vec3(0.0), color - 0.004); return (x * (6.2 * x + 0.5)) / (x * (6.2 * x + 1.7) + 0.06); } // https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/ vec3 acesFilm(const vec3 x) { const float a = 2.51; const float b = 0.03; const float c = 2.43; const float d = 0.59; const float e = 0.14; return clamp((x * (a * x + b)) / (x * (c * x + d ) + e), 0.0, 1.0); } vec3 tonemapReinhard(const vec3 color) { return color / (color + vec3(1.0)); } // Blender AgX Implementation // Troy Sobotka https://github.com/sobotka/AgX // AGX Simple vec3 tonemapAgXSimple(vec3 x) { // TODO CORRECT AND OPTIMIZE x = max(x, vec3(0.0)); float exposure = 0.6; x *= exposure; const vec3 AgX_A = vec3(0.92, 0.92, 0.72); const vec3 AgX_B = vec3(0.24, 0.24, 0.36); const vec3 AgX_C = vec3(0.92, 0.92, 0.72); const vec3 AgX_D = vec3(0.24, 0.24, 0.36); const vec3 AgX_E = vec3(0.08, 0.08, 0.12); const vec3 AgX_F = vec3(0.0); vec3 result = (x * (AgX_A * x + AgX_B)) / (x * (AgX_C * x + AgX_D) + AgX_E) + AgX_F; float luma = dot(result, vec3(0.2126, 0.7152, 0.0722)); result = mix(vec3(luma), result, 0.6); return clamp(result, vec3(0.0), vec3(1.0)); } // AGX Full Contrast Approx vec3 agxDefaultContrastApprox(vec3 x) { vec3 x2 = x * x; vec3 x4 = x2 * x2; return + 15.5 * x4 * x2 - 40.14 * x4 * x + 31.96 * x4 - 6.868 * x2 * x + 0.4298 * x2 + 0.1191 * x - 0.00232; } // AGX Full Look vec3 agxLook(vec3 x, float strength) { const vec3 slope = vec3(1.0); const vec3 power = vec3(1.35); const vec3 sat = vec3(1.4); vec3 lw = vec3(0.2126, 0.7152, 0.0722); float luma = dot(x, lw); return pow(x * slope, power) * sat - (pow(luma * slope, power) * (sat - 1.0)); } // AGX Full vec3 tonemapAgXFull(vec3 x) { // x *= 2.0 * (1.0/0.8); // Brightness scale to match Blender's default x = clamp(x, 0.0, 65504.0); x = log2(x + 1.0); x = agxDefaultContrastApprox(clamp(x * 0.5 - 10.5, -12.0, 12.0)); x = mix(x, agxLook(x, 0.5), 0.5); x = clamp(x, 0.0, 1.0); return pow(x, vec3(1.0/2.2)); }