141 lines
4.4 KiB
GLSL
141 lines
4.4 KiB
GLSL
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));
|
|
}
|
|
|
|
|
|
// Interleaved Gradient Noise (Pseudo-random, AKA Blue Noise style)
|
|
// Based on http://momentsingraphics.de/BlueNoise.html
|
|
float ditherBlueNoiseStyle(vec2 p) {
|
|
return fract(sin(dot(p.xy, vec2(12.9898, 78.233))) * 43758.5453123);
|
|
}
|
|
|
|
// White Noise Dithering
|
|
float ditherWhiteNoise(vec2 p) {
|
|
return fract(sin(dot(p, vec2(12.9898, 4.1414))) * 43758.5453);
|
|
}
|
|
|
|
// Ordered Dithering (4x4 Bayer Matrix)
|
|
float ditherOrderedBayer4x4(ivec2 p) {
|
|
const float bayer[16] = float[16](
|
|
0.0, 8.0, 2.0, 10.0,
|
|
12.0, 4.0, 14.0, 6.0,
|
|
3.0, 11.0, 1.0, 9.0,
|
|
15.0, 7.0, 13.0, 5.0
|
|
);
|
|
int index = (p.x % 4) * 4 + (p.y % 4);
|
|
return bayer[index] / 16.0;
|
|
}
|
|
|
|
// Ordered Dithering (8x8 Bayer Matrix)
|
|
float ditherOrderedBayer8x8(ivec2 p) {
|
|
const float bayer8x8[64] = float[64](
|
|
0.0, 32.0, 8.0, 40.0, 2.0, 34.0, 10.0, 42.0,
|
|
48.0, 16.0, 56.0, 24.0, 50.0, 18.0, 58.0, 26.0,
|
|
12.0, 44.0, 4.0, 36.0, 14.0, 46.0, 6.0, 38.0,
|
|
60.0, 28.0, 52.0, 20.0, 62.0, 30.0, 54.0, 22.0,
|
|
3.0, 35.0, 11.0, 43.0, 1.0, 33.0, 9.0, 41.0,
|
|
51.0, 19.0, 59.0, 27.0, 49.0, 17.0, 57.0, 25.0,
|
|
15.0, 47.0, 7.0, 39.0, 13.0, 45.0, 5.0, 37.0,
|
|
63.0, 31.0, 55.0, 23.0, 61.0, 29.0, 53.0, 21.0
|
|
);
|
|
int index = (p.x % 8) * 8 + (p.y % 8);
|
|
return bayer8x8[index] / 64.0;
|
|
}
|
|
|
|
|
|
//vec3 applyDither(vec3 color, vec2 screenCoord) {
|
|
// float quantizationLevels = 255.0;
|
|
// float noise = randomDither(screenCoord);
|
|
// float noiseOffset = (noise - 0.5) / quantizationLevels;
|
|
// vec3 ditheredColor = color + noiseOffset;
|
|
// return clamp(ditheredColor, 0.0, 1.0);
|
|
//}
|