vec2 Reprojection(vec3 pos) {
	pos = pos * 2.0 - 1.0;

	vec4 viewPosPrev = gbufferProjectionInverse * vec4(pos, 1.0);
	viewPosPrev /= viewPosPrev.w;
	viewPosPrev = gbufferModelViewInverse * viewPosPrev;

	vec3 cameraOffset = cameraPosition - previousCameraPosition;
	cameraOffset *= float(pos.z > 0.56);

	vec4 previousPosition = viewPosPrev + vec4(cameraOffset, 0.0);
	previousPosition = gbufferPreviousModelView * previousPosition;
	previousPosition = gbufferPreviousProjection * previousPosition;
	return previousPosition.xy / previousPosition.w * 0.5 + 0.5;
}

vec3 ApplyMultiColoredBlocklight(vec3 blocklightCol, vec3 screenPos) {
	if (screenPos.z > 0.56) {
		screenPos.xy = Reprojection(screenPos);
	}
	vec3 coloredLight = texture2DLod(colortex9, screenPos.xy, 3).rgb;

	// Verlixia: at render distance colortex9 has no data, so coloredRaw→0 and we
	// fall back to full yellow blocklightCol. Desaturate the fallback at depth so
	// the edge never pops to saturated yellow.
	float depthFade = smoothstep(0.93, 0.985, screenPos.z);
	float blocklightLum = GetLuminance(blocklightCol);
	// Shift toward a cool-neutral near-white; tiny purple hint keeps End portal lamps warm
	vec3 effectiveBlocklight = mix(blocklightCol,
	                               vec3(blocklightLum) * 0.95 + vec3(0.015, 0.01, 0.025),
	                               depthFade);
	
	#ifndef MCBL_LEGACY_COLOR
	vec3 coloredLightNormalized = coloredLight + 0.000001;
	coloredLightNormalized = normalize(coloredLightNormalized * coloredLightNormalized) * 0.875 + 0.125;
	coloredLightNormalized *= GetLuminance(effectiveBlocklight) * 1.7;
	// Verlixia: sqrt ramp — low signal → near-zero blend, high signal → 0.85.
	// LOD 3 + wider ramp dissolves the hard dome ring into a soft gradient.
	float coloredRaw = coloredLight.r + coloredLight.g + coloredLight.b;
	float coloredLightMix = sqrt(clamp(coloredRaw / 0.35, 0.0, 1.0)) * 0.85;
	#else
	vec3 coloredLightNormalized = normalize(coloredLight + 0.00001);
	coloredLightNormalized *= GetLuminance(blocklightCol) / GetLuminance(coloredLightNormalized);
	float coloredLightMix = min((coloredLight.r + coloredLight.g + coloredLight.b) * 256.0, 1.0);
	#endif
	
	return mix(effectiveBlocklight, coloredLightNormalized, coloredLightMix);
}