const float gaussianCurve(const in float x, const in float k) {
    return exp(-(x * x) / (2.0 * k * k));
}

vec3 filterLighting() {
    positionDepthVector pdv = fillPDVStruct(textureCoordinate);
    surfaceData sd = fillSDStruct(textureCoordinate);

    const float sigma = 4.0;

    const int samples = 3;

    vec2 coord = textureCoordinate;

    vec3 sum = texture(colortex6, coord).rgb;
    float c_phi = 1.0;
    float n_phi = 0.5;
	vec3 cval = vec3(0.0);

    for(int i = -samples; i < samples; ++i)
        for(int j = -samples; j < samples; ++j) {
            cval = texture(colortex6, vec2(i, j)  + coord).rgb * 0.027777777777 + cval;
    }

    vec3 nval = sd.normal[0];

    float sumWeight = 1.0;
    for(int i= -samples; i< samples; ++i) {
        for(int j= -samples; j< samples; ++j) {
            vec2 uv = (vec2(i, j) * sigma) / viewSize;
            vec2 sampleTextureCoordinate = coord+uv;
        
            vec3 ctmp = texture(colortex6, sampleTextureCoordinate).rgb;
            vec3 t = cval - ctmp;
            float dist2 = dot(t,t);
            float c_w = min(exp(-(dist2)/c_phi), 1.0);
        
            surfaceData sdSample = fillSDStruct(sampleTextureCoordinate);

            vec3 ntmp = sdSample.normal[0];
            t = nval - ntmp;
            dist2 = max(dot(nval, ntmp), 0.0);
            float n_w = min(exp(-(dist2)/n_phi), 1.0);

            float weight = saturate(dot(nval, ntmp)) * pow(saturate(dot(cval, ctmp)), 1.0/9.0);
            weight *= gaussianCurve(length(vec2(i, j)), sigma);
            sum += ctmp*weight;
            sumWeight += weight;
        }
    }

    return (sum/sumWeight) * 1.61;
}