108 lines
2.5 KiB
GLSL
108 lines
2.5 KiB
GLSL
// MinecraftPT — Final_FS
|
|
// HDR tonemapping, color grading, dithering, and output to screen.
|
|
|
|
#include "/Lib/Settings.glsl"
|
|
#include "/Lib/Utilities.glsl"
|
|
#include "/Lib/BasicFunctions/TemporalNoise.glsl"
|
|
|
|
uniform sampler2D exposureTex;
|
|
|
|
#if defined PROGRAM_FINAL_0
|
|
layout(location = 0) out vec4 colorOut;
|
|
#elif defined PROGRAM_FINAL_1
|
|
layout(location = 0) out vec4 colorOut;
|
|
#endif
|
|
|
|
// Tonemapping operators
|
|
vec3 TonemapACES(vec3 color){
|
|
// ACES filmic
|
|
float a = 2.51;
|
|
float b = 0.03;
|
|
float c = 2.43;
|
|
float d = 0.59;
|
|
float e = 0.14;
|
|
return saturate((color * (a * color + b)) / (color * (c * color + d) + e));
|
|
}
|
|
|
|
vec3 TonemapAGX(vec3 color){
|
|
// AGX-inspired: log-shaping curve
|
|
vec3 logColor = log2(max(color, 1e-6));
|
|
vec3 mid = vec3(AGX_HDR_MIDGREY);
|
|
vec3 shaped = logColor - mid;
|
|
shaped = tanh(shaped * 0.5) * 0.5 + 0.5;
|
|
vec3 result = exp2(shaped + mid);
|
|
return result;
|
|
}
|
|
|
|
vec3 TonemapFilmic(vec3 color){
|
|
// Uncharted 2 filmic
|
|
vec3 x = max(color, 0.0);
|
|
return (x * (6.2 * x + 0.5)) / (x * (6.2 * x + 1.7) + 0.06);
|
|
}
|
|
|
|
// Color grading
|
|
vec3 ApplyColorGrading(vec3 color){
|
|
// White/black point
|
|
color = (color - BLACK_POINT) / (WHITE_POINT - BLACK_POINT + 1e-6);
|
|
|
|
// Saturation
|
|
float lum = luminance(color);
|
|
color = mix(vec3(lum), color, SATURATION);
|
|
|
|
// Gamma
|
|
color = pow(color, vec3(GAMMA));
|
|
|
|
// Hue shifts (simplified)
|
|
#ifdef ADVANCED_COLOR
|
|
vec3 midtone = color * MIDTONE_HUE * MIDTONE_STRENGTH;
|
|
vec3 highlight = color * HIGHLIGHT_HUE * HIGHLIGHT_STRENGTH;
|
|
vec3 shadow = color * SHADOW_HUE * SHADOW_STRENGTH;
|
|
color += midtone + highlight + shadow;
|
|
#endif
|
|
|
|
return color;
|
|
}
|
|
|
|
void main(){
|
|
vec3 color = texelFetch(colortex12, ivec2(gl_FragCoord.xy), 0).rgb;
|
|
|
|
// Exposure
|
|
#ifdef MANUAL_EXPOSURE
|
|
float exposure = MANUAL_EXPOSURE * pow(2.0, EV_VALUE);
|
|
#else
|
|
float exposure = textureLod(exposureTex, vec2(0.5), 0.0).r;
|
|
#endif
|
|
color *= exposure;
|
|
|
|
// Bloom composite
|
|
#ifdef BLOOM
|
|
vec3 bloom = vec3(0.0);
|
|
// Simple bloom: sample from bloom buffer
|
|
bloom = textureLod(colortex15, gl_FragCoord.xy / screenSize, 0.0).rgb;
|
|
color += bloom * BLOOM_AMOUNT;
|
|
#endif
|
|
|
|
// Tonemapping
|
|
#if TONEMAP_OPERATOR == 0
|
|
color = TonemapACES(color);
|
|
#elif TONEMAP_OPERATOR == 1
|
|
color = TonemapAGX(color);
|
|
#elif TONEMAP_OPERATOR == 2
|
|
color = TonemapFilmic(color);
|
|
#else
|
|
// Vanilla-like: Reinhard
|
|
color = color / (color + 1.0);
|
|
#endif
|
|
|
|
// Color grading
|
|
color = ApplyColorGrading(color);
|
|
|
|
// Dithering
|
|
vec2 noise = BlueNoiseTemporal2();
|
|
color += (noise - 0.5) / 255.0;
|
|
|
|
// Gamma correction
|
|
color = LinearToGamma(color);
|
|
|
|
colorOut = vec4(color, 1.0);
|
|
} |