// RSM (Reflective Shadow Maps) Global Illumination

#ifndef RSM_GI_INCLUDED
#define RSM_GI_INCLUDED

vec3 rsmGI(vec3 worldPos, vec3 normal, vec3 albedo, vec2 lightLevel, float handLight, vec3 viewPos) {
	vec3 gi = vec3(0.0);
	#ifndef RSM_ENABLED
		return gi;
	#endif
	
	vec4 shadowPos = shadowProjection * vec4(worldPos, 1.0);
	shadowPos.xyz /= shadowPos.w;
	shadowPos.xy = shadowPos.xy * 0.5 + 0.5;
	
	if (shadowPos.x < 0.0 || shadowPos.x > 1.0 || shadowPos.y < 0.0 || shadowPos.y > 1.0 || shadowPos.z > 1.0)
		return gi;
	
	float goldenAngle = 2.3999632297;
	const int rsmSamples = 8;
	vec2 texel = 1.0 / shadowMapResolution;
	
	float totalWeight = 0.0;
	vec3 accumColor = vec3(0.0);
	
	for (int i = 0; i < rsmSamples; i++) {
		float fi = float(i);
		float radius = 0.5 + fi * 0.5;
		float angle = fi * goldenAngle;
		
		vec2 sampleOffset = vec2(cos(angle), sin(angle)) * radius * texel * 8.0;
		vec2 sampleCoord = shadowPos.xy + sampleOffset;
		
		if (sampleCoord.x < 0.0 || sampleCoord.x > 1.0 || sampleCoord.y < 0.0 || sampleCoord.y > 1.0)
			continue;
		
		vec3 sampleColor = texture2D(shadowcolor0, sampleCoord).rgb;
		vec3 sampleNormal = texture2D(shadowcolor1, sampleCoord).rgb * 2.0 - 1.0;
		
		float ndot = max(dot(sampleNormal, normalize(worldPos - shadowPos.xyz * 100.0)), 0.0);
		float distWeight = 1.0 / (1.0 + radius * radius * 4.0);
		float ndotCurrent = max(dot(normal, normalize(sampleNormal)), 0.0) * 0.5 + 0.5;
		
		float weight = ndot * distWeight * ndotCurrent;
		accumColor += sampleColor * weight;
		totalWeight += weight;
	}
	
	if (totalWeight > 0.001)
		gi = accumColor / totalWeight * 0.15;
	
	return gi;
}
#endif
