5 <title>three.js webgl - post processing - Scalable Ambient Occlusion (SAO)</title>
7 <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
10 background-color: #000000;
13 font-family:Monospace;
31 z-index: 1 !important; /* FIX DAT.GUI */
36 <script src="../build/three.js"></script>
38 <script src="js/postprocessing/EffectComposer.js"></script>
39 <script src="js/postprocessing/RenderPass.js"></script>
40 <script src="js/postprocessing/ShaderPass.js"></script>
41 <script src="js/postprocessing/SAOPass.js"></script>
43 <script src="js/shaders/CopyShader.js"></script>
44 <script src="js/shaders/SAOShader.js"></script>
45 <script src="js/shaders/DepthLimitedBlurShader.js"></script>
46 <script src="js/shaders/UnpackDepthRGBAShader.js"></script>
48 <script src="js/Detector.js"></script>
49 <script src="js/libs/stats.min.js"></script>
50 <script src='js/libs/dat.gui.min.js'></script>
53 <a href="http://threejs.org" target="_blank">three.js</a> - Scalable Ambient Occlusion (SAO) shader by <a href="http://clara.io">Ben Houston</a> / Post-processing pass by <a href="http://ludobaka.github.io">Ludobaka</a>
58 if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
61 var camera, scene, renderer;
62 var depthMaterial, saoMaterial, saoModulateMaterial, normalMaterial, vBlurMaterial, hBlurMaterial, copyMaterial;
63 var depthRenderTarget, normalRenderTarget, saoRenderTarget, beautyRenderTarget, blurIntermediateRenderTarget;
64 var composer, renderPass, saoPass, copyPass;
76 saoBlurDepthCutoff: 0.01
78 var supportsDepthTextureExtension = false;
86 container = document.createElement( 'div' );
87 document.body.appendChild( container );
89 var width = window.innerWidth || 1;
90 var height = window.innerHeight || 1;
91 var devicePixelRatio = window.devicePixelRatio || 1;
93 renderer = new THREE.WebGLRenderer( { antialias: true } );
94 renderer.setClearColor( 0xa0a0a0 );
95 renderer.setPixelRatio( devicePixelRatio );
96 renderer.setSize( width, height );
97 document.body.appendChild( renderer.domElement );
99 camera = new THREE.PerspectiveCamera( 65, width / height, 3, 10 );
100 camera.position.z = 7;
102 scene = new THREE.Scene();
104 group = new THREE.Object3D();
107 var light = new THREE.PointLight( 0xddffdd, 0.8 );
108 light.position.z = 70;
109 light.position.y = -70;
110 light.position.x = -70;
113 var light2 = new THREE.PointLight( 0xffdddd, 0.8 );
114 light2.position.z = 70;
115 light2.position.x = -70;
116 light2.position.y = 70;
119 var light3 = new THREE.PointLight( 0xddddff, 0.8 );
120 light3.position.z = 70;
121 light3.position.x = 70;
122 light3.position.y = -70;
125 var light3 = new THREE.AmbientLight( 0xffffff, 0.05 );
128 var geometry = new THREE.SphereBufferGeometry( 3, 48, 24 );
129 for ( var i = 0; i < 120; i ++ ) {
131 var material = new THREE.MeshStandardMaterial();
132 material.roughness = 0.5 * Math.random() + 0.25;
133 material.metalness = 0;
134 material.color.setHSL( Math.random(), 1.0, 0.3 );
136 var mesh = new THREE.Mesh( geometry, material );
137 mesh.position.x = Math.random() * 4 - 2;
138 mesh.position.y = Math.random() * 4 - 2;
139 mesh.position.z = Math.random() * 4 - 2;
140 mesh.rotation.x = Math.random();
141 mesh.rotation.y = Math.random();
142 mesh.rotation.z = Math.random();
144 mesh.scale.x = mesh.scale.y = mesh.scale.z = Math.random() * 0.2 + 0.05;
149 container.appendChild( stats.dom );
151 composer = new THREE.EffectComposer(renderer);
152 renderPass = new THREE.RenderPass(scene, camera);
153 composer.addPass(renderPass);
154 saoPass = new THREE.SAOPass(scene, camera, false, true);
155 saoPass.renderToScreen = true;
156 composer.addPass(saoPass);
159 var gui = new dat.GUI();
160 gui.add( saoPass.params, "output", {
161 'Beauty': THREE.SAOPass.OUTPUT.Beauty,
162 'Beauty+SAO': THREE.SAOPass.OUTPUT.Default,
163 'SAO': THREE.SAOPass.OUTPUT.SAO,
164 'Depth': THREE.SAOPass.OUTPUT.Depth,
165 'Normal': THREE.SAOPass.OUTPUT.Normal
167 gui.add( saoPass.params, "saoBias", -1, 1 );
168 gui.add( saoPass.params, "saoIntensity", 0, 1 );
169 gui.add( saoPass.params, "saoScale", 0, 10 );
170 gui.add( saoPass.params, "saoKernelRadius", 1, 100 );
171 gui.add( saoPass.params, "saoMinResolution", 0, 1 );
172 gui.add( saoPass.params, "saoBlur" );
173 gui.add( saoPass.params, "saoBlurRadius", 0, 200 );
174 gui.add( saoPass.params, "saoBlurStdDev", 0.5, 150 );
175 gui.add( saoPass.params, "saoBlurDepthCutoff", 0.0, 0.1 );
177 window.addEventListener( 'resize', onWindowResize, false );
180 function onWindowResize() {
182 var width = window.innerWidth || 1;
183 var height = window.innerHeight || 1;
184 var devicePixelRatio = window.devicePixelRatio || 1;
186 camera.aspect = width / height;
187 camera.updateProjectionMatrix();
188 renderer.setSize( width, height );
190 composer.setSize( width, height );
196 requestAnimationFrame( animate );
203 var prevStdDev, prevNumSamples;
206 var timer = performance.now();
207 group.rotation.x = timer * 0.0002;
208 group.rotation.y = timer * 0.0001;