Переглянути джерело

ColladaLoader: Convert color from srgb to linear on load (#23401)

* ColladaLoader: label color textures, material colors as sRGB

* ColladaLoader: convert vertex colors

* use outputEncoding = sRGBEncoding in collada examples

* update failing screenshots

* fix deepscan issues

* Update ColladaLoader.js

* update KMZ example
Garrett Johnson 3 роки тому
батько
коміт
2bbe2a6304

+ 36 - 8
examples/jsm/loaders/ColladaLoader.js

@@ -36,7 +36,8 @@ import {
 	TextureLoader,
 	Vector2,
 	Vector3,
-	VectorKeyframeTrack
+	VectorKeyframeTrack,
+	sRGBEncoding
 } from 'three';
 import { TGALoader } from '../loaders/TGALoader.js';
 
@@ -1579,7 +1580,7 @@ class ColladaLoader extends Loader {
 
 			material.name = data.name || '';
 
-			function getTexture( textureObject ) {
+			function getTexture( textureObject, encoding = null ) {
 
 				const sampler = effect.profile.samplers[ textureObject.id ];
 				let image = null;
@@ -1627,6 +1628,12 @@ class ColladaLoader extends Loader {
 
 						}
 
+						if ( encoding !== null ) {
+
+							texture.encoding = encoding;
+
+						}
+
 						return texture;
 
 					} else {
@@ -1657,7 +1664,7 @@ class ColladaLoader extends Loader {
 
 					case 'diffuse':
 						if ( parameter.color ) material.color.fromArray( parameter.color );
-						if ( parameter.texture ) material.map = getTexture( parameter.texture );
+						if ( parameter.texture ) material.map = getTexture( parameter.texture, sRGBEncoding );
 						break;
 					case 'specular':
 						if ( parameter.color && material.specular ) material.specular.fromArray( parameter.color );
@@ -1667,20 +1674,24 @@ class ColladaLoader extends Loader {
 						if ( parameter.texture ) material.normalMap = getTexture( parameter.texture );
 						break;
 					case 'ambient':
-						if ( parameter.texture ) material.lightMap = getTexture( parameter.texture );
+						if ( parameter.texture ) material.lightMap = getTexture( parameter.texture, sRGBEncoding );
 						break;
 					case 'shininess':
 						if ( parameter.float && material.shininess ) material.shininess = parameter.float;
 						break;
 					case 'emission':
 						if ( parameter.color && material.emissive ) material.emissive.fromArray( parameter.color );
-						if ( parameter.texture ) material.emissiveMap = getTexture( parameter.texture );
+						if ( parameter.texture ) material.emissiveMap = getTexture( parameter.texture, sRGBEncoding );
 						break;
 
 				}
 
 			}
 
+			material.color.convertSRGBToLinear();
+			if ( material.specular ) material.specular.convertSRGBToLinear();
+			if ( material.emissive ) material.emissive.convertSRGBToLinear();
+
 			//
 
 			let transparent = parameters[ 'transparent' ];
@@ -2015,7 +2026,7 @@ class ColladaLoader extends Loader {
 
 					case 'color':
 						const array = parseFloats( child.textContent );
-						data.color = new Color().fromArray( array );
+						data.color = new Color().fromArray( array ).convertSRGBToLinear();
 						break;
 
 					case 'falloff_angle':
@@ -2481,7 +2492,7 @@ class ColladaLoader extends Loader {
 							break;
 
 						case 'COLOR':
-							buildGeometryData( primitive, sources[ input.id ], input.offset, color.array );
+							buildGeometryData( primitive, sources[ input.id ], input.offset, color.array, true );
 							color.stride = sources[ input.id ].stride;
 							break;
 
@@ -2520,7 +2531,7 @@ class ColladaLoader extends Loader {
 
 		}
 
-		function buildGeometryData( primitive, source, offset, array ) {
+		function buildGeometryData( primitive, source, offset, array, isColor = false ) {
 
 			const indices = primitive.p;
 			const stride = primitive.stride;
@@ -2537,6 +2548,22 @@ class ColladaLoader extends Loader {
 
 				}
 
+				if ( isColor ) {
+
+					// convert the vertex colors from srgb to linear if present
+					const startIndex = array.length - sourceStride - 1;
+					tempColor.setRGB(
+						array[ startIndex + 0 ],
+						array[ startIndex + 1 ],
+						array[ startIndex + 2 ]
+					).convertSRGBToLinear();
+
+					array[ startIndex + 0 ] = tempColor.r;
+					array[ startIndex + 1 ] = tempColor.g;
+					array[ startIndex + 2 ] = tempColor.b;
+
+				}
+
 			}
 
 			const sourceArray = source.array;
@@ -3981,6 +4008,7 @@ class ColladaLoader extends Loader {
 
 		//
 
+		const tempColor = new Color();
 		const animations = [];
 		let kinematics = {};
 		let count = 0;

BIN
examples/screenshots/webgl_loader_collada_kinematics.jpg


BIN
examples/screenshots/webgl_loader_collada_skinning.jpg


BIN
examples/screenshots/webgl_loader_kmz.jpg


+ 1 - 0
examples/webgl_loader_collada.html

@@ -81,6 +81,7 @@
 				//
 
 				renderer = new THREE.WebGLRenderer();
+				renderer.outputEncoding = THREE.sRGBEncoding;
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );

+ 1 - 0
examples/webgl_loader_collada_kinematics.html

@@ -101,6 +101,7 @@
 				particleLight.add( pointLight );
 
 				renderer = new THREE.WebGLRenderer();
+				renderer.outputEncoding = THREE.sRGBEncoding;
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );

+ 1 - 0
examples/webgl_loader_collada_skinning.html

@@ -94,6 +94,7 @@
 				//
 
 				renderer = new THREE.WebGLRenderer( { antialias: true } );
+				renderer.outputEncoding = THREE.sRGBEncoding;
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );

+ 2 - 1
examples/webgl_loader_kmz.html

@@ -52,10 +52,11 @@
 
 				scene.add( camera );
 
-				const grid = new THREE.GridHelper( 50, 50, 0xffffff, 0x555555 );
+				const grid = new THREE.GridHelper( 50, 50, 0xffffff, 0x333333 );
 				scene.add( grid );
 
 				renderer = new THREE.WebGLRenderer( { antialias: true } );
+				renderer.outputEncoding = THREE.sRGBEncoding;
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				document.body.appendChild( renderer.domElement );