浏览代码

Merge pull request #20222 from DavidPeicho/feature/volume-rendering-jittering

examples: volume cloud: add jittering to reduce sampling artefacts
Mr.doob 4 年之前
父节点
当前提交
2cef8dc938
共有 1 个文件被更改,包括 55 次插入5 次删除
  1. 55 5
      examples/webgl2_volume_cloud.html

+ 55 - 5
examples/webgl2_volume_cloud.html

@@ -100,7 +100,7 @@
 
 				// Material
 
-				const vertexShader = `#version 300 es
+				const vertexShader = `
 					in vec3 position;
 
 					uniform mat4 modelMatrix;
@@ -121,7 +121,7 @@
 					}
 				`;
 
-				const fragmentShader = `#version 300 es
+				const fragmentShader = `
 					precision highp float;
 					precision highp sampler3D;
 
@@ -140,6 +140,22 @@
 					uniform float range;
 					uniform float opacity;
 					uniform float steps;
+					uniform float frame;
+
+					uint wang_hash(uint seed)
+					{
+							seed = (seed ^ 61u) ^ (seed >> 16u);
+							seed *= 9u;
+							seed = seed ^ (seed >> 4u);
+							seed *= 0x27d4eb2du;
+							seed = seed ^ (seed >> 15u);
+							return seed;
+					}
+
+					float randomFloat(inout uint seed)
+					{
+							return float(wang_hash(seed)) / 4294967296.;
+					}
 
 					vec2 hitBox( vec3 orig, vec3 dir ) {
 						const vec3 box_min = vec3( - 0.5 );
@@ -164,7 +180,6 @@
 					}
 
 					void main(){
-
 						vec3 rayDir = normalize( vDirection );
 						vec2 bounds = hitBox( vOrigin, rayDir );
 
@@ -177,6 +192,15 @@
 						float delta = min( inc.x, min( inc.y, inc.z ) );
 						delta /= steps;
 
+						#ifdef JITTER
+							// Nice little seed from
+							// https://blog.demofox.org/2020/05/25/casual-shadertoy-path-tracing-1-basic-camera-diffuse-emissive/
+							uint seed = uint(gl_FragCoord.x) * uint(1973) + uint(gl_FragCoord.y) * uint(9277) + uint(frame) * uint(26699);
+							vec3 size = vec3(textureSize(map, 0));
+							float randNum = randomFloat(seed) * 2.0 - 1.0;
+							p += rayDir * randNum * (1.0 / size);
+						#endif
+
 						vec4 ac = vec4( base, 0.0 );
 
 						for ( float t = bounds.x; t < bounds.y; t += delta ) {
@@ -213,20 +237,31 @@
 						threshold: { value: 0.25 },
 						opacity: { value: 0.25 },
 						range: { value: 0.1 },
-						steps: { value: 100 }
+						steps: { value: 100 },
+						frame: { value: 0 }
+					},
+					defines: {
+						JITTER: true
 					},
 					vertexShader,
 					fragmentShader,
 					side: THREE.BackSide,
 					transparent: true
 				} );
+				material.glslVersion = '300 es';
 
 				mesh = new THREE.Mesh( geometry, material );
 				scene.add( mesh );
 
 				//
 
-				const parameters = { threshold: 0.25, opacity: 0.25, range: 0.1, steps: 100 };
+				const parameters = {
+					threshold: 0.25,
+					opacity: 0.25,
+					range: 0.1,
+					steps: 100,
+					useJittering: true
+				};
 
 				function update() {
 
@@ -235,6 +270,18 @@
 					material.uniforms.range.value = parameters.range;
 					material.uniforms.steps.value = parameters.steps;
 
+					if ( ! material.defines.JITTER && parameters.useJittering ) {
+
+						material.defines.JITTER = true;
+						material.needsUpdate = true;
+
+					} else if ( material.defines.JITTER && ! parameters.useJittering ) {
+
+						delete material.defines.JITTER;
+						material.needsUpdate = true;
+
+					}
+
 				}
 
 				const gui = new GUI();
@@ -242,6 +289,7 @@
 				gui.add( parameters, 'opacity', 0, 1, 0.01 ).onChange( update );
 				gui.add( parameters, 'range', 0, 1, 0.01 ).onChange( update );
 				gui.add( parameters, 'steps', 0, 200, 1 ).onChange( update );
+				gui.add( parameters, 'useJittering' ).onChange( update );
 
 				window.addEventListener( 'resize', onWindowResize, false );
 
@@ -263,6 +311,8 @@
 				mesh.material.uniforms.cameraPos.value.copy( camera.position );
 				mesh.rotation.y = - performance.now() / 7500;
 
+				mesh.material.uniforms.frame.value ++;
+
 				renderer.render( scene, camera );
 
 			}