浏览代码

adding example for box projected cube environment mapping

Sneha Belkhale 6 年之前
父节点
当前提交
bedee743b3
共有 2 个文件被更改,包括 485 次插入0 次删除
  1. 1 0
      examples/files.js
  2. 484 0
      examples/webgl_box_projected_cubemap_environment_mapping.html

+ 1 - 0
examples/files.js

@@ -4,6 +4,7 @@ var files = {
 		"webgl_animation_keyframes",
 		"webgl_animation_keyframes",
 		"webgl_animation_skinning_blending",
 		"webgl_animation_skinning_blending",
 		"webgl_animation_skinning_morph",
 		"webgl_animation_skinning_morph",
+		"webgl_box_projected_cubemap_environment_mapping",
 		"webgl_camera",
 		"webgl_camera",
 		"webgl_camera_array",
 		"webgl_camera_array",
 		"webgl_camera_cinematic",
 		"webgl_camera_cinematic",

+ 484 - 0
examples/webgl_box_projected_cubemap_environment_mapping.html

@@ -0,0 +1,484 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - box projected cubemap environment mapping</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: #888888;
+				font-family:Monospace;
+				font-size:13px;
+
+				background-color: #000;
+				margin: 0px;
+				overflow: hidden;
+			}
+
+			#info {
+				position: absolute;
+				top: 0px;
+				width: 500px;
+				left: calc(50% - 250px);
+				text-align: center;
+			}
+
+			a {
+				color: #00f;
+			}
+		</style>
+	</head>
+	<body>
+
+		<div id="container"></div>
+		<div id="info"><a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - box projected cubemap environment mapping
+		</div>
+		<script src="../build/three.js"></script>
+		<script src="js/objects/Reflector.js"></script>
+		<script src="js/controls/OrbitControls.js"></script>
+		<script src="js/libs/dat.gui.min.js"></script>
+		<script src="js/lights/RectAreaLightUniformsLib.js"></script>
+
+		<script>
+
+			// shader injection for box projected cube environment mapping
+			var worldposReplace = `
+			#define BOX_PROJECTED_ENV_MAP
+
+			#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )
+
+				vec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );
+
+				#ifdef BOX_PROJECTED_ENV_MAP
+
+					vWorldPosition = worldPosition.xyz;
+
+				#endif
+
+			#endif
+			`
+
+			var envmapParsReplace = `
+			#define BOX_PROJECTED_ENV_MAP
+
+			#if defined( USE_ENVMAP ) || defined( PHYSICAL )
+
+				uniform float reflectivity;
+				uniform float envMapIntensity;
+
+			#endif
+
+			#ifdef USE_ENVMAP
+
+				#ifdef BOX_PROJECTED_ENV_MAP
+
+				  uniform vec3 cubeMapSize;
+				  uniform vec3 cubeMapPos;
+				  varying vec3 vWorldPosition;
+
+				  vec3 parallaxCorrectNormal( vec3 v, vec3 cubeSize, vec3 cubePos ) {
+
+				    vec3 nDir = normalize( v );
+				    vec3 rbmax = (   .5 * ( cubeSize - cubePos ) - vWorldPosition ) / nDir;
+				    vec3 rbmin = ( - .5 * ( cubeSize - cubePos ) - vWorldPosition ) / nDir;
+
+				    vec3 rbminmax;
+				    rbminmax.x = ( nDir.x > 0. ) ? rbmax.x : rbmin.x;
+				    rbminmax.y = ( nDir.y > 0. ) ? rbmax.y : rbmin.y;
+				    rbminmax.z = ( nDir.z > 0. ) ? rbmax.z : rbmin.z;
+
+				    float correction = min( min( rbminmax.x, rbminmax.y ), rbminmax.z );
+				    vec3 boxIntersection = vWorldPosition + nDir * correction;
+
+				    return boxIntersection - cubePos;
+				  }
+
+				#endif
+
+				#if ! defined( PHYSICAL ) && ( defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) )
+
+					varying vec3 vWorldPosition;
+
+				#endif
+
+				#ifdef ENVMAP_TYPE_CUBE
+
+					uniform samplerCube envMap;
+
+				#else
+
+					uniform sampler2D envMap;
+
+				#endif
+
+				uniform float flipEnvMap;
+				uniform int maxMipLevel;
+
+				#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( PHYSICAL )
+
+					uniform float refractionRatio;
+
+				#else
+
+					varying vec3 vReflect;
+
+				#endif
+
+			#endif
+			`;
+
+			var envmapPhysicalParsReplace = `
+			#if defined( USE_ENVMAP ) && defined( PHYSICAL )
+
+				vec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {
+					vec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );
+					#ifdef ENVMAP_TYPE_CUBE
+
+			    	vec3 worldNormalFinal = worldNormal;
+
+			    #ifdef BOX_PROJECTED_ENV_MAP
+
+			    	worldNormalFinal = parallaxCorrectNormal( worldNormal, cubeMapSize, cubeMapPos );
+
+					#endif
+
+					vec3 queryVec = vec3( flipEnvMap * worldNormalFinal.x, worldNormalFinal.yz );
+
+					#ifdef TEXTURE_LOD_EXT
+
+						vec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );
+
+					#else
+
+						vec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );
+
+					#endif
+
+						envMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;
+
+					#elif defined( ENVMAP_TYPE_CUBE_UV )
+
+						vec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );
+						vec4 envMapColor = textureCubeUV( envMap, queryVec, 1.0 );
+
+					#else
+
+						vec4 envMapColor = vec4( 0.0 );
+
+					#endif
+
+					return PI * envMapColor.rgb * envMapIntensity;
+				}
+
+				float getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {
+					float maxMIPLevelScalar = float( maxMIPLevel );
+					float desiredMIPLevel = maxMIPLevelScalar + 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );
+					return clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );
+				}
+
+				vec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {
+
+					#ifdef ENVMAP_MODE_REFLECTION
+
+						vec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );
+
+					#else
+
+						vec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );
+
+					#endif
+
+					reflectVec = inverseTransformDirection( reflectVec, viewMatrix );
+					float specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );
+
+					#ifdef ENVMAP_TYPE_CUBE
+
+			    	vec3 reflectVecFinal = reflectVec;
+
+			    #ifdef BOX_PROJECTED_ENV_MAP
+
+			     reflectVecFinal = parallaxCorrectNormal( reflectVec, cubeMapSize, cubeMapPos );
+
+			    #endif
+
+					vec3 queryReflectVec = vec3( flipEnvMap * reflectVecFinal.x, reflectVecFinal.yz );
+
+					#ifdef TEXTURE_LOD_EXT
+
+						vec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );
+
+					#else
+
+						vec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );
+
+					#endif
+
+					envMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;
+
+					#elif defined( ENVMAP_TYPE_CUBE_UV )
+
+						vec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );
+						vec4 envMapColor = textureCubeUV( envMap, queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent ));
+
+					#elif defined( ENVMAP_TYPE_EQUIREC )
+
+						vec2 sampleUV;
+						sampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;
+						sampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;
+
+						#ifdef TEXTURE_LOD_EXT
+
+							vec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );
+
+						#else
+
+							vec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );
+
+						#endif
+
+						envMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;
+					#elif defined( ENVMAP_TYPE_SPHERE )
+
+						vec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );
+
+						#ifdef TEXTURE_LOD_EXT
+
+							vec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );
+
+						#else
+
+							vec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );
+
+						#endif
+
+						envMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;
+
+					#endif
+
+					return envMapColor.rgb * envMapIntensity;
+				}
+				#endif
+				`;
+
+			// scene size
+			var WIDTH = window.innerWidth;
+			var HEIGHT = window.innerHeight;
+
+			// camera
+			var VIEW_ANGLE = 45;
+			var ASPECT = WIDTH / HEIGHT;
+			var NEAR = 1;
+			var FAR = 800;
+
+			var camera, scene, renderer;
+
+			var cameraControls;
+
+			var groundPlane, smallSphere, wallMat;
+
+			init();
+			animate();
+
+			function init() {
+
+				var container = document.getElementById( 'container' );
+
+				// renderer
+				renderer = new THREE.WebGLRenderer( { antialias: true } );
+				renderer.setPixelRatio( window.devicePixelRatio );
+				renderer.setSize( WIDTH, HEIGHT );
+				container.appendChild( renderer.domElement );
+
+				// gui controls
+				var gui = new dat.GUI();
+				var params = {
+					'box projected': true
+				};
+				var bpcemGui = gui.add( params, 'box projected' );
+
+				bpcemGui.onChange( function( value ) {
+					if ( value ){
+
+						groundPlane.material = boxProjectedMat;
+
+					} else {
+
+						groundPlane.material = defaultMat;
+
+					}
+				});
+
+				// scene
+				scene = new THREE.Scene();
+
+				// camera
+				camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR );
+				camera.position.set( 280, 106, -5 );
+
+				cameraControls = new THREE.OrbitControls( camera, renderer.domElement );
+				cameraControls.target.set( 0, -10, 0 );
+				cameraControls.maxDistance = 400;
+				cameraControls.minDistance = 10;
+				cameraControls.update();
+
+				// cube camera for environment map
+				cubeCamera = new THREE.CubeCamera( 1, 1000, 512 );
+				cubeCamera.renderTarget.texture.generateMipmaps = true;
+				cubeCamera.renderTarget.texture.minFilter = THREE.LinearMipMapLinearFilter;
+				cubeCamera.renderTarget.texture.magFilter = THREE.LinearFilter;
+				cubeCamera.renderTarget.texture.mapping = THREE.CubeReflectionMapping;
+
+				cubeCamera.position.set( 0, -100, 0 );
+				scene.add( cubeCamera );
+
+				// ground floor ( with box projected environment mapping )
+				var loader = new THREE.TextureLoader();
+				var rMap = loader.load( 'textures/lava/lavatile.jpg' );
+				rMap.wrapS = THREE.RepeatWrapping;
+				rMap.wrapT = THREE.RepeatWrapping;
+				rMap.repeat.set(2,1);
+
+				var defaultMat = new THREE.MeshPhysicalMaterial({
+					roughness: 1,
+					envMap: cubeCamera.renderTarget.texture,
+					roughnessMap: rMap,
+				});
+
+				var boxProjectedMat = new THREE.MeshPhysicalMaterial({
+					color: new THREE.Color('#ffffff'),
+			    roughness: 1,
+			    envMap: cubeCamera.renderTarget.texture,
+					roughnessMap: rMap,
+			  });
+
+				boxProjectedMat.onBeforeCompile = function ( shader ) {
+
+					shader.uniforms.cubeMapSize = { value: new THREE.Vector3( 200, 100, 100 ) };
+     			shader.uniforms.cubeMapPos = { value: new THREE.Vector3( 0, -50, 0 ) };
+					shader.uniforms.flipEnvMap.value = true;
+
+ 					//replace shader chunks with box projection chunks
+					shader.vertexShader = 'varying vec3 vWorldPosition;\n' + shader.vertexShader;
+
+					shader.vertexShader = shader.vertexShader.replace(
+						'#include <worldpos_vertex>',
+						worldposReplace
+					);
+
+					shader.fragmentShader = shader.fragmentShader.replace(
+						'#include <envmap_pars_fragment>',
+						envmapParsReplace
+					);
+
+					shader.fragmentShader = shader.fragmentShader.replace(
+						'#include <envmap_physical_pars_fragment>',
+						envmapPhysicalParsReplace
+					);
+
+					materialShader = shader;
+
+				};
+
+			  groundPlane = new THREE.Mesh( new THREE.PlaneGeometry( 200, 100, 100 ), boxProjectedMat );
+				groundPlane.rotateX( - Math.PI / 2 );
+				groundPlane.position.set( 0, - 49, 0 );
+				groundPlane.geometry.computeVertexNormals();
+				scene.add( groundPlane );
+
+				// walls
+				var diffuseTex = loader.load( 'textures/brick_diffuse.jpg', () => {
+					updateCubeMap();
+				} );
+				var bumpTex = loader.load( 'textures/brick_bump.jpg', () => {
+					updateCubeMap();
+				} );
+				wallMat = new THREE.MeshPhysicalMaterial({
+					map: diffuseTex,
+					bumpMap: bumpTex,
+					bumpScale: 0.3,
+				});
+
+				var planeGeo = new THREE.PlaneBufferGeometry( 100, 100 );
+
+				var planeBack1 = new THREE.Mesh( planeGeo, wallMat );
+				planeBack1.position.z = - 50;
+				planeBack1.position.x = - 50;
+				scene.add( planeBack1 );
+
+				var planeBack2 = new THREE.Mesh( planeGeo, wallMat );
+				planeBack2.position.z = - 50;
+				planeBack2.position.x = 50;
+				scene.add( planeBack2 );
+
+				var planeFront1 = new THREE.Mesh( planeGeo, wallMat );
+				planeFront1.position.z = 50;
+				planeFront1.position.x = - 50;
+				planeFront1.rotateY( Math.PI );
+				scene.add( planeFront1 );
+
+				var planeFront2 = new THREE.Mesh( planeGeo, wallMat );
+				planeFront2.position.z = 50;
+				planeFront2.position.x = 50;
+				planeFront2.rotateY( Math.PI );
+				scene.add( planeFront2 );
+
+				var planeRight = new THREE.Mesh( planeGeo, wallMat );
+				planeRight.position.x = 100;
+				planeRight.rotateY( - Math.PI / 2 );
+				scene.add( planeRight );
+
+				var planeLeft = new THREE.Mesh( planeGeo, wallMat );
+				planeLeft.position.x = - 100;
+				planeLeft.rotateY( Math.PI / 2 );
+				scene.add( planeLeft );
+
+				//lights
+				var width = 50;
+				var height = 50;
+				var intensity = 10;
+				var blueRectLight = new THREE.RectAreaLight( 0xf3aaaa, intensity,  width, height );
+				blueRectLight.position.set( 99, 5, 0 );
+				blueRectLight.lookAt( 0, 5, 0 );
+				scene.add( blueRectLight );
+
+				blueRectLightHelper = new THREE.RectAreaLightHelper( blueRectLight, 0xffffff );
+				blueRectLight.add( blueRectLightHelper );
+
+				var redRectLight = new THREE.RectAreaLight( 0x9aaeff, intensity,  width, height );
+				redRectLight.position.set( - 99, 5, 0 );
+				redRectLight.lookAt( 0, 5, 0 );
+				scene.add( redRectLight );
+
+				redRectLightHelper = new THREE.RectAreaLightHelper( redRectLight, 0xffffff );
+				redRectLight.add( redRectLightHelper );
+
+			}
+
+			function updateCubeMap () {
+
+				//disable specular highlights on walls in the environment map
+				wallMat.roughness = 1;
+
+				groundPlane.visible = false;
+
+				cubeCamera.position.copy( groundPlane.position );
+
+				cubeCamera.update( renderer, scene );
+
+				wallMat.roughness = 0.6;
+
+				groundPlane.visible = true;
+
+			}
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+
+				renderer.render( scene, camera );
+
+			}
+
+		</script>
+	</body>
+</html>