#extension GL_EXT_frag_depth : enable

uniform sampler2D u_pointCloud_colorTexture;
uniform sampler2D u_pointCloud_ecAndLogDepthTexture;
uniform vec3 u_distancesAndEdlStrength;
varying vec2 v_textureCoordinates;

vec2 neighborContribution(float log2Depth, vec2 padding)
{
    vec2 depthAndLog2Depth = texture2D(u_pointCloud_ecAndLogDepthTexture, v_textureCoordinates + padding).zw;
    if (depthAndLog2Depth.x == 0.0) // 0.0 is the clear value for the gbuffer
    {
        return vec2(0.0); // throw out this sample
    }
    else
    {
        return vec2(max(0.0, log2Depth - depthAndLog2Depth.y), 1.0);
    }
}

void main()
{
    vec4 ecAlphaDepth = texture2D(u_pointCloud_ecAndLogDepthTexture, v_textureCoordinates);
    if (length(ecAlphaDepth.xyz) < czm_epsilon7)
    {
        discard;
    }

    vec4 color = texture2D(u_pointCloud_colorTexture, v_textureCoordinates);

    // sample from neighbors up, down, left, right
    float distX = u_distancesAndEdlStrength.x;
    float distY = u_distancesAndEdlStrength.y;

    vec2 responseAndCount = vec2(0.0);

    responseAndCount += neighborContribution(ecAlphaDepth.a, vec2(0, distY));
    responseAndCount += neighborContribution(ecAlphaDepth.a, vec2(distX, 0));
    responseAndCount += neighborContribution(ecAlphaDepth.a, vec2(0, -distY));
    responseAndCount += neighborContribution(ecAlphaDepth.a, vec2(-distX, 0));

    float response = responseAndCount.x / responseAndCount.y;
    float shade = exp(-response * 300.0 * u_distancesAndEdlStrength.z);
    color.rgb *= shade;
    gl_FragColor = vec4(color);

#ifdef LOG_DEPTH
    czm_writeLogDepth(1.0 + (czm_projection * vec4(ecAlphaDepth.xyz, 1.0)).w);
#else
    gl_FragDepthEXT = czm_eyeToWindowCoordinates(vec4(ecAlphaDepth.xyz, 1.0)).z;
#endif
}
