     const float4* __restrict__ clrVarBuffer,
     float4* nextClrVarBuffer,
     int stepScale,
-    int width, int height)
+    int width, int height,
+    float cameraDistance)
 {
     int ix = blockIdx.x * blockDim.x + threadIdx.x;
     int iy = blockIdx.y * blockDim.y + threadIdx.y;


    float2 p = make_float2(ix, iy);

    // NOTE
    // 5x5

    float4 sumC = make_float4(0, 0, 0, 0);
    float weightC = 0;

    float sumV = 0;
    float weightV = 0;

    int pos = 0;

    static const float h[] = {
        1.0 / 256.0, 1.0 / 64.0, 3.0 / 128.0, 1.0 / 64.0, 1.0 / 256.0,
        1.0 / 64.0,  1.0 / 16.0, 3.0 / 32.0,  1.0 / 16.0, 1.0 / 64.0,
        3.0 / 128.0, 3.0 / 32.0, 9.0 / 64.0,  3.0 / 32.0, 3.0 / 128.0,
        1.0 / 64.0,  1.0 / 16.0, 3.0 / 32.0,  1.0 / 16.0, 1.0 / 64.0,
        1.0 / 256.0, 1.0 / 64.0, 3.0 / 128.0, 1.0 / 64.0, 1.0 / 256.0,
    };

#if 0
    int R = 2;

    for (int y = -R; y <= R; y++) {
        for (int x = -R; x <= R; x++) {
            int xx = clamp(ix + x * stepScale, 0, width - 1);
            int yy = clamp(iy + y * stepScale, 0, height - 1);
#else
    static const int offsetx[] = {
        -2, -1, 0, 1, 2,
        -2, -1, 0, 1, 2,
        -2, -1, 0, 1, 2,
        -2, -1, 0, 1, 2,
        -2, -1, 0, 1, 2,
    };
    static const int offsety[] = {
        -2, -2, -2, -2, -2,
        -1, -1, -1, -1, -1,
         0,  0,  0,  0,  0,
         1,  1,  1,  1,  1,
         2,  2,  2,  2,  2,
    };

#pragma unroll
    for (int i = 0; i < 25; i++) {
    {
            int xx = clamp(ix + offsetx[i] * stepScale, 0, width - 1);
            int yy = clamp(iy + offsety[i] * stepScale, 0, height - 1);
#endif

            float2 q = make_float2(xx, yy);

            const int qidx = getIdx(xx, yy, width);

            normalDepth = aovNormalDepth[qidx];
            texclrMeshid = aovTexclrMeshid[qidx];

            float3 normal = make_float3(normalDepth.x, normalDepth.y, normalDepth.z);

            float depth = normalDepth.w;
            int meshid = (int)texclrMeshid.w;

            float4 color;
            float variance;

            if (isFirstIter) {
                color = aovColorVariance[qidx];
                variance = color.w;

                color = map(color);
                color = RGB2YCoCg(color);
            }
            else {
                color = clrVarBuffer[qidx];
                variance = color.w;
            }

            int _idx = getIdx(xx, iy, width);
            float depthX = aovNormalDepth[_idx].w;

            _idx = getIdx(ix, yy, width);
            float depthY = aovNormalDepth[_idx].w;

            float2 ddZ = make_float2(depthX - centerDepth, depthY - centerDepth);

            float lum = AT_NAME::color::luminance(color.x, color.y, color.z);

            float Wz = min(expf(-fabs(centerDepth - depth) / (sigmaZ * fabs(dot(ddZ, p - q)) + 0.000001f)), 1.0f);

            float Wn = powf(max(0.0f, dot(centerNormal, normal)), sigmaN);

            float Wl = min(expf(-fabs(centerLum - lum) / (sigmaL * sqrGaussedVarLum + 0.000001f)), 1.0f);

            float Wm = meshid == centerMeshId ? 1.0f : 0.0f;

            float W = Wz * Wn * Wl * Wm;
            
            sumC += h[pos] * W * color;
            weightC += h[pos] * W;

#if 1
            Wz = _C(depth, centerDepth, 0.1f);
            Wn = _C(normal, centerNormal, 0.1f);
            Wl = _C(lum, centerLum, 0.1f);
            W = Wz * Wn * Wl * Wm;
#endif

            sumV += (h[pos] * h[pos]) * (W * W) * variance;
            weightV += h[pos] * W;

            pos++;
        }
    }

    if (weightC > 0.0) {
        sumC /= weightC;
    }
    if (weightV > 0.0) {
        sumV /= (weightV * weightV);
    }

    nextClrVarBuffer[idx] = make_float4(sumC.x, sumC.y, sumC.z, sumV);

    if (isFirstIter) {
        // Store color temporary.
        sumC = YCoCg2RGB(sumC);
        tmpBuffer[idx] = unmap(sumC);
    }
    
    if (isFinalIter) {
        sumC = isFirstIter ? sumC : YCoCg2RGB(sumC);
        sumC = unmap(sumC);

        texclrMeshid = aovTexclrMeshid[idx];
        sumC *= texclrMeshid;



        bool isFirstIter = iterCnt == 0 ? true : false;
        bool isFinalIter = iterCnt == maxIterCnt - 1 ? true : false;

        float cameraDistance = height / (2.0f * aten::tan(0.5f * m_camParam.vfov));

        int stepScale = 1 << iterCnt;

