瀏覽代碼

Implement half-float version of RectAreaLight.

yellowtailfan 4 年之前
父節點
當前提交
d2d30a1a2d
共有 2 個文件被更改,包括 70 次插入7 次删除
  1. 66 3
      examples/jsm/lights/RectAreaLightUniformsLib.js
  2. 4 4
      examples/webgl_lights_rectarealight.html

+ 66 - 3
examples/jsm/lights/RectAreaLightUniformsLib.js

@@ -1,7 +1,7 @@
 import {
 import {
 	ClampToEdgeWrapping,
 	ClampToEdgeWrapping,
 	DataTexture,
 	DataTexture,
-	FloatType,
+	HalfFloatType,
 	LinearFilter,
 	LinearFilter,
 	NearestFilter,
 	NearestFilter,
 	RGBAFormat,
 	RGBAFormat,
@@ -25,6 +25,59 @@ import {
 // by Eric Heitz, Jonathan Dupuy, Stephen Hill and David Neubelt
 // by Eric Heitz, Jonathan Dupuy, Stephen Hill and David Neubelt
 // code: https://github.com/selfshadow/ltc_code/
 // code: https://github.com/selfshadow/ltc_code/
 
 
+// Convert float32 array value to float16 stored in uint16 array value.
+// Source: http://gamedev.stackexchange.com/questions/17326/conversion-of-a-number-from-single-precision-floating-point-representation-to-a/17410#17410
+
+var floatView = new Float32Array( 1 );
+var int32View = new Int32Array( floatView.buffer );
+
+/* This method is faster than the OpenEXR implementation (very often
+* used, eg. in Ogre), with the additional benefit of rounding, inspired
+* by James Tursa?s half-precision code. */
+
+function toHalf ( val ) {
+
+	floatView[ 0 ] = val;
+	var x = int32View[ 0 ];
+
+	var bits = ( x >> 16 ) & 0x8000; /* Get the sign */
+	var m = ( x >> 12 ) & 0x07ff; /* Keep one extra bit for rounding */
+	var e = ( x >> 23 ) & 0xff; /* Using int is faster here */
+
+	/* If zero, or denormal, or exponent underflows too much for a denormal
+		* half, return signed zero. */
+	if ( e < 103 ) return bits;
+
+	/* If NaN, return NaN. If Inf or exponent overflow, return Inf. */
+	if ( e > 142 ) {
+
+		bits |= 0x7c00;
+		/* If exponent was 0xff and one mantissa bit was set, it means NaN,
+					* not Inf, so make sure we set one mantissa bit too. */
+		bits |= ( ( e == 255 ) ? 0 : 1 ) && ( x & 0x007fffff );
+		return bits;
+
+	}
+
+	/* If exponent underflows but not too much, return a denormal */
+	if ( e < 113 ) {
+
+		m |= 0x0800;
+		/* Extra rounding may overflow and set mantissa to 0 and exponent
+			* to 1, which is OK. */
+		bits |= ( m >> ( 114 - e ) ) + ( ( m >> ( 113 - e ) ) & 1 );
+		return bits;
+
+	}
+
+	bits |= ( ( e - 112 ) << 10 ) | ( m >> 1 );
+	/* Extra rounding. An overflow will set mantissa to 0 and increment
+		* the exponent, which is OK. */
+	bits += m & 1;
+	return bits;
+
+};
+
 var RectAreaLightUniformsLib = {
 var RectAreaLightUniformsLib = {
 
 
 	init: function () {
 	init: function () {
@@ -37,8 +90,18 @@ var RectAreaLightUniformsLib = {
 
 
 		// data textures
 		// data textures
 
 
-		var ltc_1 = new DataTexture( new Float32Array( LTC_MAT_1 ), 64, 64, RGBAFormat, FloatType, UVMapping, ClampToEdgeWrapping, ClampToEdgeWrapping, LinearFilter, NearestFilter, 1 );
-		var ltc_2 = new DataTexture( new Float32Array( LTC_MAT_2 ), 64, 64, RGBAFormat, FloatType, UVMapping, ClampToEdgeWrapping, ClampToEdgeWrapping, LinearFilter, NearestFilter, 1 );
+		const LTC_MAT_HALF_1 = new Uint16Array(LTC_MAT_1.length);
+		LTC_MAT_1.forEach(function(x, index) {
+			LTC_MAT_HALF_1[index] = toHalf(x);
+		});
+
+		const LTC_MAT_HALF_2 = new Uint16Array(LTC_MAT_2.length);
+		LTC_MAT_2.forEach(function(x, index) {
+			LTC_MAT_HALF_2[index] = toHalf(x);
+		});
+
+		var ltc_1 = new DataTexture( LTC_MAT_HALF_1, 64, 64, RGBAFormat, HalfFloatType, UVMapping, ClampToEdgeWrapping, ClampToEdgeWrapping, LinearFilter, NearestFilter, 1 );
+		var ltc_2 = new DataTexture( LTC_MAT_HALF_2, 64, 64, RGBAFormat, HalfFloatType, UVMapping, ClampToEdgeWrapping, ClampToEdgeWrapping, LinearFilter, NearestFilter, 1 );
 
 
 		UniformsLib.LTC_1 = ltc_1;
 		UniformsLib.LTC_1 = ltc_1;
 		UniformsLib.LTC_2 = ltc_2;
 		UniformsLib.LTC_2 = ltc_2;

+ 4 - 4
examples/webgl_lights_rectarealight.html

@@ -56,12 +56,12 @@
 
 
 				}
 				}
 
 
-				if ( renderer.capabilities.isWebGL2 === false && ! renderer.extensions.get( 'OES_texture_float_linear' ) ) {
+				// if ( renderer.capabilities.isWebGL2 === false && ! renderer.extensions.get( 'OES_texture_float_linear' ) ) {
 
 
-					alert( 'OES_texture_float_linear not supported' );
-					throw 'missing webgl extension';
+				// 	alert( 'OES_texture_float_linear not supported' );
+				// 	throw 'missing webgl extension';
 
 
-				}
+				// }
 
 
 				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
 				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
 				camera.position.set( 0, 20, 35 );
 				camera.position.set( 0, 20, 35 );