diff --git a/components/renderers/cpp/include/ftl/cuda/normals.hpp b/components/renderers/cpp/include/ftl/cuda/normals.hpp
index dc3d0265ce4c142861bb0ca0b2e841dc81887449..bbf690f4f66178297158dea35528ba01629445a1 100644
--- a/components/renderers/cpp/include/ftl/cuda/normals.hpp
+++ b/components/renderers/cpp/include/ftl/cuda/normals.hpp
@@ -42,6 +42,11 @@ void normal_visualise(ftl::cuda::TextureObject<float4> &norm,
         const float3 &light, const uchar4 &diffuse, const uchar4 &ambient,
         cudaStream_t stream);
 
+void cool_blue(ftl::cuda::TextureObject<float4> &norm,
+        ftl::cuda::TextureObject<uchar4> &output,
+        const uchar4 &colouring, const float3x3 &pose,
+        cudaStream_t stream);
+
 void normal_filter(ftl::cuda::TextureObject<float4> &norm,
         ftl::cuda::TextureObject<float4> &points,
         const ftl::rgbd::Camera &camera, const float4x4 &pose,
diff --git a/components/renderers/cpp/src/normals.cu b/components/renderers/cpp/src/normals.cu
index 97452555dfb61fd5015aa6a1745b39e2ddcca409..31034c0af6059f2b8014d7af780bd082bb34868a 100644
--- a/components/renderers/cpp/src/normals.cu
+++ b/components/renderers/cpp/src/normals.cu
@@ -399,6 +399,50 @@ void ftl::cuda::normal_visualise(ftl::cuda::TextureObject<float4> &norm,
 
 //==============================================================================
 
+__global__ void cool_blue_kernel(ftl::cuda::TextureObject<float4> norm,
+        ftl::cuda::TextureObject<uchar4> output,
+        uchar4 colouring, float3x3 pose) {
+    const unsigned int x = blockIdx.x*blockDim.x + threadIdx.x;
+    const unsigned int y = blockIdx.y*blockDim.y + threadIdx.y;
+
+    if(x >= norm.width() || y >= norm.height()) return;
+
+    //output(x,y) = make_uchar4(0,0,0,0);
+    float3 ray = pose * make_float3(0.0f,0.0f,1.0f);
+    ray = ray / length(ray);
+    float3 n = make_float3(norm.tex2D((int)x,(int)y));
+    float l = length(n);
+    if (l == 0) return;
+    n /= l;
+
+    const float d = 1.0f - max(dot(ray, n), 0.0f);
+    uchar4 original = output(x,y); //.tex2D(x,y);
+
+    output(x,y) = make_uchar4(
+        min(255.0f, colouring.x*d + original.x),
+        min(255.0f, colouring.y*d + original.y),
+        min(255.0f, colouring.z*d + original.z), 255);
+}
+
+void ftl::cuda::cool_blue(ftl::cuda::TextureObject<float4> &norm,
+        ftl::cuda::TextureObject<uchar4> &output,
+        const uchar4 &colouring, const float3x3 &pose,
+        cudaStream_t stream) {
+
+    const dim3 gridSize((norm.width() + T_PER_BLOCK - 1)/T_PER_BLOCK, (norm.height() + T_PER_BLOCK - 1)/T_PER_BLOCK);
+    const dim3 blockSize(T_PER_BLOCK, T_PER_BLOCK);
+
+    cool_blue_kernel<<<gridSize, blockSize, 0, stream>>>(norm, output, colouring, pose);
+
+    cudaSafeCall( cudaGetLastError() );
+    #ifdef _DEBUG
+    cudaSafeCall(cudaDeviceSynchronize());
+    //cutilCheckMsg(__FUNCTION__);
+    #endif
+}
+
+//==============================================================================
+
 __global__ void filter_normals_kernel(ftl::cuda::TextureObject<float4> norm,
         ftl::cuda::TextureObject<float4> output,
         ftl::rgbd::Camera camera, float4x4 pose, float thresh) {
diff --git a/components/renderers/cpp/src/tri_render.cpp b/components/renderers/cpp/src/tri_render.cpp
index 5912b6480b109db2c3cce960ae5bca6abe6531f8..5d38742cf979575fd24388689b6cb5899821af65 100644
--- a/components/renderers/cpp/src/tri_render.cpp
+++ b/components/renderers/cpp/src/tri_render.cpp
@@ -609,6 +609,18 @@ bool Triangular::render(ftl::rgbd::VirtualSource *src, ftl::rgbd::Frame &out) {
 	// Reprojection of colours onto surface
 	_renderChannel(out, Channel::Colour, Channel::Colour, stream_);
 
+	if (value("cool_effect", false)) {
+		auto pose = params.m_viewMatrixInverse.getFloat3x3();
+		auto col = parseCUDAColour(value("cool_effect_colour", std::string("#2222ff")));
+
+		ftl::cuda::cool_blue(
+			out.getTexture<float4>(Channel::Normals),
+			out.getTexture<uchar4>(Channel::Colour),
+			col, pose,
+			stream_	
+		);
+	}
+
 	if (value("show_bad_colour", false)) {
 		ftl::cuda::show_missing_colour(
 			out.getTexture<float>(Channel::Depth),