소스 검색

Add instancing lambert example

WestLangley 7 년 전
부모
커밋
53b1867a30
2개의 변경된 파일410개의 추가작업 그리고 0개의 파일을 삭제
  1. 1 0
      examples/files.js
  2. 409 0
      examples/webgl_buffergeometry_instancing_lambert.html

+ 1 - 0
examples/files.js

@@ -284,6 +284,7 @@ var files = {
 		"webgl_buffergeometry_instancing_billboards",
 		"webgl_buffergeometry_instancing_dynamic",
 		"webgl_buffergeometry_instancing_interleaved_dynamic",
+		"webgl_buffergeometry_instancing_lambert",
 		"webgl_buffergeometry_lines",
 		"webgl_buffergeometry_lines_indexed",
 		"webgl_buffergeometry_points",

+ 409 - 0
examples/webgl_buffergeometry_instancing_lambert.html

@@ -0,0 +1,409 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+	<title>three.js webgl - instancing - lambert shader</title>
+	<meta charset="utf-8">
+	<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+	<style>
+		body {
+			color: #ffffff;
+			font-family: Monospace;
+			font-size: 13px;
+			text-align: center;
+			font-weight: bold;
+			background-color: #000000;
+			margin: 0px;
+			overflow: hidden;
+		}
+
+		#info {
+			position: absolute;
+			top: 0px;
+			width: 100%;
+			padding: 5px;
+		}
+
+		a {
+			color: #ffffff;
+		}
+
+		#notSupported {
+			width: 50%;
+			margin: auto;
+			border: 2px red solid;
+			margin-top: 20px;
+			padding: 10px;
+		}
+	</style>
+</head>
+<body>
+
+	<div id="container"></div>
+	<div id="info">
+		<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - instancing - lambert shader
+		<div id="notSupported" style="display:none">Sorry your graphics card + browser does not support hardware instancing</div>
+	</div>
+
+	<script src="../build/three.js"></script>
+	<script src="js/Detector.js"></script>
+	<script src="js/libs/stats.min.js"></script>
+
+	<script src="js/controls/OrbitControls.js"></script>
+	<script src="js/CurveExtras.js"></script>
+
+
+	<script>
+
+		if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
+
+		THREE.CustomShaderLib = {
+
+			customDepthRGBA: { // this is a cut-and-paste of the depth shader -- modified to accommodate instancing for this app
+
+				uniforms: THREE.ShaderLib.depth.uniforms,
+
+				vertexShader:
+					`
+					// instanced
+					#ifdef INSTANCED
+
+						attribute vec3 instanceOffset;
+						attribute float instanceScale;
+
+					#endif
+
+					#include <common>
+					#include <uv_pars_vertex>
+					#include <displacementmap_pars_vertex>
+					#include <morphtarget_pars_vertex>
+					#include <skinning_pars_vertex>
+					#include <logdepthbuf_pars_vertex>
+					#include <clipping_planes_pars_vertex>
+
+					void main() {
+
+						#include <uv_vertex>
+
+						#include <skinbase_vertex>
+
+						#ifdef USE_DISPLACEMENTMAP
+
+							#include <beginnormal_vertex>
+							#include <morphnormal_vertex>
+							#include <skinnormal_vertex>
+
+						#endif
+
+						#include <begin_vertex>
+
+						// instanced
+						#ifdef INSTANCED
+
+							transformed *= instanceScale;
+							transformed = transformed + instanceOffset;
+
+						#endif
+
+						#include <morphtarget_vertex>
+						#include <skinning_vertex>
+						#include <displacementmap_vertex>
+						#include <project_vertex>
+						#include <logdepthbuf_vertex>
+						#include <clipping_planes_vertex>
+
+					}
+				`,
+
+				fragmentShader: THREE.ShaderChunk.depth_frag
+
+			},
+
+			lambert: { // this is a cut-and-paste of the lambert shader -- modified to accommodate instancing for this app
+
+				uniforms: THREE.ShaderLib.lambert.uniforms,
+
+				vertexShader:
+					`
+					#define LAMBERT
+
+					#ifdef INSTANCED
+						attribute vec3 instanceOffset;
+						attribute vec3 instanceColor;
+						attribute float instanceScale;
+					#endif
+
+					varying vec3 vLightFront;
+
+					#ifdef DOUBLE_SIDED
+
+						varying vec3 vLightBack;
+
+					#endif
+
+					#include <common>
+					#include <uv_pars_vertex>
+					#include <uv2_pars_vertex>
+					#include <envmap_pars_vertex>
+					#include <bsdfs>
+					#include <lights_pars_begin>
+					#include <lights_pars_maps>
+					#include <color_pars_vertex>
+					#include <fog_pars_vertex>
+					#include <morphtarget_pars_vertex>
+					#include <skinning_pars_vertex>
+					#include <shadowmap_pars_vertex>
+					#include <logdepthbuf_pars_vertex>
+					#include <clipping_planes_pars_vertex>
+
+					void main() {
+
+						#include <uv_vertex>
+						#include <uv2_vertex>
+						#include <color_vertex>
+
+						// vertex colors instanced
+						#ifdef INSTANCED
+							#ifdef USE_COLOR
+								vColor.xyz = instanceColor.xyz;
+							#endif
+						#endif
+
+						#include <beginnormal_vertex>
+						#include <morphnormal_vertex>
+						#include <skinbase_vertex>
+						#include <skinnormal_vertex>
+						#include <defaultnormal_vertex>
+
+						#include <begin_vertex>
+
+						// position instanced
+						#ifdef INSTANCED
+							transformed *= instanceScale;
+							transformed = transformed + instanceOffset;
+						#endif
+
+						#include <morphtarget_vertex>
+						#include <skinning_vertex>
+						#include <project_vertex>
+						#include <logdepthbuf_vertex>
+						#include <clipping_planes_vertex>
+
+						#include <worldpos_vertex>
+						#include <envmap_vertex>
+						#include <lights_lambert_vertex>
+						#include <shadowmap_vertex>
+						#include <fog_vertex>
+
+					}
+					`,
+
+				fragmentShader: THREE.ShaderLib.lambert.fragmentShader
+
+			}
+
+		};
+
+		//
+
+		var mesh, renderer, scene, camera, controls;
+		var stats;
+
+		init();
+		animate();
+
+		function init() {
+
+			renderer = new THREE.WebGLRenderer( { antialias: true } );
+			renderer.setSize( window.innerWidth, window.innerHeight );
+			renderer.shadowMap.enabled = true;
+			document.body.appendChild( renderer.domElement );
+
+			renderer.gammaOutput = true;
+
+			scene = new THREE.Scene();
+
+			scene.fog = new THREE.FogExp2( 0x000000, 0.004 );
+			renderer.setClearColor( scene.fog.color, 1 );
+
+			camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 1000 );
+			camera.position.set( 80, 40, 80 );
+
+			scene.add( camera );
+
+			controls = new THREE.OrbitControls( camera, renderer.domElement );
+			controls.enableZoom = false;
+			controls.maxPolarAngle = Math.PI / 2;
+
+			scene.add( new THREE.AmbientLight( 0xffffff, 0.7 ) );
+
+			var light = new THREE.DirectionalLight( 0xffffff, 0.4 );
+			light.position.set( 50, 40, 0 );
+
+			light.castShadow = true;
+			light.shadow.camera.left = - 40;
+			light.shadow.camera.right = 40;
+			light.shadow.camera.top = 40;
+			light.shadow.camera.bottom = - 40;
+			light.shadow.camera.near = 10;
+			light.shadow.camera.far = 180;
+
+			light.shadow.bias = - 0.001;
+			light.shadow.mapSize.width = 512;
+			light.shadow.mapSize.height = 512;
+
+			scene.add( light );
+
+			// light shadow camera helper
+			//light.shadowCameraHelper = new THREE.CameraHelper( light.shadow.camera );
+			//scene.add( light.shadowCameraHelper );
+
+
+			// instanced buffer geometry
+
+			var geometry = new THREE.InstancedBufferGeometry();
+			geometry.copy( new THREE.TorusBufferGeometry( 2, 0.5, 8, 128 ) );
+
+			const INSTANCES = 256;
+
+			var knot = new THREE.Curves.TorusKnot( 10 );
+			var positions = knot.getSpacedPoints( INSTANCES );
+
+			var offsets = new Float32Array( INSTANCES * 3 ); // xyz
+			var colors = new Float32Array( INSTANCES * 3 ); // rgb
+			var scales = new Float32Array( INSTANCES * 1 ); // s
+
+			var color = new THREE.Color();
+
+			for ( var i = 0, l = INSTANCES; i < l; i ++ ) {
+
+				var index = 3 * i;
+
+				// per-instance position offset
+				offsets[ index ] = positions[ i ].x;
+				offsets[ index + 1 ] = positions[ i ].y;
+				offsets[ index + 2 ] = positions[ i ].z;
+
+				// per-instance color tint - optional
+				colors[ index ] = 1;
+				colors[ index + 1 ] = 1;
+				colors[ index + 2 ] = 1;
+
+				// per-instance scale variation
+				scales[ i ] = 1 + 0.5 * Math.sin( 32 * Math.PI * i / INSTANCES );
+
+			}
+
+			geometry.addAttribute( 'instanceOffset', new THREE.InstancedBufferAttribute( offsets, 3 ) );
+			geometry.addAttribute( 'instanceColor', new THREE.InstancedBufferAttribute( colors, 3 ) );
+			geometry.addAttribute( 'instanceScale', new THREE.InstancedBufferAttribute( scales, 1 ) );
+
+
+			// material
+
+			var envMap = new THREE.TextureLoader().load( `textures/metal.jpg`, function ( texture ) {
+
+				texture.mapping = THREE.SphericalReflectionMapping;
+
+			} );
+
+			var shader = THREE.CustomShaderLib[ 'lambert' ];
+
+			var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
+
+			uniforms[ "diffuse" ].value.set( 0xffb54a );
+			uniforms[ "envMap" ].value = envMap;
+			uniforms[ "reflectivity" ].value = 1;
+
+			// defines - Since we are reusing the ShaderChunks, we must specify the required defines.
+			// The renderer does not set these defines for ShaderMaterial
+
+			var defines = {
+				'INSTANCED': "",
+				'USE_ENVMAP': "",
+				'ENVMAP_TYPE_SPHERE': "",
+				'ENVMAP_MODE_REFLECTION': "",
+				'ENVMAP_BLENDING_MULTIPLY': "",
+			};
+
+			var material = new THREE.ShaderMaterial( {
+
+				// Material and ShaderMaterial properties can be set here -- except opacity
+				// the Lambert-properties must be set in the uniforms or defines
+
+				defines: defines,
+				uniforms: uniforms,
+				vertexShader: shader.vertexShader,
+				fragmentShader: shader.fragmentShader,
+
+				vertexColors: THREE.VertexColors,
+				lights: true,
+				fog: true
+
+			} );
+
+
+			// custom depth material - required for instanced shadows
+
+			var shader = THREE.CustomShaderLib[ 'customDepthRGBA' ];
+
+			var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
+
+			var customDepthMaterial = new THREE.ShaderMaterial( {
+
+				defines: {
+					'INSTANCED': "",
+					'DEPTH_PACKING': THREE.RGBADepthPacking
+				},
+				uniforms: uniforms,
+				vertexShader: shader.vertexShader,
+				fragmentShader: shader.fragmentShader
+
+			} );
+
+			//
+
+			mesh = new THREE.Mesh( geometry, material );
+			mesh.scale.set( 1, 1, 2 );
+			mesh.castShadow = true;
+			mesh.receiveShadow = true;
+			mesh.customDepthMaterial = customDepthMaterial;
+			mesh.frustumCulled = false;
+
+			scene.add( mesh );
+
+			//
+
+			var ground = new THREE.Mesh(
+				new THREE.PlaneBufferGeometry( 800, 800 ).rotateX( - Math.PI / 2 ),
+				new THREE.MeshPhongMaterial( { color: 0x888888 } )
+			);
+			ground.position.set( 0, - 40, 0 );
+			ground.receiveShadow = true;
+
+			scene.add( ground );
+
+			//
+
+			stats = new Stats();
+			document.body.appendChild( stats.dom );
+
+		}
+
+		function animate() {
+
+			requestAnimationFrame( animate );
+
+			mesh.rotation.y += 0.005;
+
+			stats.update();
+
+			renderer.render( scene, camera );
+
+		}
+
+
+	</script>
+
+</body>
+
+</html>