mirror of
				https://github.com/luanti-org/luanti.git
				synced 2025-11-04 09:15:29 +01:00 
			
		
		
		
	* Add uniform for frame delta time * Adjust exposure in logarithmic (EV) space * Add network support and LUA API * Add testing mod
		
			
				
	
	
		
			76 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			GLSL
		
	
	
	
	
	
			
		
		
	
	
			76 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			GLSL
		
	
	
	
	
	
#define exposure texture0
 | 
						|
#define screen texture1
 | 
						|
 | 
						|
struct ExposureParams {
 | 
						|
	float luminanceMin;
 | 
						|
	float luminanceMax;
 | 
						|
	float exposureCorrection;
 | 
						|
	float luminanceKey;
 | 
						|
	float speedDarkBright;
 | 
						|
	float speedBrightDark;
 | 
						|
	float centerWeightPower;
 | 
						|
	float compensationFactor;
 | 
						|
};
 | 
						|
 | 
						|
uniform sampler2D exposure;
 | 
						|
uniform sampler2D screen;
 | 
						|
 | 
						|
#ifdef ENABLE_BLOOM
 | 
						|
uniform float bloomStrength;
 | 
						|
#else
 | 
						|
const float bloomStrength = 1.0;
 | 
						|
#endif
 | 
						|
uniform ExposureParams exposureParams;
 | 
						|
uniform float animationTimerDelta;
 | 
						|
 | 
						|
 | 
						|
const vec3 luminanceFactors = vec3(0.213, 0.715, 0.072);
 | 
						|
 | 
						|
float getLuminance(vec3 color)
 | 
						|
{
 | 
						|
	return dot(color, luminanceFactors);
 | 
						|
}
 | 
						|
 | 
						|
void main(void)
 | 
						|
{
 | 
						|
	float previousExposure = texture2D(exposure, vec2(0.5, 0.5)).r;
 | 
						|
 | 
						|
	vec3 averageColor = vec3(0.);
 | 
						|
	float n = 0.;
 | 
						|
 | 
						|
	// Scan the screen with center-weighting and sample average color
 | 
						|
	for (float _x = 0.1; _x < 0.9; _x += 0.17) {
 | 
						|
		float x = pow(_x, exposureParams.centerWeightPower);
 | 
						|
		for (float _y = 0.1; _y < 0.9; _y += 0.17) {
 | 
						|
			float y = pow(_y, exposureParams.centerWeightPower);
 | 
						|
			averageColor += texture2D(screen, vec2(0.5 + 0.5 * x, 0.5 + 0.5 * y)).rgb;
 | 
						|
			averageColor += texture2D(screen, vec2(0.5 + 0.5 * x, 0.5 - 0.5 * y)).rgb;
 | 
						|
			averageColor += texture2D(screen, vec2(0.5 - 0.5 * x, 0.5 + 0.5 * y)).rgb;
 | 
						|
			averageColor += texture2D(screen, vec2(0.5 - 0.5 * x, 0.5 - 0.5 * y)).rgb;
 | 
						|
			n += 4.;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	float luminance = getLuminance(averageColor);
 | 
						|
	luminance /= n;
 | 
						|
 | 
						|
	luminance /= pow(2., previousExposure) * bloomStrength * exposureParams.compensationFactor; // compensate for the configurable factors
 | 
						|
 | 
						|
	luminance = clamp(luminance, exposureParams.luminanceMin, exposureParams.luminanceMax);
 | 
						|
 | 
						|
	// From https://media.contentapi.ea.com/content/dam/eacom/frostbite/files/course-notes-moving-frostbite-to-pbr-v2.pdf
 | 
						|
	// 1. EV100 = log2(luminance * S / K) where S = 100, K = 0.125 = log2(luminance) + 3
 | 
						|
	// 2. Lmax = 1.2 * 2 ^ (EV100 - EC)
 | 
						|
	//    => Lmax = 1.2 * 2^3 * luminance / 2^EC = 9.6 * luminance / 2^EC
 | 
						|
	// 3. exposure = 1 / Lmax
 | 
						|
	//    => exposure = 2^EC / (9.6 * luminance)
 | 
						|
	float wantedExposure = exposureParams.exposureCorrection - log(luminance)/0.693147180559945 - 3.263034405833794;
 | 
						|
 | 
						|
	if (wantedExposure < previousExposure)
 | 
						|
		wantedExposure = mix(wantedExposure, previousExposure, exp(-animationTimerDelta * exposureParams.speedDarkBright)); // dark -> bright
 | 
						|
	else
 | 
						|
		wantedExposure = mix(wantedExposure, previousExposure, exp(-animationTimerDelta * exposureParams.speedBrightDark)); // bright -> dark
 | 
						|
 | 
						|
	gl_FragColor = vec4(vec3(wantedExposure), 1.);
 | 
						|
}
 |