Silhouette (Filter)

worldNormal with Laplace filter

by jmcjc5u

HTML

<div id="info">
  <br> Silhouette
  <br> (worldNormalPlot + Laplace filter)
</div>
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<!-- shader for worldNormal Plot -->
<script id="vsNormal" type="x-shader/x-vertex">
  varying vec3 vNormal;
  void main() { 
  	gl_Position = projectionMatrix* modelViewMatrix * vec4( position, 1.0); 
    //vNormal = normalMatrix*normal;
    vNormal = normal;
  }
</script>
<script id="fsNormal" type="x-shader/x-fragment">
  varying vec3 vNormal; 
  void main() {
  	vec3 color = (vNormal+1.0)/2.;
  	gl_FragColor = vec4 (color,1);
  }
</script>

<!-- shader for Lapace filter -->
<!-- with background discard  -->

<script id="vsFilter" type="x-shader/x-vertex">
  varying vec2 vUv; 
  void main() { 
    gl_Position = projectionMatrix* modelViewMatrix * vec4( position, 1.0); 
    vUv = uv; 
  }
</script>
<script id="fsFilter" type="x-shader/x-fragment">
  uniform sampler2D mytex; 
  uniform int imageSize;
  varying vec2 vUv; 
  //http://stackoverflow.com/questions/15262729/const-float-array-in-webgl-shader 
  void main() { 
  float step_w = 1.0/float(imageSize); 
  float step_h = 1.0/float(imageSize); 
	// Laplace filter
	float kernel[9]; 
    kernel[0] = kernel[2] = kernel[6] = kernel[8] = 0.0/1.0; 
    kernel[1] = kernel[3] = kernel[5] = kernel[7] = 1.0/1.0; 
    kernel[4] = -4.0/1.0; 
  vec2 offset[9]; 
  offset[0]=vec2(-step_w, -step_h); 
  offset[1]=vec2(0.0, -step_h); offset[2]= vec2(step_w, -step_h), 
  offset[3]=vec2(-step_w, 0.0), offset[4]=vec2(0.0, 0.0), offset[5]=vec2(step_w, 0.0), 
  offset[6]=vec2(-step_w, step_h), offset[7]=vec2(0.0, step_h), offset[8]=vec2(step_w, step_h); 
  vec3 sum= vec3(0.0); 
 	for (int i=0 ; i < 9; i++) { 
    	vec3 tmp=texture2D (mytex, vUv+offset[i]).rgb; 
      sum += tmp*kernel[i]; 
 }

 if ((sum.r+sum.g+sum.b)/3.0 < 0.1) 
  		discard;
 else 
  		gl_FragColor = vec4 (0,0,0, 1.0); 
}
</script>

CSS

body {
	  background-color: #fff;
	  color: #111;
	  margin: 0px;
	  overflow: hidden;
	  font-family: Monospace;
	  font-size: 20px;
	  position: absolute;
	}
  
	#info {
	  position: absolute;
	  top: 0px;
	  width: 100%;
	  padding: 5px;
	  text-align: center;
	  color: #ffff00
	}

JavaScript

var scene, renderer, camera;
var material_shh;
var sceneRTT, cameraRTT;
var renderTarget;

init();
animate();

function init() {

  renderer = new THREE.WebGLRenderer({
    antialias: true
  });
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);
  renderer.setClearColor(0x888888);
  renderer.autoClear = false;
  
  scene = new THREE.Scene();

  camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);
  camera.position.set (0, 80, 400);
  
  let controls = new THREE.OrbitControls(camera, renderer.domElement);

  var pointLight = new THREE.PointLight(0xffffff);
  pointLight.position.set(0, 300, 200);
  scene.add(pointLight);

  var ambientLight = new THREE.AmbientLight(0x555555);
  scene.add(ambientLight);

	window.addEventListener('resize', onWindowResize, false);

  //////////////////////////////////////////////////////////////
	var normalVS = document.getElementById('vsNormal').innerHTML;
  var normalFS = document.getElementById('fsNormal').innerHTML;
	var material_shh_normal = new THREE.ShaderMaterial({
    vertexShader: normalVS,
    fragmentShader: normalFS
  });

  scene0 = new THREE.Scene();
	var mesh = new THREE.Mesh (new THREE.TorusKnotGeometry( 10, 3, 100, 16 ),
  	material_shh_normal);
  mesh.scale.set (5,5,5);
  scene0.add (mesh);
    
	////////////////////////////////////////////////////////

  renderTarget = new THREE.WebGLRenderTarget( 
   	1024,1024,  // size of the FBO
		{ minFilter: THREE.LinearFilter, magFilter: THREE.NearestFilter, format: THREE.RGBFormat } 
		);

	  var uniforms = {
    imageSize: {
    	type: 'i',
      value: 1024
    },
    mytex: {
    	type: 't',
      value: renderTarget.texture
    }
  };

	var filterVS = document.getElementById('vsFilter').innerHTML;
  var filterFS = document.getElementById('fsFilter').innerHTML;
	material_shh = new THREE.ShaderMaterial({
    uniforms: uniforms,
    vertexShader: filterVS,
    fragmentShader:...