Pārlūkot izejas kodu

Merge branch 'gammaFactor' of https://github.com/bhouston/three.js into dev

Conflicts:
	src/renderers/WebGLRenderer.js
	src/renderers/shaders/ShaderChunk/common.glsl
	src/renderers/shaders/ShaderLib.js
	src/renderers/webgl/WebGLProgram.js
Mr.doob 10 gadi atpakaļ
vecāks
revīzija
c0478beba3

+ 1 - 5
examples/js/ShaderDeferred.js

@@ -225,11 +225,7 @@ THREE.ShaderDeferred = {
 
 					"#endif",
 
-					"#ifdef GAMMA_INPUT",
-
-						"cubeColor.xyz *= cubeColor.xyz;",
-
-					"#endif",
+					"cubeColor.xyz = inputToLinear( cubeColor.xyz );",
 
 					"if ( combine == 1 ) {",
 

+ 2 - 6
examples/js/ShaderTerrain.js

@@ -134,12 +134,8 @@ THREE.ShaderTerrain = {
 					"vec4 colDiffuse1 = texture2D( tDiffuse1, uvOverlay );",
 					"vec4 colDiffuse2 = texture2D( tDiffuse2, uvOverlay );",
 
-					"#ifdef GAMMA_INPUT",
-
-						"colDiffuse1.xyz *= colDiffuse1.xyz;",
-						"colDiffuse2.xyz *= colDiffuse2.xyz;",
-
-					"#endif",
+					"colDiffuse1.xyz = inputToLinear( colDiffuse1.xyz );",
+					"colDiffuse2.xyz = inputToLinear( colDiffuse2.xyz );",
 
 					"gl_FragColor = gl_FragColor * mix ( colDiffuse1, colDiffuse2, 1.0 - texture2D( tDisplacement, uvBase ) );",
 

+ 37 - 7
examples/webgl_shading_physical.html

@@ -88,6 +88,10 @@
 				shadowBias: -0.0002,
 				shadowDarkness: 0.3
 
+			}, gamma = {
+				gammaFactor: 2.0,
+				gammaInput: true,
+				gammaOutput: true
 			};
 
 			init();
@@ -384,44 +388,70 @@
 
 				gui = new dat.GUI();
 
-				gui.add( shadowConfig, 'shadowCameraVisible' ).onChange( function() {
+				shadowGUI = gui.addFolder( "Shadow" );
+    	
+    			shadowGUI.add( shadowConfig, 'shadowCameraVisible' ).onChange( function() {
 
 					sunLight.shadowCameraVisible = shadowConfig.shadowCameraVisible;
 
 				});
 
-				gui.add( shadowConfig, 'shadowCameraNear', 1, 1500 ).onChange( function() {
+				shadowGUI.add( shadowConfig, 'shadowCameraNear', 1, 1500 ).onChange( function() {
 
 					sunLight.shadowCamera.near = shadowConfig.shadowCameraNear;
 					sunLight.shadowCamera.updateProjectionMatrix();
 
 				});
 
-				gui.add( shadowConfig, 'shadowCameraFar', 1501, 5000 ).onChange( function() {
+				shadowGUI.add( shadowConfig, 'shadowCameraFar', 1501, 5000 ).onChange( function() {
 
 					sunLight.shadowCamera.far = shadowConfig.shadowCameraFar;
 					sunLight.shadowCamera.updateProjectionMatrix();
 
 				});
 
-				gui.add( shadowConfig, 'shadowCameraFov', 1, 120 ).onChange( function() {
+				shadowGUI.add( shadowConfig, 'shadowCameraFov', 1, 120 ).onChange( function() {
 
 					sunLight.shadowCamera.fov = shadowConfig.shadowCameraFov;
 					sunLight.shadowCamera.updateProjectionMatrix();
 
 				});
 
-				gui.add( shadowConfig, 'shadowBias', -0.01, 0.01 ).onChange( function() {
+				shadowGUI.add( shadowConfig, 'shadowBias', -0.01, 0.01 ).onChange( function() {
 
 					sunLight.shadowBias = shadowConfig.shadowBias;
 
 				});
 
-				gui.add( shadowConfig, 'shadowDarkness', 0, 1 ).onChange( function() {
+				shadowGUI.add( shadowConfig, 'shadowDarkness', 0, 1 ).onChange( function() {
 
 				});
+				shadowGUI.open();
 
-				gui.close();
+				gammaGUI = gui.addFolder( "Gamma" );
+    
+				gammaGUI.add( gamma, 'gammaFactor', 0.1, 4.0 ).onChange( function() {
+
+					renderer.gammaFactor = gamma.gammaFactor;
+
+				});
+				gammaGUI.open();
+
+				/*
+
+				Not exposed because they are not easily dynamically updated - as all shaders need to be recompiled.  -bhouston
+
+				gammaGUI.add( gamma, 'gammaInput', true ).onChange( function() {
+
+					renderer.gammaInput = gamma.gammaInput;
+
+				});
+
+				gammaGUI.add( gamma, 'gammaOutput', true ).onChange( function() {
+
+					renderer.gammaOutput = gamma.gammaOutput;
+
+				});*/
 
 			}
 

+ 14 - 8
src/math/Color.js

@@ -173,21 +173,27 @@ THREE.Color.prototype = {
 
 	},
 
-	copyGammaToLinear: function ( color ) {
+	copyGammaToLinear: function ( color, gammaFactor ) {
 
-		this.r = color.r * color.r;
-		this.g = color.g * color.g;
-		this.b = color.b * color.b;
+		if ( gammaFactor === undefined ) gammaFactor = 2.0;
+
+		this.r = Math.pow( color.r, gammaFactor );
+		this.g = Math.pow( color.g, gammaFactor );
+		this.b = Math.pow( color.b, gammaFactor );
 
 		return this;
 
 	},
 
-	copyLinearToGamma: function ( color ) {
+	copyLinearToGamma: function ( color, gammaFactor ) {
+
+		if ( gammaFactor === undefined ) gammaFactor = 2.0;
+
+		var safeInverse = ( gammaFactor > 0 ) ? ( 1.0 / gammaFactor ) : 1.0;
 
-		this.r = Math.sqrt( color.r );
-		this.g = Math.sqrt( color.g );
-		this.b = Math.sqrt( color.b );
+		this.r = Math.pow( color.r, safeInverse );
+		this.g = Math.pow( color.g, safeInverse );
+		this.b = Math.pow( color.b, safeInverse );
 
 		return this;
 

+ 17 - 18
src/renderers/WebGLRenderer.js

@@ -58,6 +58,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	// physically based shading
 
+	this.gammaFactor = 2.0;	// for backwards compatibility
 	this.gammaInput = false;
 	this.gammaOutput = false;
 
@@ -4594,7 +4595,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		if ( _this.gammaInput ) {
 
-			uniforms.diffuse.value.copyGammaToLinear( material.color );
+			uniforms.diffuse.value.copyGammaToLinear( material.color, _this.gammaFactor );
 
 		} else {
 
@@ -4728,8 +4729,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		if ( _this.gammaInput ) {
 
-			uniforms.emissive.value.copyGammaToLinear( material.emissive );
-			uniforms.specular.value.copyGammaToLinear( material.specular );
+			uniforms.emissive.value.copyGammaToLinear( material.emissive, _this.gammaFactor );
+			uniforms.specular.value.copyGammaToLinear( material.specular, _this.gammaFactor );
 
 		} else {
 
@@ -4750,7 +4751,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		if ( _this.gammaInput ) {
 
-			uniforms.emissive.value.copyGammaToLinear( material.emissive );
+			uniforms.emissive.value.copyGammaToLinear( material.emissive, _this.gammaFactor );
 
 		} else {
 
@@ -5227,11 +5228,11 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	//
 
-	function setColorGamma( array, offset, color, intensitySq ) {
+	function setColorGamma( array, offset, color, intensity, gammaFactor ) {
 
-		array[ offset ]     = color.r * color.r * intensitySq;
-		array[ offset + 1 ] = color.g * color.g * intensitySq;
-		array[ offset + 2 ] = color.b * color.b * intensitySq;
+		array[ offset ]     = Math.pow( color.r * intensity, gammaFactor );
+		array[ offset + 1 ] = Math.pow( color.g * intensity, gammaFactor );
+		array[ offset + 2 ] = Math.pow( color.b * intensity, gammaFactor );
 
 	}
 
@@ -5305,9 +5306,9 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				if ( _this.gammaInput ) {
 
-					r += color.r * color.r;
-					g += color.g * color.g;
-					b += color.b * color.b;
+					r += Math.pow( color.r, _this.gammaFactor );
+					g += Math.pow( color.g, _this.gammaFactor );
+					b += Math.pow( color.b, _this.gammaFactor );
 
 				} else {
 
@@ -5336,7 +5337,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				if ( _this.gammaInput ) {
 
-					setColorGamma( dirColors, dirOffset, color, intensity * intensity );
+					setColorGamma( dirColors, dirOffset, color, intensity, _this.gammaFactor );
 
 				} else {
 
@@ -5356,7 +5357,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				if ( _this.gammaInput ) {
 
-					setColorGamma( pointColors, pointOffset, color, intensity * intensity );
+					setColorGamma( pointColors, pointOffset, color, intensity, _this.gammaFactor );
 
 				} else {
 
@@ -5386,7 +5387,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				if ( _this.gammaInput ) {
 
-					setColorGamma( spotColors, spotOffset, color, intensity * intensity );
+					setColorGamma( spotColors, spotOffset, color, intensity, _this.gammaFactor );
 
 				} else {
 
@@ -5436,10 +5437,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				if ( _this.gammaInput ) {
 
-					intensitySq = intensity * intensity;
-
-					setColorGamma( hemiSkyColors, hemiOffset, skyColor, intensitySq );
-					setColorGamma( hemiGroundColors, hemiOffset, groundColor, intensitySq );
+					setColorGamma( hemiSkyColors, hemiOffset, skyColor, intensity, _this.gammaFactor );
+					setColorGamma( hemiGroundColors, hemiOffset, groundColor, intensity, _this.gammaFactor );
 
 				} else {
 

+ 1 - 9
src/renderers/shaders/ShaderChunk/color_vertex.glsl

@@ -1,13 +1,5 @@
 #ifdef USE_COLOR
 
-	#ifdef GAMMA_INPUT
-
-		vColor = square( color );
-
-	#else
-
-		vColor = color;
-
-	#endif
+	vColor.xyz = inputToLinear( color.xyz );
 
 #endif

+ 14 - 0
src/renderers/shaders/ShaderChunk/common.glsl

@@ -44,3 +44,17 @@ float calcLightAttenuation( float lightDistance, float cutoffDistance, float dec
 	return 1.0;
 }
 
+vec3 inputToLinear( in vec3 a ) {
+#ifdef GAMMA_INPUT
+	return pow( a, vec3( float( GAMMA_FACTOR ) ) );
+#else
+	return a;
+#endif
+}
+vec3 linearToOutput( in vec3 a ) {
+#ifdef GAMMA_OUTPUT
+	return pow( a, vec3( 1.0 / float( GAMMA_FACTOR ) ) );
+#else
+	return a;
+#endif
+}

+ 1 - 5
src/renderers/shaders/ShaderChunk/envmap_fragment.glsl

@@ -43,11 +43,7 @@
 		vec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );
 	#endif
 
-	#ifdef GAMMA_INPUT
-
-		envColor.xyz *= envColor.xyz;
-
-	#endif
+	envColor.xyz = inputToLinear( envColor.xyz );
 
 	#ifdef ENVMAP_BLENDING_MULTIPLY
 

+ 1 - 4
src/renderers/shaders/ShaderChunk/linear_to_gamma_fragment.glsl

@@ -1,5 +1,2 @@
-#ifdef GAMMA_OUTPUT
 
-	gl_FragColor.xyz = sqrt( gl_FragColor.xyz );
-
-#endif
+	gl_FragColor.xyz = linearToOutput( gl_FragColor.xyz );

+ 1 - 5
src/renderers/shaders/ShaderChunk/map_fragment.glsl

@@ -2,11 +2,7 @@
 
 	vec4 texelColor = texture2D( map, vUv );
 
-	#ifdef GAMMA_INPUT
-
-		texelColor.xyz *= texelColor.xyz;
-
-	#endif
+	texelColor.xyz = inputToLinear( texelColor.xyz );
 
 	gl_FragColor = gl_FragColor * texelColor;
 

+ 2 - 5
src/renderers/shaders/ShaderChunk/shadowmap_fragment.glsl

@@ -209,11 +209,8 @@
 
 	}
 
-	#ifdef GAMMA_OUTPUT
-
-		shadowColor *= shadowColor;
-
-	#endif
+	// NOTE: I am unsure if this is correct in linear space.  -bhouston, Dec 29, 2014
+	shadowColor = inputToLinear( shadowColor );
 
 	gl_FragColor.xyz = gl_FragColor.xyz * shadowColor;
 

+ 4 - 0
src/renderers/webgl/WebGLProgram.js

@@ -135,6 +135,8 @@ THREE.WebGLProgram = ( function () {
 
 		}
 
+		var gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0;
+
 		// console.log( 'building new program ' );
 
 		//
@@ -165,6 +167,7 @@ THREE.WebGLProgram = ( function () {
 
 				_this.gammaInput ? '#define GAMMA_INPUT' : '',
 				_this.gammaOutput ? '#define GAMMA_OUTPUT' : '',
+				'#define GAMMA_FACTOR ' + gammaFactorDefine,
 
 				'#define MAX_DIR_LIGHTS ' + parameters.maxDirLights,
 				'#define MAX_POINT_LIGHTS ' + parameters.maxPointLights,
@@ -279,6 +282,7 @@ THREE.WebGLProgram = ( function () {
 
 				_this.gammaInput ? '#define GAMMA_INPUT' : '',
 				_this.gammaOutput ? '#define GAMMA_OUTPUT' : '',
+				'#define GAMMA_FACTOR ' + gammaFactorDefine,
 
 				( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',
 				( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '',