فهرست منبع

added fromCubemap

Emmett Lalish 5 سال پیش
والد
کامیت
676342da1d
2فایلهای تغییر یافته به همراه242 افزوده شده و 136 حذف شده
  1. 121 68
      examples/js/pmrem/PMREMGenerator.js
  2. 121 68
      examples/jsm/pmrem/PMREMGenerator.js

+ 121 - 68
examples/js/pmrem/PMREMGenerator.js

@@ -105,7 +105,23 @@ THREE.PMREMGenerator = ( function () {
 			equirectangular.generateMipmaps = false;
 
 			var cubeUVRenderTarget = _allocateTargets( equirectangular );
-			_equirectangularToCubeUV( equirectangular, cubeUVRenderTarget );
+			_textureToCubeUV( equirectangular, cubeUVRenderTarget );
+			_applyPMREM( cubeUVRenderTarget );
+			_cleanup();
+
+			return cubeUVRenderTarget;
+
+		},
+
+		/**
+		 * Generates a PMREM from an cubemap texture, which can be either LDR
+		 * (RGBFormat) or HDR (RGBEFormat). The ideal input cube size is 256 x 256,
+		 * as this matches best with the 256 x 256 cubemap output.
+		 */
+		fromCubemap: function ( cubemap ) {
+
+			var cubeUVRenderTarget = _allocateTargets( cubemap );
+			_textureToCubeUV( cubemap, cubeUVRenderTarget );
 			_applyPMREM( cubeUVRenderTarget );
 			_cleanup();
 
@@ -219,43 +235,41 @@ THREE.PMREMGenerator = ( function () {
 
 	}
 
-	function _sceneToCubeUV(
-		scene, near, far,
-		cubeUVRenderTarget ) {
+	function _sceneToCubeUV( scene, near, far, cubeUVRenderTarget ) {
 
-	  var fov = 90;
-	  var aspect = 1;
-	  var cubeCamera = new THREE.PerspectiveCamera( fov, aspect, near, far );
-	  var upSign = [ 1, 1, 1, 1, - 1, 1 ];
-	  var forwardSign = [ 1, 1, - 1, - 1, - 1, 1 ];
+		var fov = 90;
+		var aspect = 1;
+		var cubeCamera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+		var upSign = [ 1, 1, 1, 1, - 1, 1 ];
+		var forwardSign = [ 1, 1, - 1, - 1, - 1, 1 ];
 
-	  var gammaOutput = _renderer.gammaOutput;
-	  var toneMapping = _renderer.toneMapping;
-	  var toneMappingExposure = _renderer.toneMappingExposure;
+		var gammaOutput = _renderer.gammaOutput;
+		var toneMapping = _renderer.toneMapping;
+		var toneMappingExposure = _renderer.toneMappingExposure;
 
-	  _renderer.toneMapping = THREE.LinearToneMapping;
-	  _renderer.toneMappingExposure = 1.0;
-	  _renderer.gammaOutput = false;
-	  scene.scale.z *= - 1;
+		_renderer.toneMapping = THREE.LinearToneMapping;
+		_renderer.toneMappingExposure = 1.0;
+		_renderer.gammaOutput = false;
+		scene.scale.z *= - 1;
 
-	  _renderer.setRenderTarget( cubeUVRenderTarget );
-	  for ( var i = 0; i < 6; i ++ ) {
+		_renderer.setRenderTarget( cubeUVRenderTarget );
+		for ( var i = 0; i < 6; i ++ ) {
 
 			var col = i % 3;
 			if ( col == 0 ) {
 
-		  cubeCamera.up.set( 0, upSign[ i ], 0 );
-		  cubeCamera.lookAt( forwardSign[ i ], 0, 0 );
+				cubeCamera.up.set( 0, upSign[ i ], 0 );
+				cubeCamera.lookAt( forwardSign[ i ], 0, 0 );
 
 			} else if ( col == 1 ) {
 
-		  cubeCamera.up.set( 0, 0, upSign[ i ] );
-		  cubeCamera.lookAt( 0, forwardSign[ i ], 0 );
+				cubeCamera.up.set( 0, 0, upSign[ i ] );
+				cubeCamera.lookAt( 0, forwardSign[ i ], 0 );
 
 			} else {
 
-		  cubeCamera.up.set( 0, upSign[ i ], 0 );
-		  cubeCamera.lookAt( 0, 0, forwardSign[ i ] );
+				cubeCamera.up.set( 0, upSign[ i ], 0 );
+				cubeCamera.lookAt( 0, 0, forwardSign[ i ] );
 
 			}
 			_setViewport(
@@ -264,40 +278,42 @@ THREE.PMREMGenerator = ( function () {
 
 		}
 
-	  _renderer.toneMapping = toneMapping;
-	  _renderer.toneMappingExposure = toneMappingExposure;
-	  _renderer.gammaOutput = gammaOutput;
-	  scene.scale.z *= - 1;
+		_renderer.toneMapping = toneMapping;
+		_renderer.toneMappingExposure = toneMappingExposure;
+		_renderer.gammaOutput = gammaOutput;
+		scene.scale.z *= - 1;
 
 	}
 
-	function _equirectangularToCubeUV(
-		equirectangular, cubeUVRenderTarget ) {
+	function _textureToCubeUV( texture, cubeUVRenderTarget ) {
 
-	  var scene = new THREE.Scene();
-	  var equirectMaterial = _getEquirectShader();
-	  scene.add( new THREE.Mesh( _lodPlanes[ 0 ], equirectMaterial ) );
-	  var uniforms = equirectMaterial.uniforms;
+		var scene = new THREE.Scene();
+		var material = texture.isCubeTexture ? _getCubemapShader() : _getEquirectShader();
+		scene.add( new THREE.Mesh( _lodPlanes[ 0 ], material ) );
+		var uniforms = material.uniforms;
 
-	  uniforms[ 'envMap' ].value = equirectangular;
-	  uniforms[ 'texelSize' ].value.set(
-		  1.0 / equirectangular.image.width, 1.0 / equirectangular.image.height );
-	  uniforms[ 'inputEncoding' ].value = ENCODINGS[ equirectangular.encoding ];
-	  uniforms[ 'outputEncoding' ].value = ENCODINGS[ equirectangular.encoding ];
+		uniforms[ 'envMap' ].value = texture;
+		if ( ! texture.isCubeTexture ) {
+
+			uniforms[ 'texelSize' ].value.set( 1.0 / texture.image.width, 1.0 / texture.image.height );
+
+		}
+		uniforms[ 'inputEncoding' ].value = ENCODINGS[ texture.encoding ];
+		uniforms[ 'outputEncoding' ].value = ENCODINGS[ texture.encoding ];
 
-	  _renderer.setRenderTarget( cubeUVRenderTarget );
-	  _setViewport( 0, 0, 3 * SIZE_MAX, 2 * SIZE_MAX );
-	  _renderer.render( scene, _flatCamera );
+		_renderer.setRenderTarget( cubeUVRenderTarget );
+		_setViewport( 0, 0, 3 * SIZE_MAX, 2 * SIZE_MAX );
+		_renderer.render( scene, _flatCamera );
 
 	}
 
 	function _createRenderTarget( params ) {
 
-	  var cubeUVRenderTarget =
-		  new THREE.WebGLRenderTarget( 3 * SIZE_MAX, 3 * SIZE_MAX, params );
-	  cubeUVRenderTarget.texture.mapping = THREE.CubeUVReflectionMapping;
-	  cubeUVRenderTarget.texture.name = 'PMREM.cubeUv';
-	  return cubeUVRenderTarget;
+		var cubeUVRenderTarget =
+		new THREE.WebGLRenderTarget( 3 * SIZE_MAX, 3 * SIZE_MAX, params );
+		cubeUVRenderTarget.texture.mapping = THREE.CubeUVReflectionMapping;
+		cubeUVRenderTarget.texture.name = 'PMREM.cubeUv';
+		return cubeUVRenderTarget;
 
 	}
 
@@ -335,34 +351,29 @@ THREE.PMREMGenerator = ( function () {
    * the poles) to approximate the orthogonally-separable blur. It is least
    * accurate at the poles, but still does a decent job.
    */
-	function _blur(
-		cubeUVRenderTarget, lodIn, lodOut,
-		sigma, poleAxis ) {
+	function _blur( cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis ) {
 
 		_halfBlur(
-	  cubeUVRenderTarget,
-	  _pingPongRenderTarget,
-	  lodIn,
-	  lodOut,
-	  sigma,
-	  'latitudinal',
-	  poleAxis );
+			cubeUVRenderTarget,
+			_pingPongRenderTarget,
+			lodIn,
+			lodOut,
+			sigma,
+			'latitudinal',
+			poleAxis );
 
 		_halfBlur(
-	  _pingPongRenderTarget,
-	  cubeUVRenderTarget,
-	  lodOut,
-	  lodOut,
-	  sigma,
-	  'longitudinal',
-	  poleAxis );
+			_pingPongRenderTarget,
+			cubeUVRenderTarget,
+			lodOut,
+			lodOut,
+			sigma,
+			'longitudinal',
+			poleAxis );
 
 	}
 
-	function _halfBlur(
-		targetIn, targetOut, lodIn,
-		lodOut, sigmaRadians, direction,
-		poleAxis ) {
+	function _halfBlur( targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis ) {
 
 		if ( direction !== 'latitudinal' && direction !== 'longitudinal' ) {
 
@@ -574,6 +585,48 @@ void main() {
 
 	}
 
+	function _getCubemapShader() {
+
+		var shaderMaterial = new THREE.RawShaderMaterial( {
+
+			uniforms: {
+				'envMap': { value: null },
+				'inputEncoding': { value: ENCODINGS[ THREE.LinearEncoding ] },
+				'outputEncoding': { value: ENCODINGS[ THREE.LinearEncoding ] }
+			},
+
+			vertexShader: _getCommonVertexShader(),
+
+			fragmentShader: `
+precision mediump float;
+precision mediump int;
+varying vec3 vOutputDirection;
+uniform samplerCube envMap;
+
+${_getEncodings()}
+
+#define RECIPROCAL_PI 0.31830988618
+#define RECIPROCAL_PI2 0.15915494
+
+void main() {
+	gl_FragColor = vec4(0.0);
+	gl_FragColor.rgb = envMapTexelToLinear(textureCube(envMap, vOutputDirection)).rgb;
+  	gl_FragColor = linearToOutputTexel(gl_FragColor);
+}
+     		`,
+
+			blending: THREE.NoBlending,
+			depthTest: false,
+	   		depthWrite: false
+
+		} );
+
+		shaderMaterial.type = 'CubemapToCubeUV';
+
+		return shaderMaterial;
+
+	}
+
 	function _getCommonVertexShader() {
 
 		return `

+ 121 - 68
examples/jsm/pmrem/PMREMGenerator.js

@@ -131,7 +131,23 @@ var PMREMGenerator = ( function () {
 			equirectangular.generateMipmaps = false;
 
 			var cubeUVRenderTarget = _allocateTargets( equirectangular );
-			_equirectangularToCubeUV( equirectangular, cubeUVRenderTarget );
+			_textureToCubeUV( equirectangular, cubeUVRenderTarget );
+			_applyPMREM( cubeUVRenderTarget );
+			_cleanup();
+
+			return cubeUVRenderTarget;
+
+		},
+
+		/**
+		 * Generates a PMREM from an cubemap texture, which can be either LDR
+		 * (RGBFormat) or HDR (RGBEFormat). The ideal input cube size is 256 x 256,
+		 * as this matches best with the 256 x 256 cubemap output.
+		 */
+		fromCubemap: function ( cubemap ) {
+
+			var cubeUVRenderTarget = _allocateTargets( cubemap );
+			_textureToCubeUV( cubemap, cubeUVRenderTarget );
 			_applyPMREM( cubeUVRenderTarget );
 			_cleanup();
 
@@ -245,43 +261,41 @@ var PMREMGenerator = ( function () {
 
 	}
 
-	function _sceneToCubeUV(
-		scene, near, far,
-		cubeUVRenderTarget ) {
+	function _sceneToCubeUV( scene, near, far, cubeUVRenderTarget ) {
 
-	  var fov = 90;
-	  var aspect = 1;
-	  var cubeCamera = new PerspectiveCamera( fov, aspect, near, far );
-	  var upSign = [ 1, 1, 1, 1, - 1, 1 ];
-	  var forwardSign = [ 1, 1, - 1, - 1, - 1, 1 ];
+		var fov = 90;
+		var aspect = 1;
+		var cubeCamera = new PerspectiveCamera( fov, aspect, near, far );
+		var upSign = [ 1, 1, 1, 1, - 1, 1 ];
+		var forwardSign = [ 1, 1, - 1, - 1, - 1, 1 ];
 
-	  var gammaOutput = _renderer.gammaOutput;
-	  var toneMapping = _renderer.toneMapping;
-	  var toneMappingExposure = _renderer.toneMappingExposure;
+		var gammaOutput = _renderer.gammaOutput;
+		var toneMapping = _renderer.toneMapping;
+		var toneMappingExposure = _renderer.toneMappingExposure;
 
-	  _renderer.toneMapping = LinearToneMapping;
-	  _renderer.toneMappingExposure = 1.0;
-	  _renderer.gammaOutput = false;
-	  scene.scale.z *= - 1;
+		_renderer.toneMapping = LinearToneMapping;
+		_renderer.toneMappingExposure = 1.0;
+		_renderer.gammaOutput = false;
+		scene.scale.z *= - 1;
 
-	  _renderer.setRenderTarget( cubeUVRenderTarget );
-	  for ( var i = 0; i < 6; i ++ ) {
+		_renderer.setRenderTarget( cubeUVRenderTarget );
+		for ( var i = 0; i < 6; i ++ ) {
 
 			var col = i % 3;
 			if ( col == 0 ) {
 
-		  cubeCamera.up.set( 0, upSign[ i ], 0 );
-		  cubeCamera.lookAt( forwardSign[ i ], 0, 0 );
+				cubeCamera.up.set( 0, upSign[ i ], 0 );
+				cubeCamera.lookAt( forwardSign[ i ], 0, 0 );
 
 			} else if ( col == 1 ) {
 
-		  cubeCamera.up.set( 0, 0, upSign[ i ] );
-		  cubeCamera.lookAt( 0, forwardSign[ i ], 0 );
+				cubeCamera.up.set( 0, 0, upSign[ i ] );
+				cubeCamera.lookAt( 0, forwardSign[ i ], 0 );
 
 			} else {
 
-		  cubeCamera.up.set( 0, upSign[ i ], 0 );
-		  cubeCamera.lookAt( 0, 0, forwardSign[ i ] );
+				cubeCamera.up.set( 0, upSign[ i ], 0 );
+				cubeCamera.lookAt( 0, 0, forwardSign[ i ] );
 
 			}
 			_setViewport(
@@ -290,40 +304,42 @@ var PMREMGenerator = ( function () {
 
 		}
 
-	  _renderer.toneMapping = toneMapping;
-	  _renderer.toneMappingExposure = toneMappingExposure;
-	  _renderer.gammaOutput = gammaOutput;
-	  scene.scale.z *= - 1;
+		_renderer.toneMapping = toneMapping;
+		_renderer.toneMappingExposure = toneMappingExposure;
+		_renderer.gammaOutput = gammaOutput;
+		scene.scale.z *= - 1;
 
 	}
 
-	function _equirectangularToCubeUV(
-		equirectangular, cubeUVRenderTarget ) {
+	function _textureToCubeUV( texture, cubeUVRenderTarget ) {
 
-	  var scene = new Scene();
-	  var equirectMaterial = _getEquirectShader();
-	  scene.add( new Mesh( _lodPlanes[ 0 ], equirectMaterial ) );
-	  var uniforms = equirectMaterial.uniforms;
+		var scene = new Scene();
+		var material = texture.isCubeTexture ? _getCubemapShader() : _getEquirectShader();
+		scene.add( new Mesh( _lodPlanes[ 0 ], material ) );
+		var uniforms = material.uniforms;
 
-	  uniforms[ 'envMap' ].value = equirectangular;
-	  uniforms[ 'texelSize' ].value.set(
-		  1.0 / equirectangular.image.width, 1.0 / equirectangular.image.height );
-	  uniforms[ 'inputEncoding' ].value = ENCODINGS[ equirectangular.encoding ];
-	  uniforms[ 'outputEncoding' ].value = ENCODINGS[ equirectangular.encoding ];
+		uniforms[ 'envMap' ].value = texture;
+		if ( ! texture.isCubeTexture ) {
+
+			uniforms[ 'texelSize' ].value.set( 1.0 / texture.image.width, 1.0 / texture.image.height );
+
+		}
+		uniforms[ 'inputEncoding' ].value = ENCODINGS[ texture.encoding ];
+		uniforms[ 'outputEncoding' ].value = ENCODINGS[ texture.encoding ];
 
-	  _renderer.setRenderTarget( cubeUVRenderTarget );
-	  _setViewport( 0, 0, 3 * SIZE_MAX, 2 * SIZE_MAX );
-	  _renderer.render( scene, _flatCamera );
+		_renderer.setRenderTarget( cubeUVRenderTarget );
+		_setViewport( 0, 0, 3 * SIZE_MAX, 2 * SIZE_MAX );
+		_renderer.render( scene, _flatCamera );
 
 	}
 
 	function _createRenderTarget( params ) {
 
-	  var cubeUVRenderTarget =
-		  new WebGLRenderTarget( 3 * SIZE_MAX, 3 * SIZE_MAX, params );
-	  cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping;
-	  cubeUVRenderTarget.texture.name = 'PMREM.cubeUv';
-	  return cubeUVRenderTarget;
+		var cubeUVRenderTarget =
+		new WebGLRenderTarget( 3 * SIZE_MAX, 3 * SIZE_MAX, params );
+		cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping;
+		cubeUVRenderTarget.texture.name = 'PMREM.cubeUv';
+		return cubeUVRenderTarget;
 
 	}
 
@@ -361,34 +377,29 @@ var PMREMGenerator = ( function () {
    * the poles) to approximate the orthogonally-separable blur. It is least
    * accurate at the poles, but still does a decent job.
    */
-	function _blur(
-		cubeUVRenderTarget, lodIn, lodOut,
-		sigma, poleAxis ) {
+	function _blur( cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis ) {
 
 		_halfBlur(
-	  cubeUVRenderTarget,
-	  _pingPongRenderTarget,
-	  lodIn,
-	  lodOut,
-	  sigma,
-	  'latitudinal',
-	  poleAxis );
+			cubeUVRenderTarget,
+			_pingPongRenderTarget,
+			lodIn,
+			lodOut,
+			sigma,
+			'latitudinal',
+			poleAxis );
 
 		_halfBlur(
-	  _pingPongRenderTarget,
-	  cubeUVRenderTarget,
-	  lodOut,
-	  lodOut,
-	  sigma,
-	  'longitudinal',
-	  poleAxis );
+			_pingPongRenderTarget,
+			cubeUVRenderTarget,
+			lodOut,
+			lodOut,
+			sigma,
+			'longitudinal',
+			poleAxis );
 
 	}
 
-	function _halfBlur(
-		targetIn, targetOut, lodIn,
-		lodOut, sigmaRadians, direction,
-		poleAxis ) {
+	function _halfBlur( targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis ) {
 
 		if ( direction !== 'latitudinal' && direction !== 'longitudinal' ) {
 
@@ -600,6 +611,48 @@ void main() {
 
 	}
 
+	function _getCubemapShader() {
+
+		var shaderMaterial = new RawShaderMaterial( {
+
+			uniforms: {
+				'envMap': { value: null },
+				'inputEncoding': { value: ENCODINGS[ LinearEncoding ] },
+				'outputEncoding': { value: ENCODINGS[ LinearEncoding ] }
+			},
+
+			vertexShader: _getCommonVertexShader(),
+
+			fragmentShader: `
+precision mediump float;
+precision mediump int;
+varying vec3 vOutputDirection;
+uniform samplerCube envMap;
+
+${_getEncodings()}
+
+#define RECIPROCAL_PI 0.31830988618
+#define RECIPROCAL_PI2 0.15915494
+
+void main() {
+	gl_FragColor = vec4(0.0);
+	gl_FragColor.rgb = envMapTexelToLinear(textureCube(envMap, vOutputDirection)).rgb;
+  	gl_FragColor = linearToOutputTexel(gl_FragColor);
+}
+     		`,
+
+			blending: NoBlending,
+			depthTest: false,
+	   		depthWrite: false
+
+		} );
+
+		shaderMaterial.type = 'CubemapToCubeUV';
+
+		return shaderMaterial;
+
+	}
+
 	function _getCommonVertexShader() {
 
 		return `