shader_type spatial;
render_mode cull_back;

uniform sampler2D DEPTH_TEXTURE : hint_depth_texture, filter_linear_mipmap;

void vertex() {
	// Called for every vertex the material is visible on.
}

varying vec2 _screen_pos;
varying vec2 _pixel_size;
varying mat4 _inv_pr_mat;
varying mat4 _pr_mat;


void fragment() {
	_screen_pos = SCREEN_UV;
	_pixel_size = vec2(1.0,1.0);
	_inv_pr_mat = INV_PROJECTION_MATRIX;
	_pr_mat = PROJECTION_MATRIX;
}


float get_depth(vec2 uv) {
	return textureLod(DEPTH_TEXTURE, uv, 0.0).r;
}

vec3 get_pos(vec2 uv) {
	float depth = textureLod(DEPTH_TEXTURE, uv, 0.0).r;
    vec4 upos = _inv_pr_mat * vec4(uv * 2.0 - 1.0, depth, 1.0);
    return upos.xyz / upos.w;
}

const int MAX_STEPS = 1000;

float RayTrace(vec3 ro, vec3 rd, vec2 vp_size) {
	vec2 step_dir = 1.0 * rd.xy / vp_size;
	float step_len = length(step_dir);
	ro.xy /= vp_size;
	ro.z = get_depth(ro.xy);
	vec3 od = get_pos(ro.xy);

	float d = .0;
	for (int i = 0; i < MAX_STEPS; i++) {
		vec2 uv = ro.xy + step_dir * d;
		vec3 pos = get_pos(uv);
		if(normalize(pos - od).z > rd.z) return 0.0;
		if(length(pos-od) > 0.05) return 1.0;
		d += 1.0;
	}
	return 1.0;
}

float calculate_light(vec3 normal, vec3 light) {
	return max(dot(normal, light),0);
}

float screen_shadows(vec3 normal, vec3 light, vec3 screen_pos, vec2 vp_size) {
	// WHY????
	light.y *= -1.0;
	return RayTrace(screen_pos, light, vp_size);
}

void light() {
	//DIFFUSE_LIGHT = vec3(get_pos(FRAGCOORD.xy / VIEWPORT_SIZE).z * -1.0);
	DIFFUSE_LIGHT += screen_shadows(NORMAL, LIGHT, FRAGCOORD.xyz, VIEWPORT_SIZE) * calculate_light(NORMAL, LIGHT);
}
