#version 430

layout(local_size_x = 16, local_size_y = 16) in;
layout(rgba32f, binding = 0) writeonly uniform image2D uvTex;

uniform sampler2D tex;
uniform sampler2D texPrev;
uniform sampler2D tex3D;
uniform usampler2D texDepth;
uniform usampler2D texDepthFar;
uniform sampler2D prevND;
uniform vec2 res;
uniform float debug;
uniform int camMoved;

uniform vec3 originPrev;
uniform mat4 MVPprev;

uniform vec3 origin;
uniform mat4 MVP;

ivec2 offset[] = ivec2[](ivec2(-1, -1), ivec2(0, -1), ivec2(1, -1),
	ivec2(-1, 0), ivec2(0, 0), ivec2(1, 0),
	ivec2(-1, 1), ivec2(0, 1), ivec2(1, 1));

float getDepth(inout ivec2 storePos, out vec2 UV) {
	UV = (1.0f * storePos + vec2(0.5)) / res;
	vec3 pos = texture(tex3D, UV).rgb;

	if (isnan(pos.x))
		return pos.x;

	//get UV2 offset
	vec4 pos4 = MVP * vec4(pos, 1);
	pos4 /= pos4.w;
	vec2 UV2 = (pos4.xy + 1) / 2;

	//get new pixel pos
	vec2 diff = res*(UV2 - UV) /*/ 2*/;
	ivec2 off = ivec2(trunc(diff));
	ivec2 storePos2 = storePos + off;
	storePos = storePos2;

	//get new depth as uint
	vec3 dist = pos - origin;
	float depth = sqrt(dot(dist, dist));
	return depth;
}

void main() {
	vec2 UV;
	ivec2 storePos = ivec2(gl_GlobalInvocationID.xy);
	float depth = getDepth(storePos,UV);

	if (isnan(depth))
		return;

	uint udepth = uint(depth * 100);
	uint udepthOrig = udepth;

	vec2 UV2 = (1.0f * storePos + vec2(0.5)) / res;
	uint prevDepth = texture(texDepth, UV2).r;
	if (camMoved == 1) {
		uvec2 prevDepthFar = texture(texDepthFar, UV2).rg;
		uint depthSpan = prevDepthFar.g - prevDepthFar.r;

		udepth -= prevDepthFar.r;
		prevDepth -= prevDepthFar.r;

		//reprojected +- ok
		if (abs(udepth - prevDepth) < max(depthSpan, uint(100)) / uint(2))
			imageStore(uvTex, storePos, vec4((UV - UV2)/res, 0, 0));
		
		//{
			/*for (int i = 0; i < 9; i++) {
				vec2 UV3 = UV2 + offset[i]/res;
				prevDepth = texture(texDepth, UV3 ).r;
				//prevDepth -= prevDepthFar.r;

				if (prevDepth > (1 << 29))
					imageStore(uvTex, storePos + offset[i], vec4((UV - UV2) / res, 0, 0));
			}*/
		//}
	}
	else {
		//top layer exactly
		if (udepth == prevDepth)
			imageStore(uvTex, storePos, vec4((UV - UV2)/res, 0, 0));
	}

	//imageAtomicMax(depthTex, storePos2, udepth); //prefer smaller depth (closer to camera)
	//imageStore(uvTex, storePos2, vec4(abs(prevDepth))/10000/10000);
}