Visual experiment
Unsharp Masking the Depth Buffer
It’s been a while since I worked on an extension to three.js – thje webGL 3D engine developed by Mrdoob – to permit to doing post processing more easily on the 3D result.
Check ‘Unsharp Masking the depth buffer’ here !
Post processing
This technique is commonly used in video games and motion design to improve the final rendering. For example, Glow, Screen Space Ambient Occlusion (SSOA) or Depth Of Field (DOF) are post process effects. you can also use the post processing to correct the rendering’s color, apply deformation warping or filter the image with pixelation, etc …
To do so, we need to apply shaders and textures and to combine them.
Unsharp Masking the Depth Buffer
The first example using the PP.js extension is the Unsharp Maskingthe Depth Buffer which enhances the perception of the elements of a 3D image. This traitmeent is also very close to the SSOA, but at a lower computational cost. To understand this technique, I suggest you to read this article before: Image enhancement by unsharp masking the depth buffer.
The technique
To achieve this treatment, we need to render the 3D scene (diffuse texture) and the depth buffer. Then we apply a gaussian blur on the depth buffer. The difference between the blurred depth buffer and texture diffuse is called spacial importance.
Properly used, this new texture applied to the diffuse texture will help to highlight the difference in depth and contour of objects.

from left/top to right/bottom: diffuse texture, depth texture, depth texture blured on x, depth texture blured, final result
The effect of blur on the texture depth is performed in two passes (horizontal and vertical).
Implémentation: Three.js and PP.js
To boot PP is simple:
PP.init({ renderer: renderer, scene: scene, camera: camera, guiEnabled: true}); PP.debug.init(); PP.addTexture('tDiffuse') .addTexture('tDepth') .loadShader('blurTriangleX', {radius: 25.0}) .loadShader('blurTriangleY', {radius: 25.0}) .loadShader('unsharpMasking', {bias: -6.0});
PP.init() initialising the extension. Then we transmit the Three.js’s infos.
Thanks to PP.addTexture() and PP.loaderShader(), we can create size screen textures easely and load shaders that we will use in the rendering loop.
PP.start(); // Render color for( i = 0; i < nobjects; i++ ) objects[i].materials = [ material ]; PP.renderScene().toTexture('tDiffuse'); PP.get('unsharpMasking').set('textureIn').toTexture('tDiffuse'); // Render depth for( i = 0; i < nobjects; i++ ) objects[i].materials = [ material_depth ]; PP.renderScene().toTexture('tDepth'); PP.get('unsharpMasking').set('tDepth').toTexture('tDepth'); // Render blur PP.get('blurTriangleX').set('textureIn').toTexture('tDepth'); PP.renderShader('blurTriangleX').toTexture('blurTriangleY'); PP.renderShader('blurTriangleY'); // Render Unsharp masking PP.get('unsharpMasking').set('tBlur').toTexture('blurTriangleY'); PP.renderShader('unsharpMasking').toScene();
In the rendering loop, methods PP.renderScene() and PP.renderShader() comput the effects and transmit to the following effect the result of the effect before.
Conclusion
Thanks to Three.js and PP.js, post processing with multiple shaders is simple. I would later come back on PP.js with new examples. The PP.js extension will be downloadable on GitHub when it is fully operational.
I made two examples using this effect:
You can show/hide the effect and control the uniforms parameters with the control pannel.