 		static const int radius = 3;
 		static const float sigmaN = 0.005f;
 		static const float sigmaD = 0.005f;
-		static const float sigmaS = 8;
+		static const float sigmaS = 0.965f;
 
 		auto centerNormal = aovs[idx].normal;
 

		//varianceEstimation << <1, 1 >> > (
			outputSurf,
			curaov.ptr(),
			width, height);

		checkCudaKernel(varianceEstimation);

	return &aovs[idx];
}

inline __device__ float3 computeViewSpace(
	int ix, int iy,
	float centerDepth,
	int width, int height,
	const aten::mat4* mtxC2V)
{
	// NOTE
	// Pview = (Xview, Yview, Zview, 1)
	// mtxV2C = W 0 0  0
	//          0 H 0  0
	//          0 0 A  B
	//          0 0 -1 0
	// mtxV2C * Pview = (Xclip, Yclip, Zclip, Wclip) = (Xclip, Yclip, Zclip, Zview)
	//  Wclip = Zview = depth
	// Xscr = Xclip / Wclip = Xclip / Zview = Xclip / depth
	// Yscr = Yclip / Wclip = Yclip / Zview = Yclip / depth
	//
	// Xscr * depth = Xclip
	// Xview = mtxC2V * Xclip

	float2 uv = make_float2(ix + 0.5, iy + 0.5);
	uv /= make_float2(width - 1, height - 1);	// [0, 1]
	uv = uv * 2.0f - 1.0f;	// [0, 1] -> [-1, 1]

	aten::vec4 pos(uv.x, uv.y, 0, 0);

	// Screen-space -> Clip-space.
	pos.x *= centerDepth;
	pos.y *= centerDepth;

	// Clip-space -> View-space
	pos = mtxC2V->apply(pos);
	pos.z = -centerDepth;
	pos.w = 1.0;

	return make_float3(pos.x, pos.y, pos.z);
}

#define IS_IN_BOUND(x, a, b)	((a) <= (x) && (x) < (b))

__global__ void varianceEstimation(
	cudaSurfaceObject_t dst,
	idaten::SVGFPathTracing::AOV* aovs,
	aten::mat4 mtxC2V,
	int width, int height)
{
	int ix = blockIdx.x * blockDim.x + threadIdx.x;
