vec3 ScreenSpaceReflection(vec2 uv, float depth, vec3 normal, vec3 color)
{
   float linearDepth = LinearizeDepth(depth);

	vec3 pos = vpGetViewPosition(uv, depth);

	vec3 V = normalize(pos);

    vec3 R = normalize(reflect(V, normal));

	vec3 sky = vpRenderSky(R);

    float fresnel = pow(1.0 - max(dot(-V, normal), 0.0), 5.0);

    vec3 rayPos = pos;

	float fade = 0.0;

    vec2 hitUV = vec2(0.0);
    bool hit = false;

    const float stepSize = 4.15;
    float thickness = mix(
    0.02,
    0.35,
    clamp(linearDepth / far,0.0,1.0)
);

   int steps = int(
    mix(24.0,64.0,
    clamp(linearDepth / far,0.0,1.0))
);


for(int i = 0; i < rayTraceSteps; i++)
{
    if(i >= steps)
        break;
        rayPos += normal * 0.02;
		rayPos += R * stepSize;


        vec4 projected = gbufferProjection * vec4(rayPos, 1.0);

        if(projected.w <= 0.0)
            break;

        vec2 rayUV = projected.xy / projected.w * 0.5 + 0.5;

        if(rayUV.x < 0.0 || rayUV.x > 1.0 ||
           rayUV.y < 0.0 || rayUV.y > 1.0)
            break;

		float rayDepth = LinearizeDepth(texture2D(depthtex0,rayUV).r);

		if(rayDepth > far)
			break;	

        float sceneDepth = texture2D(depthtex0, rayUV).r;
        vec3 scenePos = vpGetViewPosition(rayUV, sceneDepth);

		fade =1.0-float(i)/float(rayTraceSteps);

        if(rayPos.z < scenePos.z + thickness)
        {
            vec3 startPos = rayPos - R * stepSize;
            vec3 endPos   = rayPos;

            for(int j = 0; j < rayTraceBiSteps; j++)
            {
                vec3 midPos = (startPos + endPos) * 0.5;

                vec2 midUV = ViewToScreen(midPos);

                if(midUV.x < 0.0 || midUV.x > 1.0 ||
                   midUV.y < 0.0 || midUV.y > 1.0)
                    break;

                float midDepth = texture2D(depthtex0, midUV).r;
                vec3 midScene = vpGetViewPosition(midUV, midDepth);

                if(midPos.z < midScene.z + thickness)
                    endPos = midPos;
                else
                    startPos = midPos;
            }

            hitUV = ViewToScreen(endPos);
            hit = true;
            break;
        }
    }
	 vec3 reflection = sky;
    if(hit)
    {
        reflection = vec3(0.0);

		float radius = (1.0 - normal.y) * 0.01;


		reflection = texture2D(colortex0, hitUV).rgb;
        reflection = mix(sky, reflection, fresnel * fade);
    }
	color = mix(color, reflection, fresnel);


    return color;
}
