Jelajahi Sumber

UniformUtils: Fix deep-copy with array of uniforms. (#33384)

Michael Herzog 2 hari lalu
induk
melakukan
f9557c4db2

+ 27 - 5
src/renderers/shaders/UniformsUtils.js

@@ -27,10 +27,7 @@ export function cloneUniforms( src ) {
 
 			const property = src[ u ][ p ];
 
-			if ( property && ( property.isColor ||
-				property.isMatrix3 || property.isMatrix4 ||
-				property.isVector2 || property.isVector3 || property.isVector4 ||
-				property.isTexture || property.isQuaternion ) ) {
+			if ( isThreeObject( property ) ) {
 
 				if ( property.isRenderTargetTexture ) {
 
@@ -45,7 +42,23 @@ export function cloneUniforms( src ) {
 
 			} else if ( Array.isArray( property ) ) {
 
-				dst[ u ][ p ] = property.slice();
+				if ( isThreeObject( property[ 0 ] ) ) {
+
+					const clonedProperty = [];
+
+					for ( let i = 0, l = property.length; i < l; i ++ ) {
+
+						clonedProperty[ i ] = property[ i ].clone();
+
+					}
+
+					dst[ u ][ p ] = clonedProperty;
+
+				} else {
+
+					dst[ u ][ p ] = property.slice();
+
+				}
 
 			} else {
 
@@ -89,6 +102,15 @@ export function mergeUniforms( uniforms ) {
 
 }
 
+function isThreeObject( property ) {
+
+	return ( property && ( property.isColor ||
+		property.isMatrix3 || property.isMatrix4 ||
+		property.isVector2 || property.isVector3 || property.isVector4 ||
+		property.isTexture || property.isQuaternion ) );
+
+}
+
 export function cloneUniformsGroups( src ) {
 
 	const dst = [];

+ 23 - 0
test/unit/src/renderers/shaders/UniformsUtils.tests.js

@@ -114,6 +114,29 @@ export default QUnit.module( 'Renderers', () => {
 
 			} );
 
+			QUnit.test( 'cloneUniforms clones arrays of objects', ( assert ) => {
+
+				const uniforms = {
+					vector3Array: { value: [ new Vector3( 1, 2, 3 ), new Vector3( 4, 5, 6 ) ] },
+				};
+
+				const uniformClones = UniformsUtils.clone( uniforms );
+
+				// Cloned array is a different reference and contains different object references
+				assert.ok( uniforms.vector3Array.value !== uniformClones.vector3Array.value );
+				assert.ok( uniforms.vector3Array.value[ 0 ] !== uniformClones.vector3Array.value[ 0 ] );
+				assert.ok( uniforms.vector3Array.value[ 1 ] !== uniformClones.vector3Array.value[ 1 ] );
+
+				// Values are equal after cloning
+				assert.ok( uniforms.vector3Array.value[ 0 ].equals( uniformClones.vector3Array.value[ 0 ] ) );
+				assert.ok( uniforms.vector3Array.value[ 1 ].equals( uniformClones.vector3Array.value[ 1 ] ) );
+
+				// Mutating the original does not affect the clone
+				uniforms.vector3Array.value[ 0 ].x = 123.0;
+				assert.ok( ! uniforms.vector3Array.value[ 0 ].equals( uniformClones.vector3Array.value[ 0 ] ) );
+
+			} );
+
 			QUnit.test( 'cloneUniforms skips render target textures', ( assert ) => {
 
 				const uniforms = {

粤ICP备19079148号