Przeglądaj źródła

Merge remote-tracking branch 'upstream/dev' into dev49

Mugen87 5 lat temu
rodzic
commit
95957b59d8

+ 4 - 6
build/three.js

@@ -23615,6 +23615,10 @@
 				uniforms.color.value.copy( material.color );
 				uniforms.opacity.value = material.opacity;
 
+			} else if ( material.isShaderMaterial ) {
+
+				material.uniformsNeedUpdate = false; // #15581
+
 			}
 
 		}
@@ -26016,12 +26020,6 @@
 
 				WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );
 
-				if ( material.isShaderMaterial ) {
-
-					material.uniformsNeedUpdate = false; // #15581
-
-				}
-
 			}
 
 			if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) {

+ 18 - 18
build/three.min.js

@@ -180,26 +180,26 @@ a.displacementScale.value=e.displacementScale,a.displacementBias.value=e.displac
 e.displacementMap&&(a.displacementMap.value=e.displacementMap,a.displacementScale.value=e.displacementScale,a.displacementBias.value=e.displacementBias);else if(e.isMeshDepthMaterial)b(a,e),e.displacementMap&&(a.displacementMap.value=e.displacementMap,a.displacementScale.value=e.displacementScale,a.displacementBias.value=e.displacementBias);else if(e.isMeshDistanceMaterial)b(a,e),e.displacementMap&&(a.displacementMap.value=e.displacementMap,a.displacementScale.value=e.displacementScale,a.displacementBias.value=
 e.displacementBias),a.referencePosition.value.copy(e.referencePosition),a.nearDistance.value=e.nearDistance,a.farDistance.value=e.farDistance;else if(e.isMeshNormalMaterial)b(a,e),e.bumpMap&&(a.bumpMap.value=e.bumpMap,a.bumpScale.value=e.bumpScale,1===e.side&&(a.bumpScale.value*=-1)),e.normalMap&&(a.normalMap.value=e.normalMap,a.normalScale.value.copy(e.normalScale),1===e.side&&a.normalScale.value.negate()),e.displacementMap&&(a.displacementMap.value=e.displacementMap,a.displacementScale.value=e.displacementScale,
 a.displacementBias.value=e.displacementBias);else if(e.isLineBasicMaterial)a.diffuse.value.copy(e.color),a.opacity.value=e.opacity,e.isLineDashedMaterial&&(a.dashSize.value=e.dashSize,a.totalSize.value=e.dashSize+e.gapSize,a.scale.value=e.scale);else if(e.isPointsMaterial){a.diffuse.value.copy(e.color);a.opacity.value=e.opacity;a.size.value=e.size*g;a.scale.value=.5*h;e.map&&(a.map.value=e.map);e.alphaMap&&(a.alphaMap.value=e.alphaMap);if(e.map)var d=e.map;else e.alphaMap&&(d=e.alphaMap);void 0!==
-d&&(!0===d.matrixAutoUpdate&&d.updateMatrix(),a.uvTransform.value.copy(d.matrix))}else if(e.isSpriteMaterial){a.diffuse.value.copy(e.color);a.opacity.value=e.opacity;a.rotation.value=e.rotation;e.map&&(a.map.value=e.map);e.alphaMap&&(a.alphaMap.value=e.alphaMap);if(e.map)var m=e.map;else e.alphaMap&&(m=e.alphaMap);void 0!==m&&(!0===m.matrixAutoUpdate&&m.updateMatrix(),a.uvTransform.value.copy(m.matrix))}else e.isShadowMaterial&&(a.color.value.copy(e.color),a.opacity.value=e.opacity)}}}function kg(a){var b;
-function c(){sa=new pj(H);Ga=new nj(H,sa,a);!1===Ga.isWebGL2&&(sa.get("WEBGL_depth_texture"),sa.get("OES_texture_float"),sa.get("OES_texture_half_float"),sa.get("OES_texture_half_float_linear"),sa.get("OES_standard_derivatives"),sa.get("OES_element_index_uint"),sa.get("ANGLE_instanced_arrays"));sa.get("OES_texture_float_linear");ra=new Uh(H,sa,Ga);X=new yk(H,sa,Ga);X.scissor(R.copy(ca).multiplyScalar(wa).floor());X.viewport(Y.copy(ha).multiplyScalar(wa).floor());ea=new sj(H);Q=new ok;S=new zk(H,sa,
-X,Q,Ga,ra,ea);ma=new kj(H,Ga);ta=new qj(H,ma,ea);na=new vj(H,ta,ma,ea);za=new uj(H);pa=new nk(y,sa,Ga);ya=new Ak(Q);xa=new rk;va=new xk;qa=new lj(y,X,na,oa);Aa=new mj(H,sa,ea,Ga);Ca=new rj(H,sa,ea,Ga);ea.programs=pa.programs;y.capabilities=Ga;y.extensions=sa;y.properties=Q;y.renderLists=xa;y.state=X;y.info=ea}function d(a){a.preventDefault();console.log("THREE.WebGLRenderer: Context Lost.");E=!0}function e(){console.log("THREE.WebGLRenderer: Context Restored.");E=!1;c()}function f(a){a=a.target;a.removeEventListener("dispose",
-f);g(a);Q.remove(a)}function g(a){var b=Q.get(a).program;a.program=void 0;void 0!==b&&pa.releaseProgram(b)}function h(a,b){a.render(function(a){y.renderBufferImmediate(a,b)})}function l(a,b,c,d){if(!1!==a.visible){if(a.layers.test(b.layers))if(a.isGroup)c=a.renderOrder;else if(a.isLOD)!0===a.autoUpdate&&a.update(b);else if(a.isLight)P.pushLight(a),a.castShadow&&P.pushShadow(a);else if(a.isSprite){if(!a.frustumCulled||la.intersectsSprite(a)){d&&Lb.setFromMatrixPosition(a.matrixWorld).applyMatrix4(ja);
-var e=na.update(a),f=a.material;f.visible&&B.push(a,e,f,c,Lb.z,null)}}else if(a.isImmediateRenderObject)d&&Lb.setFromMatrixPosition(a.matrixWorld).applyMatrix4(ja),B.push(a,null,a.material,c,Lb.z,null);else if(a.isMesh||a.isLine||a.isPoints)if(a.isSkinnedMesh&&a.skeleton.frame!==ea.render.frame&&(a.skeleton.update(),a.skeleton.frame=ea.render.frame),!a.frustumCulled||la.intersectsObject(a))if(d&&Lb.setFromMatrixPosition(a.matrixWorld).applyMatrix4(ja),e=na.update(a),f=a.material,Array.isArray(f))for(var g=
-e.groups,h=0,m=g.length;h<m;h++){var n=g[h],k=f[n.materialIndex];k&&k.visible&&B.push(a,e,k,c,Lb.z,n)}else f.visible&&B.push(a,e,f,c,Lb.z,null);a=a.children;h=0;for(m=a.length;h<m;h++)l(a[h],b,c,d)}}function m(a,b,c,d){for(var e=0,f=a.length;e<f;e++){var g=a[e],h=g.object,l=g.geometry,m=void 0===d?g.material:d;g=g.group;if(c.isArrayCamera){Ke=c;for(var n=c.cameras,A=0,q=n.length;A<q;A++){var t=n[A];h.layers.test(t.layers)&&(X.viewport(Y.copy(t.viewport)),P.setupLights(t),k(h,b,t,l,m,g))}}else Ke=
-null,k(h,b,c,l,m,g)}}function k(a,c,d,e,f,g){a.onBeforeRender(y,c,d,e,f,g);P=va.get(c,Ke||d);a.modelViewMatrix.multiplyMatrices(d.matrixWorldInverse,a.matrixWorld);a.normalMatrix.getNormalMatrix(a.modelViewMatrix);if(a.isImmediateRenderObject){var l=t(d,c,f,a);X.setMaterial(f);V=b=null;Je=!1;h(a,l)}else y.renderBufferDirect(d,c,e,f,a,g);a.onAfterRender(y,c,d,e,f,g);P=va.get(c,Ke||d)}function n(a,b,c){var d=Q.get(a),e=P.state.lights,h=e.state.version;c=pa.getParameters(a,e.state,P.state.shadowsArray,
-b,ia.numPlanes,ia.numIntersection,c);var l=pa.getProgramCacheKey(c),m=d.program,n=!0;if(void 0===m)a.addEventListener("dispose",f);else if(m.cacheKey!==l)g(a);else{if(d.lightsStateVersion!==h)d.lightsStateVersion=h;else if(void 0!==c.shaderID)return;n=!1}n&&(m=pa.acquireProgram(c,l),d.program=m,d.uniforms=c.uniforms,d.outputEncoding=c.outputEncoding,a.program=m);c=m.getAttributes();if(a.morphTargets)for(l=a.numSupportedMorphTargets=0;l<y.maxMorphTargets;l++)0<=c["morphTarget"+l]&&a.numSupportedMorphTargets++;
-if(a.morphNormals)for(l=a.numSupportedMorphNormals=0;l<y.maxMorphNormals;l++)0<=c["morphNormal"+l]&&a.numSupportedMorphNormals++;c=d.uniforms;if(!a.isShaderMaterial&&!a.isRawShaderMaterial||!0===a.clipping)d.numClippingPlanes=ia.numPlanes,d.numIntersection=ia.numIntersection,c.clippingPlanes=ia.uniform;d.environment=a.isMeshStandardMaterial?b.environment:null;d.fog=b.fog;d.needsLights=a.isMeshLambertMaterial||a.isMeshToonMaterial||a.isMeshPhongMaterial||a.isMeshStandardMaterial||a.isShadowMaterial||
-a.isShaderMaterial&&!0===a.lights;d.lightsStateVersion=h;d.needsLights&&(c.ambientLightColor.value=e.state.ambient,c.lightProbe.value=e.state.probe,c.directionalLights.value=e.state.directional,c.directionalLightShadows.value=e.state.directionalShadow,c.spotLights.value=e.state.spot,c.spotLightShadows.value=e.state.spotShadow,c.rectAreaLights.value=e.state.rectArea,c.pointLights.value=e.state.point,c.pointLightShadows.value=e.state.pointShadow,c.hemisphereLights.value=e.state.hemi,c.directionalShadowMap.value=
-e.state.directionalShadowMap,c.directionalShadowMatrix.value=e.state.directionalShadowMatrix,c.spotShadowMap.value=e.state.spotShadowMap,c.spotShadowMatrix.value=e.state.spotShadowMatrix,c.pointShadowMap.value=e.state.pointShadowMap,c.pointShadowMatrix.value=e.state.pointShadowMatrix);a=d.program.getUniforms();a=Ib.seqWithValue(a.seq,c);d.uniformsList=a}function t(a,b,c,d){S.resetTextureUnits();var e=b.fog,f=c.isMeshStandardMaterial?b.environment:null,g=null===F?y.outputEncoding:F.texture.encoding,
-h=Q.get(c),l=P.state.lights;Ie&&(jg||a!==da)&&ia.setState(c.clippingPlanes,c.clipIntersection,c.clipShadows,a,h,a===da&&c.id===N);c.version===h.__version?void 0===h.program?n(c,b,d):c.fog&&h.fog!==e?n(c,b,d):h.environment!==f?n(c,b,d):h.needsLights&&h.lightsStateVersion!==l.state.version?n(c,b,d):void 0===h.numClippingPlanes||h.numClippingPlanes===ia.numPlanes&&h.numIntersection===ia.numIntersection?h.outputEncoding!==g&&n(c,b,d):n(c,b,d):(n(c,b,d),h.__version=c.version);var m=!1,k=!1,A=!1;b=h.program;
-g=b.getUniforms();l=h.uniforms;X.useProgram(b.program)&&(A=k=m=!0);c.id!==N&&(N=c.id,k=!0);if(m||da!==a){g.setValue(H,"projectionMatrix",a.projectionMatrix);Ga.logarithmicDepthBuffer&&g.setValue(H,"logDepthBufFC",2/(Math.log(a.far+1)/Math.LN2));da!==a&&(da=a,A=k=!0);if(c.isShaderMaterial||c.isMeshPhongMaterial||c.isMeshToonMaterial||c.isMeshStandardMaterial||c.envMap)m=g.map.cameraPosition,void 0!==m&&m.setValue(H,Lb.setFromMatrixPosition(a.matrixWorld));(c.isMeshPhongMaterial||c.isMeshToonMaterial||
-c.isMeshLambertMaterial||c.isMeshBasicMaterial||c.isMeshStandardMaterial||c.isShaderMaterial)&&g.setValue(H,"isOrthographic",!0===a.isOrthographicCamera);(c.isMeshPhongMaterial||c.isMeshToonMaterial||c.isMeshLambertMaterial||c.isMeshBasicMaterial||c.isMeshStandardMaterial||c.isShaderMaterial||c.skinning)&&g.setValue(H,"viewMatrix",a.matrixWorldInverse)}if(c.skinning&&(g.setOptional(H,d,"bindMatrix"),g.setOptional(H,d,"bindMatrixInverse"),a=d.skeleton))if(m=a.bones,Ga.floatVertexTextures){if(void 0===
+d&&(!0===d.matrixAutoUpdate&&d.updateMatrix(),a.uvTransform.value.copy(d.matrix))}else if(e.isSpriteMaterial){a.diffuse.value.copy(e.color);a.opacity.value=e.opacity;a.rotation.value=e.rotation;e.map&&(a.map.value=e.map);e.alphaMap&&(a.alphaMap.value=e.alphaMap);if(e.map)var m=e.map;else e.alphaMap&&(m=e.alphaMap);void 0!==m&&(!0===m.matrixAutoUpdate&&m.updateMatrix(),a.uvTransform.value.copy(m.matrix))}else e.isShadowMaterial?(a.color.value.copy(e.color),a.opacity.value=e.opacity):e.isShaderMaterial&&
+(e.uniformsNeedUpdate=!1)}}}function kg(a){var b;function c(){sa=new pj(H);Ga=new nj(H,sa,a);!1===Ga.isWebGL2&&(sa.get("WEBGL_depth_texture"),sa.get("OES_texture_float"),sa.get("OES_texture_half_float"),sa.get("OES_texture_half_float_linear"),sa.get("OES_standard_derivatives"),sa.get("OES_element_index_uint"),sa.get("ANGLE_instanced_arrays"));sa.get("OES_texture_float_linear");ra=new Uh(H,sa,Ga);X=new yk(H,sa,Ga);X.scissor(R.copy(ca).multiplyScalar(wa).floor());X.viewport(Y.copy(ha).multiplyScalar(wa).floor());
+ea=new sj(H);Q=new ok;S=new zk(H,sa,X,Q,Ga,ra,ea);ma=new kj(H,Ga);ta=new qj(H,ma,ea);na=new vj(H,ta,ma,ea);za=new uj(H);pa=new nk(y,sa,Ga);ya=new Ak(Q);xa=new rk;va=new xk;qa=new lj(y,X,na,oa);Aa=new mj(H,sa,ea,Ga);Ca=new rj(H,sa,ea,Ga);ea.programs=pa.programs;y.capabilities=Ga;y.extensions=sa;y.properties=Q;y.renderLists=xa;y.state=X;y.info=ea}function d(a){a.preventDefault();console.log("THREE.WebGLRenderer: Context Lost.");E=!0}function e(){console.log("THREE.WebGLRenderer: Context Restored.");
+E=!1;c()}function f(a){a=a.target;a.removeEventListener("dispose",f);g(a);Q.remove(a)}function g(a){var b=Q.get(a).program;a.program=void 0;void 0!==b&&pa.releaseProgram(b)}function h(a,b){a.render(function(a){y.renderBufferImmediate(a,b)})}function l(a,b,c,d){if(!1!==a.visible){if(a.layers.test(b.layers))if(a.isGroup)c=a.renderOrder;else if(a.isLOD)!0===a.autoUpdate&&a.update(b);else if(a.isLight)P.pushLight(a),a.castShadow&&P.pushShadow(a);else if(a.isSprite){if(!a.frustumCulled||la.intersectsSprite(a)){d&&
+Lb.setFromMatrixPosition(a.matrixWorld).applyMatrix4(ja);var e=na.update(a),f=a.material;f.visible&&B.push(a,e,f,c,Lb.z,null)}}else if(a.isImmediateRenderObject)d&&Lb.setFromMatrixPosition(a.matrixWorld).applyMatrix4(ja),B.push(a,null,a.material,c,Lb.z,null);else if(a.isMesh||a.isLine||a.isPoints)if(a.isSkinnedMesh&&a.skeleton.frame!==ea.render.frame&&(a.skeleton.update(),a.skeleton.frame=ea.render.frame),!a.frustumCulled||la.intersectsObject(a))if(d&&Lb.setFromMatrixPosition(a.matrixWorld).applyMatrix4(ja),
+e=na.update(a),f=a.material,Array.isArray(f))for(var g=e.groups,h=0,m=g.length;h<m;h++){var n=g[h],k=f[n.materialIndex];k&&k.visible&&B.push(a,e,k,c,Lb.z,n)}else f.visible&&B.push(a,e,f,c,Lb.z,null);a=a.children;h=0;for(m=a.length;h<m;h++)l(a[h],b,c,d)}}function m(a,b,c,d){for(var e=0,f=a.length;e<f;e++){var g=a[e],h=g.object,l=g.geometry,m=void 0===d?g.material:d;g=g.group;if(c.isArrayCamera){Ke=c;for(var n=c.cameras,A=0,q=n.length;A<q;A++){var t=n[A];h.layers.test(t.layers)&&(X.viewport(Y.copy(t.viewport)),
+P.setupLights(t),k(h,b,t,l,m,g))}}else Ke=null,k(h,b,c,l,m,g)}}function k(a,c,d,e,f,g){a.onBeforeRender(y,c,d,e,f,g);P=va.get(c,Ke||d);a.modelViewMatrix.multiplyMatrices(d.matrixWorldInverse,a.matrixWorld);a.normalMatrix.getNormalMatrix(a.modelViewMatrix);if(a.isImmediateRenderObject){var l=t(d,c,f,a);X.setMaterial(f);V=b=null;Je=!1;h(a,l)}else y.renderBufferDirect(d,c,e,f,a,g);a.onAfterRender(y,c,d,e,f,g);P=va.get(c,Ke||d)}function n(a,b,c){var d=Q.get(a),e=P.state.lights,h=e.state.version;c=pa.getParameters(a,
+e.state,P.state.shadowsArray,b,ia.numPlanes,ia.numIntersection,c);var l=pa.getProgramCacheKey(c),m=d.program,n=!0;if(void 0===m)a.addEventListener("dispose",f);else if(m.cacheKey!==l)g(a);else{if(d.lightsStateVersion!==h)d.lightsStateVersion=h;else if(void 0!==c.shaderID)return;n=!1}n&&(m=pa.acquireProgram(c,l),d.program=m,d.uniforms=c.uniforms,d.outputEncoding=c.outputEncoding,a.program=m);c=m.getAttributes();if(a.morphTargets)for(l=a.numSupportedMorphTargets=0;l<y.maxMorphTargets;l++)0<=c["morphTarget"+
+l]&&a.numSupportedMorphTargets++;if(a.morphNormals)for(l=a.numSupportedMorphNormals=0;l<y.maxMorphNormals;l++)0<=c["morphNormal"+l]&&a.numSupportedMorphNormals++;c=d.uniforms;if(!a.isShaderMaterial&&!a.isRawShaderMaterial||!0===a.clipping)d.numClippingPlanes=ia.numPlanes,d.numIntersection=ia.numIntersection,c.clippingPlanes=ia.uniform;d.environment=a.isMeshStandardMaterial?b.environment:null;d.fog=b.fog;d.needsLights=a.isMeshLambertMaterial||a.isMeshToonMaterial||a.isMeshPhongMaterial||a.isMeshStandardMaterial||
+a.isShadowMaterial||a.isShaderMaterial&&!0===a.lights;d.lightsStateVersion=h;d.needsLights&&(c.ambientLightColor.value=e.state.ambient,c.lightProbe.value=e.state.probe,c.directionalLights.value=e.state.directional,c.directionalLightShadows.value=e.state.directionalShadow,c.spotLights.value=e.state.spot,c.spotLightShadows.value=e.state.spotShadow,c.rectAreaLights.value=e.state.rectArea,c.pointLights.value=e.state.point,c.pointLightShadows.value=e.state.pointShadow,c.hemisphereLights.value=e.state.hemi,
+c.directionalShadowMap.value=e.state.directionalShadowMap,c.directionalShadowMatrix.value=e.state.directionalShadowMatrix,c.spotShadowMap.value=e.state.spotShadowMap,c.spotShadowMatrix.value=e.state.spotShadowMatrix,c.pointShadowMap.value=e.state.pointShadowMap,c.pointShadowMatrix.value=e.state.pointShadowMatrix);a=d.program.getUniforms();a=Ib.seqWithValue(a.seq,c);d.uniformsList=a}function t(a,b,c,d){S.resetTextureUnits();var e=b.fog,f=c.isMeshStandardMaterial?b.environment:null,g=null===F?y.outputEncoding:
+F.texture.encoding,h=Q.get(c),l=P.state.lights;Ie&&(jg||a!==da)&&ia.setState(c.clippingPlanes,c.clipIntersection,c.clipShadows,a,h,a===da&&c.id===N);c.version===h.__version?void 0===h.program?n(c,b,d):c.fog&&h.fog!==e?n(c,b,d):h.environment!==f?n(c,b,d):h.needsLights&&h.lightsStateVersion!==l.state.version?n(c,b,d):void 0===h.numClippingPlanes||h.numClippingPlanes===ia.numPlanes&&h.numIntersection===ia.numIntersection?h.outputEncoding!==g&&n(c,b,d):n(c,b,d):(n(c,b,d),h.__version=c.version);var m=
+!1,k=!1,A=!1;b=h.program;g=b.getUniforms();l=h.uniforms;X.useProgram(b.program)&&(A=k=m=!0);c.id!==N&&(N=c.id,k=!0);if(m||da!==a){g.setValue(H,"projectionMatrix",a.projectionMatrix);Ga.logarithmicDepthBuffer&&g.setValue(H,"logDepthBufFC",2/(Math.log(a.far+1)/Math.LN2));da!==a&&(da=a,A=k=!0);if(c.isShaderMaterial||c.isMeshPhongMaterial||c.isMeshToonMaterial||c.isMeshStandardMaterial||c.envMap)m=g.map.cameraPosition,void 0!==m&&m.setValue(H,Lb.setFromMatrixPosition(a.matrixWorld));(c.isMeshPhongMaterial||
+c.isMeshToonMaterial||c.isMeshLambertMaterial||c.isMeshBasicMaterial||c.isMeshStandardMaterial||c.isShaderMaterial)&&g.setValue(H,"isOrthographic",!0===a.isOrthographicCamera);(c.isMeshPhongMaterial||c.isMeshToonMaterial||c.isMeshLambertMaterial||c.isMeshBasicMaterial||c.isMeshStandardMaterial||c.isShaderMaterial||c.skinning)&&g.setValue(H,"viewMatrix",a.matrixWorldInverse)}if(c.skinning&&(g.setOptional(H,d,"bindMatrix"),g.setOptional(H,d,"bindMatrixInverse"),a=d.skeleton))if(m=a.bones,Ga.floatVertexTextures){if(void 0===
 a.boneTexture){m=Math.sqrt(4*m.length);m=M.ceilPowerOfTwo(m);m=Math.max(m,4);var q=new Float32Array(m*m*4);q.set(a.boneMatrices);var t=new ac(q,m,m,1023,1015);a.boneMatrices=q;a.boneTexture=t;a.boneTextureSize=m}g.setValue(H,"boneTexture",a.boneTexture,S);g.setValue(H,"boneTextureSize",a.boneTextureSize)}else g.setOptional(H,a,"boneMatrices");if(k||h.receiveShadow!==d.receiveShadow)h.receiveShadow=d.receiveShadow,g.setValue(H,"receiveShadow",d.receiveShadow);k&&(g.setValue(H,"toneMappingExposure",
 y.toneMappingExposure),g.setValue(H,"toneMappingWhitePoint",y.toneMappingWhitePoint),h.needsLights&&(k=A,l.ambientLightColor.needsUpdate=k,l.lightProbe.needsUpdate=k,l.directionalLights.needsUpdate=k,l.directionalLightShadows.needsUpdate=k,l.pointLights.needsUpdate=k,l.pointLightShadows.needsUpdate=k,l.spotLights.needsUpdate=k,l.spotLightShadows.needsUpdate=k,l.rectAreaLights.needsUpdate=k,l.hemisphereLights.needsUpdate=k),e&&c.fog&&ya.refreshFogUniforms(l,e),ya.refreshMaterialUniforms(l,c,f,wa,Ra),
-void 0!==l.ltc_1&&(l.ltc_1.value=z.LTC_1),void 0!==l.ltc_2&&(l.ltc_2.value=z.LTC_2),Ib.upload(H,h.uniformsList,l,S),c.isShaderMaterial&&(c.uniformsNeedUpdate=!1));c.isShaderMaterial&&!0===c.uniformsNeedUpdate&&(Ib.upload(H,h.uniformsList,l,S),c.uniformsNeedUpdate=!1);c.isSpriteMaterial&&g.setValue(H,"center",d.center);g.setValue(H,"modelViewMatrix",d.modelViewMatrix);g.setValue(H,"normalMatrix",d.normalMatrix);g.setValue(H,"modelMatrix",d.matrixWorld);return b}a=a||{};var r=void 0!==a.canvas?a.canvas:
-document.createElementNS("http://www.w3.org/1999/xhtml","canvas"),q=void 0!==a.context?a.context:null,u=void 0!==a.alpha?a.alpha:!1,G=void 0!==a.depth?a.depth:!0,x=void 0!==a.stencil?a.stencil:!0,w=void 0!==a.antialias?a.antialias:!1,oa=void 0!==a.premultipliedAlpha?a.premultipliedAlpha:!0,T=void 0!==a.preserveDrawingBuffer?a.preserveDrawingBuffer:!1,Z=void 0!==a.powerPreference?a.powerPreference:"default",C=void 0!==a.failIfMajorPerformanceCaveat?a.failIfMajorPerformanceCaveat:!1,B=null,P=null;this.domElement=
-r;this.debug={checkShaderErrors:!0};this.sortObjects=this.autoClearStencil=this.autoClearDepth=this.autoClearColor=this.autoClear=!0;this.clippingPlanes=[];this.localClippingEnabled=!1;this.gammaFactor=2;this.outputEncoding=3E3;this.physicallyCorrectLights=!1;this.toneMapping=0;this.toneMappingWhitePoint=this.toneMappingExposure=1;this.maxMorphTargets=8;this.maxMorphNormals=4;var y=this,E=!1,D=null,I=0,L=0,F=null,K=null,N=-1;var V=b=null;var Je=!1;var da=null,Ke=null,Y=new fa,R=new fa,aa=null,W=r.width,
-Ra=r.height,wa=1,J=null,ba=null,ha=new fa(0,0,W,Ra),ca=new fa(0,0,W,Ra),ka=!1,la=new Gc,ia=new oj,Ie=!1,jg=!1,ja=new O,Lb=new p;try{u={alpha:u,depth:G,stencil:x,antialias:w,premultipliedAlpha:oa,preserveDrawingBuffer:T,powerPreference:Z,failIfMajorPerformanceCaveat:C,xrCompatible:!0};r.addEventListener("webglcontextlost",d,!1);r.addEventListener("webglcontextrestored",e,!1);var H=q||r.getContext("webgl",u)||r.getContext("experimental-webgl",u);if(null===H){if(null!==r.getContext("webgl"))throw Error("Error creating WebGL context with your selected attributes.");
+void 0!==l.ltc_1&&(l.ltc_1.value=z.LTC_1),void 0!==l.ltc_2&&(l.ltc_2.value=z.LTC_2),Ib.upload(H,h.uniformsList,l,S));c.isShaderMaterial&&!0===c.uniformsNeedUpdate&&(Ib.upload(H,h.uniformsList,l,S),c.uniformsNeedUpdate=!1);c.isSpriteMaterial&&g.setValue(H,"center",d.center);g.setValue(H,"modelViewMatrix",d.modelViewMatrix);g.setValue(H,"normalMatrix",d.normalMatrix);g.setValue(H,"modelMatrix",d.matrixWorld);return b}a=a||{};var r=void 0!==a.canvas?a.canvas:document.createElementNS("http://www.w3.org/1999/xhtml",
+"canvas"),q=void 0!==a.context?a.context:null,u=void 0!==a.alpha?a.alpha:!1,G=void 0!==a.depth?a.depth:!0,x=void 0!==a.stencil?a.stencil:!0,w=void 0!==a.antialias?a.antialias:!1,oa=void 0!==a.premultipliedAlpha?a.premultipliedAlpha:!0,T=void 0!==a.preserveDrawingBuffer?a.preserveDrawingBuffer:!1,Z=void 0!==a.powerPreference?a.powerPreference:"default",C=void 0!==a.failIfMajorPerformanceCaveat?a.failIfMajorPerformanceCaveat:!1,B=null,P=null;this.domElement=r;this.debug={checkShaderErrors:!0};this.sortObjects=
+this.autoClearStencil=this.autoClearDepth=this.autoClearColor=this.autoClear=!0;this.clippingPlanes=[];this.localClippingEnabled=!1;this.gammaFactor=2;this.outputEncoding=3E3;this.physicallyCorrectLights=!1;this.toneMapping=0;this.toneMappingWhitePoint=this.toneMappingExposure=1;this.maxMorphTargets=8;this.maxMorphNormals=4;var y=this,E=!1,D=null,I=0,L=0,F=null,K=null,N=-1;var V=b=null;var Je=!1;var da=null,Ke=null,Y=new fa,R=new fa,aa=null,W=r.width,Ra=r.height,wa=1,J=null,ba=null,ha=new fa(0,0,
+W,Ra),ca=new fa(0,0,W,Ra),ka=!1,la=new Gc,ia=new oj,Ie=!1,jg=!1,ja=new O,Lb=new p;try{u={alpha:u,depth:G,stencil:x,antialias:w,premultipliedAlpha:oa,preserveDrawingBuffer:T,powerPreference:Z,failIfMajorPerformanceCaveat:C,xrCompatible:!0};r.addEventListener("webglcontextlost",d,!1);r.addEventListener("webglcontextrestored",e,!1);var H=q||r.getContext("webgl",u)||r.getContext("experimental-webgl",u);if(null===H){if(null!==r.getContext("webgl"))throw Error("Error creating WebGL context with your selected attributes.");
 throw Error("Error creating WebGL context.");}void 0===H.getShaderPrecisionFormat&&(H.getShaderPrecisionFormat=function(){return{rangeMin:1,rangeMax:1,precision:1}})}catch(Wh){throw console.error("THREE.WebGLRenderer: "+Wh.message),Wh;}var sa,Ga,X,ea,Q,S,ma,ta,na,pa,ya,xa,va,qa,za,Aa,Ca,ra;c();var ua=new Vh(y,H);this.xr=ua;var Fa=new Sh(y,na,Ga.maxTextureSize);this.shadowMap=Fa;this.getContext=function(){return H};this.getContextAttributes=function(){return H.getContextAttributes()};this.forceContextLoss=
 function(){var a=sa.get("WEBGL_lose_context");a&&a.loseContext()};this.forceContextRestore=function(){var a=sa.get("WEBGL_lose_context");a&&a.restoreContext()};this.getPixelRatio=function(){return wa};this.setPixelRatio=function(a){void 0!==a&&(wa=a,this.setSize(W,Ra,!1))};this.getSize=function(a){void 0===a&&(console.warn("WebGLRenderer: .getsize() now requires a Vector2 as an argument"),a=new v);return a.set(W,Ra)};this.setSize=function(a,b,c){ua.isPresenting?console.warn("THREE.WebGLRenderer: Can't change size while VR device is presenting."):
 (W=a,Ra=b,r.width=Math.floor(a*wa),r.height=Math.floor(b*wa),!1!==c&&(r.style.width=a+"px",r.style.height=b+"px"),this.setViewport(0,0,a,b))};this.getDrawingBufferSize=function(a){void 0===a&&(console.warn("WebGLRenderer: .getdrawingBufferSize() now requires a Vector2 as an argument"),a=new v);return a.set(W*wa,Ra*wa).floor()};this.setDrawingBufferSize=function(a,b,c){W=a;Ra=b;wa=c;r.width=Math.floor(a*c);r.height=Math.floor(b*c);this.setViewport(0,0,a,b)};this.getCurrentViewport=function(a){void 0===

+ 4 - 6
build/three.module.js

@@ -23607,6 +23607,10 @@ function WebGLMaterials( properties ) {
 			uniforms.color.value.copy( material.color );
 			uniforms.opacity.value = material.opacity;
 
+		} else if ( material.isShaderMaterial ) {
+
+			material.uniformsNeedUpdate = false; // #15581
+
 		}
 
 	}
@@ -26008,12 +26012,6 @@ function WebGLRenderer( parameters ) {
 
 			WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );
 
-			if ( material.isShaderMaterial ) {
-
-				material.uniformsNeedUpdate = false; // #15581
-
-			}
-
 		}
 
 		if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) {

+ 2 - 2
docs/api/en/core/InstancedBufferGeometry.html

@@ -24,9 +24,9 @@
 		<h2>Properties</h2>
 		<p>See [page:BufferGeometry] for inherited properties.</p>
 
-		<h3>[property:Number maxInstancedCount]</h3>
+		<h3>[property:Number instanceCount]</h3>
 		<p>
-			Default is *undefined*.
+			Default is *Infinity*.
 		</p>
 
 		<h2>Methods</h2>

+ 1 - 4
docs/api/en/math/Matrix4.html

@@ -125,10 +125,7 @@ m.elements = [ 11, 21, 31, 41,
 		<h3>[method:this compose]( [param:Vector3 position], [param:Quaternion quaternion], [param:Vector3 scale] )</h3>
 		<p>
 		Sets this matrix to the transformation composed of [page:Vector3 position],
-		[page:Quaternion quaternion] and [page:Vector3 scale]. Internally this calls
-		[page:.makeRotationFromQuaternion makeRotationFromQuaternion]( [page:Quaternion quaternion] )
-		followed by [page:.scale scale]( [page:Vector3 scale] ), then finally
-		[page:.setPosition setPosition]( [page:Vector3 position] ).
+		[page:Quaternion quaternion] and [page:Vector3 scale].
 		</p>
 
 		<h3>[method:this copy]( [param:Matrix4 m] )</h3>

+ 2 - 2
docs/api/zh/core/InstancedBufferGeometry.html

@@ -24,9 +24,9 @@
 		<h2>属性</h2>
 		<p>继承属性详见 [page:BufferGeometry]。</p>
 
-		<h3>[property:Number maxInstancedCount]</h3>
+		<h3>[property:Number instanceCount]</h3>
 		<p>
-			默认值是 *undefined*。
+			默认值是 *Infinity*。
 		</p>
 
 		<h2>方法</h2>

+ 0 - 2
docs/api/zh/math/Matrix4.html

@@ -117,8 +117,6 @@ m.elements = [ 11, 21, 31, 41,
 		<h3>[method:this compose]( [param:Vector3 position], [param:Quaternion quaternion], [param:Vector3 scale] )</h3>
 		<p>
 		设置将该对象由位置[page:Vector3 position],四元数[page:Quaternion quaternion] 和 缩放[page:Vector3 scale]
-		组合变换的矩阵。内部先调用[page:.makeRotationFromQuaternion makeRotationFromQuaternion]( [page:Quaternion quaternion] )
-		再调用缩放[page:.scale scale]( [page:Vector3 scale] )最后是平移[page:.setPosition setPosition]( [page:Vector3 position] )。
 		</p>
 
 		<h3>[method:this copy]( [param:Matrix4 m] )</h3>

+ 1 - 0
examples/files.js

@@ -298,6 +298,7 @@ var files = {
 		"webgl_custom_attributes_points3",
 		"webgl_fire",
 		"webgl_gpgpu_birds",
+		"webgl_gpgpu_birds_gltf",
 		"webgl_gpgpu_water",
 		"webgl_gpgpu_protoplanet",
 		"webgl_instancing_modified",

+ 2 - 0
examples/js/controls/DragControls.js

@@ -44,6 +44,8 @@ THREE.DragControls = function ( _objects, _camera, _domElement ) {
 		_domElement.removeEventListener( 'touchstart', onDocumentTouchStart, false );
 		_domElement.removeEventListener( 'touchend', onDocumentTouchEnd, false );
 
+		_domElement.style.cursor = '';
+
 	}
 
 	function dispose() {

+ 2 - 0
examples/jsm/controls/DragControls.js

@@ -53,6 +53,8 @@ var DragControls = function ( _objects, _camera, _domElement ) {
 		_domElement.removeEventListener( 'touchstart', onDocumentTouchStart, false );
 		_domElement.removeEventListener( 'touchend', onDocumentTouchEnd, false );
 
+		_domElement.style.cursor = '';
+
 	}
 
 	function dispose() {

+ 2 - 2
examples/webgl_buffergeometry_instancing.html

@@ -145,7 +145,7 @@
 			}
 
 			var geometry = new THREE.InstancedBufferGeometry();
-			geometry.maxInstancedCount = instances; // set so its initalized for dat.GUI, will be set in first draw otherwise
+			geometry.instanceCount = instances; // set so its initalized for dat.GUI, will be set in first draw otherwise
 
 			geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( positions, 3 ) );
 
@@ -191,7 +191,7 @@
 			//
 
 			var gui = new GUI( { width: 350 } );
-			gui.add( geometry, 'maxInstancedCount', 0, instances );
+			gui.add( geometry, 'instanceCount', 0, instances );
 
 			//
 

+ 664 - 0
examples/webgl_gpgpu_birds_gltf.html

@@ -0,0 +1,664 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - gpgpu - flocking</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<link type="text/css" rel="stylesheet" href="main.css">
+		<style>
+			body {
+				background-color: #fff;
+				color: #444;
+			}
+			a {
+				color:#08f;
+			}
+		</style>
+	</head>
+	<body>
+
+		<div id="info">
+			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - webgl gpgpu birds + GLTF mesh<br/>
+			Flamingo by <a href="http://mirada.com/">mirada</a> from <a href="http://ro.me">rome</a><br/>
+			Move mouse to disturb birds. 
+		</div>
+
+		<!-- shader for bird's position -->
+		<script id="fragmentShaderPosition" type="x-shader/x-fragment">
+
+			uniform float time;
+			uniform float delta;
+
+			void main()	{
+
+				vec2 uv = gl_FragCoord.xy / resolution.xy;
+				vec4 tmpPos = texture2D( texturePosition, uv );
+				vec3 position = tmpPos.xyz;
+				vec3 velocity = texture2D( textureVelocity, uv ).xyz;
+
+				float phase = tmpPos.w;
+
+				phase = mod( ( phase + delta +
+					length( velocity.xz ) * delta * 3. +
+					max( velocity.y, 0.0 ) * delta * 6. ), 62.83 );
+
+				gl_FragColor = vec4( position + velocity * delta * 15. , phase );
+
+			}
+
+		</script>
+
+		<!-- shader for bird's velocity -->
+		<script id="fragmentShaderVelocity" type="x-shader/x-fragment">
+
+			uniform float time;
+			uniform float testing;
+			uniform float delta; // about 0.016
+			uniform float separationDistance; // 20
+			uniform float alignmentDistance; // 40
+			uniform float cohesionDistance; //
+			uniform float freedomFactor;
+			uniform vec3 predator;
+
+			const float width = resolution.x;
+			const float height = resolution.y;
+
+			const float PI = 3.141592653589793;
+			const float PI_2 = PI * 2.0;
+			// const float VISION = PI * 0.55;
+
+			float zoneRadius = 40.0;
+			float zoneRadiusSquared = 1600.0;
+
+			float separationThresh = 0.45;
+			float alignmentThresh = 0.65;
+
+			const float UPPER_BOUNDS = BOUNDS;
+			const float LOWER_BOUNDS = -UPPER_BOUNDS;
+
+			const float SPEED_LIMIT = 9.0;
+
+			float rand( vec2 co ){
+				return fract( sin( dot( co.xy, vec2(12.9898,78.233) ) ) * 43758.5453 );
+			}
+
+			void main() {
+
+				zoneRadius = separationDistance + alignmentDistance + cohesionDistance;
+				separationThresh = separationDistance / zoneRadius;
+				alignmentThresh = ( separationDistance + alignmentDistance ) / zoneRadius;
+				zoneRadiusSquared = zoneRadius * zoneRadius;
+
+
+				vec2 uv = gl_FragCoord.xy / resolution.xy;
+				vec3 birdPosition, birdVelocity;
+
+				vec3 selfPosition = texture2D( texturePosition, uv ).xyz;
+				vec3 selfVelocity = texture2D( textureVelocity, uv ).xyz;
+
+				float dist;
+				vec3 dir; // direction
+				float distSquared;
+
+				float separationSquared = separationDistance * separationDistance;
+				float cohesionSquared = cohesionDistance * cohesionDistance;
+
+				float f;
+				float percent;
+
+				vec3 velocity = selfVelocity;
+
+				float limit = SPEED_LIMIT;
+
+				dir = predator * UPPER_BOUNDS - selfPosition;
+				dir.z = 0.;
+				// dir.z *= 0.6;
+				dist = length( dir );
+				distSquared = dist * dist;
+
+				float preyRadius = 150.0;
+				float preyRadiusSq = preyRadius * preyRadius;
+
+
+				// move birds away from predator
+				if ( dist < preyRadius ) {
+
+					f = ( distSquared / preyRadiusSq - 1.0 ) * delta * 100.;
+					velocity += normalize( dir ) * f;
+					limit += 5.0;
+				}
+
+
+				// if (testing == 0.0) {}
+				// if ( rand( uv + time ) < freedomFactor ) {}
+
+
+				// Attract flocks to the center
+				vec3 central = vec3( 0., 0., 0. );
+				dir = selfPosition - central;
+				dist = length( dir );
+
+				dir.y *= 2.5;
+				velocity -= normalize( dir ) * delta * 5.;
+
+				for ( float y = 0.0; y < height; y++ ) {
+					for ( float x = 0.0; x < width; x++ ) {
+
+						vec2 ref = vec2( x + 0.5, y + 0.5 ) / resolution.xy;
+						birdPosition = texture2D( texturePosition, ref ).xyz;
+
+						dir = birdPosition - selfPosition;
+						dist = length( dir );
+
+						if ( dist < 0.0001 ) continue;
+
+						distSquared = dist * dist;
+
+						if ( distSquared > zoneRadiusSquared ) continue;
+
+						percent = distSquared / zoneRadiusSquared;
+
+						if ( percent < separationThresh ) { // low
+
+							// Separation - Move apart for comfort
+							f = ( separationThresh / percent - 1.0 ) * delta;
+							velocity -= normalize( dir ) * f;
+
+						} else if ( percent < alignmentThresh ) { // high
+
+							// Alignment - fly the same direction
+							float threshDelta = alignmentThresh - separationThresh;
+							float adjustedPercent = ( percent - separationThresh ) / threshDelta;
+
+							birdVelocity = texture2D( textureVelocity, ref ).xyz;
+
+							f = ( 0.5 - cos( adjustedPercent * PI_2 ) * 0.5 + 0.5 ) * delta;
+							velocity += normalize( birdVelocity ) * f;
+
+						} else {
+
+							// Attraction / Cohesion - move closer
+							float threshDelta = 1.0 - alignmentThresh;
+							float adjustedPercent = ( percent - alignmentThresh ) / threshDelta;
+
+							f = ( 0.5 - ( cos( adjustedPercent * PI_2 ) * -0.5 + 0.5 ) ) * delta;
+
+							velocity += normalize( dir ) * f;
+
+						}
+
+					}
+
+				}
+
+				// this make tends to fly around than down or up
+				// if (velocity.y > 0.) velocity.y *= (1. - 0.2 * delta);
+
+				// Speed Limits
+				if ( length( velocity ) > limit ) {
+					velocity = normalize( velocity ) * limit;
+				}
+
+				gl_FragColor = vec4( velocity, 1.0 );
+
+			}
+
+		</script>
+
+		<script type="module">
+
+			import * as THREE from '../build/three.module.js';
+			import Stats from './jsm/libs/stats.module.js';
+			import { GUI } from './jsm/libs/dat.gui.module.js';
+			import { GLTFLoader } from './jsm/loaders/GLTFLoader.js';
+			import { GPUComputationRenderer } from './jsm/misc/GPUComputationRenderer.js';
+
+			/* TEXTURE WIDTH FOR SIMULATION */
+			var WIDTH = 64
+			var BIRDS = WIDTH * WIDTH;
+			
+			/* BAKE ANIMATION INTO TEXTURE and CREATE GEOMETRY FROM BASE MODEL */
+			var BirdGeometry = new THREE.BufferGeometry();
+			var textureAnimation, durationAnimation, originalMaterial,birdMesh, materialShader, vertexPerBird;
+			function nextPowerOf2( n ) { return Math.pow( 2, Math.ceil( Math.log( n ) / Math.log( 2 ) ) ) };
+
+			Math.lerp = function (value1, value2, amount) {
+
+				amount = Math.max( Math.min( amount, 1 ), 0 );
+				return value1 + (value2 - value1) * amount;
+				
+			};
+
+			var gltfs = [ 'models/gltf/Parrot.glb', 'models/gltf/Flamingo.glb' ]
+			var colors = [ 0xccFFFF, 0xffdeff ]
+			var sizes = [ 0.2, 0.1 ]
+			var selectModel = Math.floor( Math.random() * gltfs.length )
+			new GLTFLoader().load( gltfs[ selectModel ], function ( gltf ) {
+
+				var animations = gltf.animations;
+				durationAnimation = Math.round( animations[ 0 ].duration * 60 );
+				var birdGeo = gltf.scene.children[ 0 ].geometry;
+				originalMaterial = gltf.scene.children[ 0 ].material;
+				var morphAttributes = birdGeo.morphAttributes.position;
+				var tHeight = nextPowerOf2( durationAnimation );
+				var tWidth = nextPowerOf2( birdGeo.getAttribute( 'position' ).count );
+				vertexPerBird = birdGeo.getAttribute( 'position' ).count;
+				var tData = new Float32Array( 3 * tWidth * tHeight );
+
+				for( var i = 0 ; i < tWidth ; i++ ){
+
+					for( var j = 0 ; j < tHeight ; j++ ){
+
+						var offset = j * tWidth * 3;
+
+						var curFrame = j;
+						var curMorph = Math.floor( j / durationAnimation * morphAttributes.length );
+						var nextMorph = ( Math.floor( j / durationAnimation * morphAttributes.length ) + 1 ) % morphAttributes.length;
+						var lerpAmount = j / durationAnimation * morphAttributes.length % 1;
+
+						if( j < durationAnimation ){
+
+							tData[ offset + i * 3 ] = Math.lerp( morphAttributes[ curMorph ].array[ i * 3 ], morphAttributes[ nextMorph ].array[ i * 3 ], lerpAmount );
+							tData[ offset + i * 3 + 1 ] = Math.lerp( morphAttributes[ curMorph ].array[ i * 3 + 1 ], morphAttributes[ nextMorph ].array[ i * 3 + 1 ], lerpAmount );
+							tData[ offset + i * 3 + 2 ] = Math.lerp( morphAttributes[ curMorph ].array[ i * 3 + 2 ], morphAttributes[ nextMorph ].array[ i * 3 + 2 ], lerpAmount );
+						
+						}
+					}
+
+				}
+				
+				textureAnimation = new THREE.DataTexture( tData, tWidth, tHeight, THREE.RGBFormat, THREE.FloatType );
+				textureAnimation.needsUpdate = true;
+
+				var vertices = [], color = [], reference = [], seeds = [], indices = [];
+				var totalVertices = birdGeo.getAttribute( 'position' ).count * 3 * BIRDS;
+				for( var i = 0 ; i < totalVertices ; i++ ){
+
+					var bIndex = i % ( birdGeo.getAttribute( 'position' ).count * 3 );
+					vertices.push( birdGeo.getAttribute( 'position' ).array[ bIndex ] );
+					color.push( birdGeo.getAttribute( 'color' ).array[ bIndex ] );
+
+				}
+
+				var r = Math.random();
+				for( var i = 0 ; i < birdGeo.getAttribute( 'position' ).count * BIRDS ; i++ ){
+					
+					var bIndex = i % ( birdGeo.getAttribute( 'position' ).count );
+					var bird = Math.floor( i / birdGeo.getAttribute( 'position' ).count );
+					if( bIndex == 0 ) r = Math.random();
+					var j = ~ ~ bird;
+					var x = ( j % WIDTH ) / WIDTH;
+					var y = ~ ~ ( j / WIDTH ) / WIDTH;
+					reference.push( x, y, bIndex / tWidth, durationAnimation / tHeight );
+					seeds.push( bird, r, Math.random(), Math.random() );
+
+				}
+
+				for( var i = 0 ; i < birdGeo.index.array.length * BIRDS ; i++ ){
+
+					var offset = Math.floor( i / birdGeo.index.array.length ) * ( birdGeo.getAttribute( 'position' ).count );				
+					indices.push( birdGeo.index.array[ i % birdGeo.index.array.length ] + offset );
+
+				}
+
+				BirdGeometry.setAttribute( 'position', new THREE.BufferAttribute( new Float32Array( vertices ), 3 ) );
+				BirdGeometry.setAttribute( 'birdColor', new THREE.BufferAttribute( new Float32Array( color ), 3 ) );
+				BirdGeometry.setAttribute( 'color', new THREE.BufferAttribute( new Float32Array( color ), 3 ) );
+				BirdGeometry.setAttribute( 'reference', new THREE.BufferAttribute( new Float32Array( reference ), 4 ) );
+				BirdGeometry.setAttribute( 'seeds', new THREE.BufferAttribute( new Float32Array( seeds ), 4 ) );
+
+				BirdGeometry.setIndex( indices );
+
+				init();
+				animate();
+
+			} );
+
+			var container, stats;
+			var camera, scene, renderer;
+			var mouseX = 0, mouseY = 0;
+
+			var windowHalfX = window.innerWidth / 2;
+			var windowHalfY = window.innerHeight / 2;
+
+			var BOUNDS = 800, BOUNDS_HALF = BOUNDS / 2;
+
+			var last = performance.now();
+
+			var gpuCompute;
+			var velocityVariable;
+			var positionVariable;
+			var positionUniforms;
+			var velocityUniforms;
+			var birdUniforms;
+
+			function init() {
+
+				container = document.createElement( 'div' );
+				document.body.appendChild( container );
+
+				camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 3000 );
+				camera.position.z = 350;
+
+				scene = new THREE.Scene();
+				scene.background = new THREE.Color( colors[ selectModel ] );
+				scene.fog = new THREE.Fog( colors[ selectModel ], 100, 1000 );
+
+				// LIGHTS
+
+				var hemiLight = new THREE.HemisphereLight( colors[ selectModel ], 0xffffff, 1.6 );
+				hemiLight.color.setHSL( 0.6, 1, 0.6 );
+				hemiLight.groundColor.setHSL( 0.095, 1, 0.75 );
+				hemiLight.position.set( 0, 50, 0 );
+				scene.add( hemiLight );
+
+				var dirLight = new THREE.DirectionalLight( 0x00CED1, 0.6 );
+				dirLight.color.setHSL( 0.1, 1, 0.95 );
+				dirLight.position.set( - 1, 1.75, 1 );
+				dirLight.position.multiplyScalar( 30 );
+				scene.add( dirLight );
+
+				renderer = new THREE.WebGLRenderer( { antialias : true, alpha : true } );
+				renderer.setPixelRatio( window.devicePixelRatio );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				container.appendChild( renderer.domElement );
+
+				initComputeRenderer();
+
+				stats = new Stats();
+				container.appendChild( stats.dom );
+
+				document.addEventListener( 'mousemove', onDocumentMouseMove, false );
+				document.addEventListener( 'touchstart', onDocumentTouchStart, false );
+				document.addEventListener( 'touchmove', onDocumentTouchMove, false );
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+				var gui = new GUI();
+
+				var effectController = {
+
+					separation: 20.0,
+					alignment: 20.0,
+					cohesion: 20.0,
+					freedom: 0.75,
+					size: sizes[ selectModel ],
+					count: BIRDS
+
+				};
+
+				var valuesChanger = function () {
+
+					velocityUniforms[ "separationDistance" ].value = effectController.separation;
+					velocityUniforms[ "alignmentDistance" ].value = effectController.alignment;
+					velocityUniforms[ "cohesionDistance" ].value = effectController.cohesion;
+					velocityUniforms[ "freedomFactor" ].value = effectController.freedom;
+					if( materialShader ) materialShader.uniforms[ "size" ].value = effectController.size;
+					BirdGeometry.setDrawRange ( 0, vertexPerBird * effectController.count )
+
+				};
+
+				valuesChanger();
+
+				gui.add( effectController, "separation", 0.0, 100.0, 1.0 ).onChange( valuesChanger );
+				gui.add( effectController, "alignment", 0.0, 100, 0.001 ).onChange( valuesChanger );
+				gui.add( effectController, "cohesion", 0.0, 100, 0.025 ).onChange( valuesChanger );
+				gui.add( effectController, "size", 0, 1, 0.01 ).onChange( valuesChanger );
+				gui.add( effectController, "count", 0, BIRDS, 1 ).onChange( valuesChanger );
+				gui.close();
+
+				initBirds();
+
+			}
+
+			function initComputeRenderer() {
+
+				gpuCompute = new GPUComputationRenderer( WIDTH, WIDTH, renderer );
+
+				var dtPosition = gpuCompute.createTexture();
+				var dtVelocity = gpuCompute.createTexture();
+				fillPositionTexture( dtPosition );
+				fillVelocityTexture( dtVelocity );
+
+				velocityVariable = gpuCompute.addVariable( "textureVelocity", document.getElementById( 'fragmentShaderVelocity' ).textContent, dtVelocity );
+				positionVariable = gpuCompute.addVariable( "texturePosition", document.getElementById( 'fragmentShaderPosition' ).textContent, dtPosition );
+
+				gpuCompute.setVariableDependencies( velocityVariable, [ positionVariable, velocityVariable ] );
+				gpuCompute.setVariableDependencies( positionVariable, [ positionVariable, velocityVariable ] );
+
+				positionUniforms = positionVariable.material.uniforms;
+				velocityUniforms = velocityVariable.material.uniforms;
+
+				positionUniforms[ "time" ] = { value: 0.0 };
+				positionUniforms[ "delta" ] = { value: 0.0 };
+				velocityUniforms[ "time" ] = { value: 1.0 };
+				velocityUniforms[ "delta" ] = { value: 0.0 };
+				velocityUniforms[ "testing" ] = { value: 1.0 };
+				velocityUniforms[ "separationDistance" ] = { value: 1.0 };
+				velocityUniforms[ "alignmentDistance" ] = { value: 1.0 };
+				velocityUniforms[ "cohesionDistance" ] = { value: 1.0 };
+				velocityUniforms[ "freedomFactor" ] = { value: 1.0 };
+				velocityUniforms[ "predator" ] = { value: new THREE.Vector3() };
+				velocityVariable.material.defines.BOUNDS = BOUNDS.toFixed( 2 );
+
+				velocityVariable.wrapS = THREE.RepeatWrapping;
+				velocityVariable.wrapT = THREE.RepeatWrapping;
+				positionVariable.wrapS = THREE.RepeatWrapping;
+				positionVariable.wrapT = THREE.RepeatWrapping;
+				
+				var error = gpuCompute.init();
+				if ( error !== null ) {
+					console.error( error );
+				}
+			}
+
+			function initBirds() {
+
+				var geometry = BirdGeometry;
+
+				var m = new THREE.MeshStandardMaterial({
+					vertexColors : true,
+					flatShading : true,
+					roughness : 1,
+					metalness : 0
+				})
+
+				m.onBeforeCompile = ( shader ) => {
+
+					shader.uniforms.texturePosition = { value : null };
+					shader.uniforms.textureVelocity = { value : null };
+					shader.uniforms.textureAnimation = { value : textureAnimation };
+					shader.uniforms.time = { value : 1.0 };
+					shader.uniforms.size = { value : 0.1 };
+					shader.uniforms.delta = { value : 0.0 };
+
+					var token = '#define STANDARD';
+					
+					var insert = /* glsl */`
+						attribute vec4 reference;
+						attribute vec4 seeds;
+						attribute vec3 birdColor;
+						uniform sampler2D texturePosition;
+						uniform sampler2D textureVelocity;
+						uniform sampler2D textureAnimation;
+						uniform float size;
+						uniform float time;
+					`;
+
+					shader.vertexShader = shader.vertexShader.replace( token, token + insert );
+
+					var token = '#include <begin_vertex>';
+						
+					var insert = /* glsl */`
+						vec4 tmpPos = texture2D( texturePosition, reference.xy );
+					
+						vec3 pos = tmpPos.xyz;
+						vec3 velocity = normalize(texture2D( textureVelocity, reference.xy ).xyz);
+						vec3 aniPos = texture2D( textureAnimation, vec2( reference.z, mod( ( time + seeds.x ) * ( ( 0.0004 + seeds.y / 10000.0) + normalize( velocity ) / 20000.0 ), reference.w ) ) ).xyz;
+						vec3 newPosition = position;
+						
+						newPosition = mat3( modelMatrix ) * ( newPosition + aniPos );
+						newPosition *= size + seeds.y * size * 0.2;
+						
+						velocity.z *= -1.;
+						float xz = length( velocity.xz );
+						float xyz = 1.;
+						float x = sqrt( 1. - velocity.y * velocity.y );
+
+						float cosry = velocity.x / xz;
+						float sinry = velocity.z / xz;
+
+						float cosrz = x / xyz;
+						float sinrz = velocity.y / xyz;
+
+						mat3 maty =  mat3( cosry, 0, -sinry, 0    , 1, 0     , sinry, 0, cosry );
+						mat3 matz =  mat3( cosrz , sinrz, 0, -sinrz, cosrz, 0, 0     , 0    , 1 );
+
+						newPosition =  maty * matz * newPosition;
+						newPosition += pos;
+						
+						vec3 transformed = vec3( newPosition );
+					`;
+					
+					shader.vertexShader = shader.vertexShader.replace( token, insert );
+
+					materialShader = shader;
+
+				}    
+
+				birdMesh = new THREE.Mesh( geometry, m );
+				birdMesh.rotation.y = Math.PI / 2;
+				
+				birdMesh.castShadow = true;
+				birdMesh.receiveShadow = true;
+
+				scene.add( birdMesh );
+
+			}
+
+			function fillPositionTexture( texture ) {
+
+				var theArray = texture.image.data;
+
+				for ( var k = 0, kl = theArray.length; k < kl; k += 4 ) {
+
+					var x = Math.random() * BOUNDS - BOUNDS_HALF;
+					var y = Math.random() * BOUNDS - BOUNDS_HALF;
+					var z = Math.random() * BOUNDS - BOUNDS_HALF;
+
+					theArray[ k + 0 ] = x;
+					theArray[ k + 1 ] = y;
+					theArray[ k + 2 ] = z;
+					theArray[ k + 3 ] = 1;
+
+				}
+
+			}
+
+			function fillVelocityTexture( texture ) {
+
+				var theArray = texture.image.data;
+
+				for ( var k = 0, kl = theArray.length; k < kl; k += 4 ) {
+
+					var x = Math.random() - 0.5;
+					var y = Math.random() - 0.5;
+					var z = Math.random() - 0.5;
+
+					theArray[ k + 0 ] = x * 10;
+					theArray[ k + 1 ] = y * 10;
+					theArray[ k + 2 ] = z * 10;
+					theArray[ k + 3 ] = 1;
+
+				}
+
+			}
+
+
+			function onWindowResize() {
+
+				windowHalfX = window.innerWidth / 2;
+				windowHalfY = window.innerHeight / 2;
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			function onDocumentMouseMove( event ) {
+
+				mouseX = event.clientX - windowHalfX;
+				mouseY = event.clientY - windowHalfY;
+
+			}
+
+			function onDocumentTouchStart( event ) {
+
+				if ( event.touches.length === 1 ) {
+
+					event.preventDefault();
+
+					mouseX = event.touches[ 0 ].pageX - windowHalfX;
+					mouseY = event.touches[ 0 ].pageY - windowHalfY;
+
+				}
+
+			}
+
+			function onDocumentTouchMove( event ) {
+
+				if ( event.touches.length === 1 ) {
+
+					event.preventDefault();
+
+					mouseX = event.touches[ 0 ].pageX - windowHalfX;
+					mouseY = event.touches[ 0 ].pageY - windowHalfY;
+
+				}
+
+			}
+
+			//
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+
+				render();
+				stats.update();
+
+			}
+
+			function render() {
+
+				var now = performance.now();
+				var delta = ( now - last ) / 1000;
+				
+				if ( delta > 1 ) delta = 1; // safety cap on large deltas
+				last = now;
+
+				positionUniforms[ "time" ].value = now;
+				positionUniforms[ "delta" ].value = delta;
+				velocityUniforms[ "time" ].value = now;
+				velocityUniforms[ "delta" ].value = delta;
+				if( materialShader ) materialShader.uniforms[ "time" ].value = now;
+				if( materialShader ) materialShader.uniforms[ "delta" ].value = delta;
+
+				velocityUniforms[ "predator" ].value.set( 0.5 * mouseX / windowHalfX, - 0.5 * mouseY / windowHalfY, 0 );
+
+				mouseX = 10000;
+				mouseY = 10000;
+
+				gpuCompute.compute();
+				
+				if( materialShader ) materialShader.uniforms[ "texturePosition" ].value = gpuCompute.getCurrentRenderTarget( positionVariable ).texture;
+				if( materialShader ) materialShader.uniforms[ "textureVelocity" ].value = gpuCompute.getCurrentRenderTarget( velocityVariable ).texture;
+				
+				renderer.render( scene, camera );
+			}
+
+		</script>
+	</body>
+</html>

+ 20 - 0
src/Three.Legacy.js

@@ -26,6 +26,7 @@ import {
 	BufferAttribute
 } from './core/BufferAttribute.js';
 import { BufferGeometry } from './core/BufferGeometry.js';
+import { InstancedBufferGeometry } from './core/InstancedBufferGeometry.js';
 import { InterleavedBuffer } from './core/InterleavedBuffer.js';
 import { Face3 } from './core/Face3.js';
 import { Geometry } from './core/Geometry.js';
@@ -1371,6 +1372,25 @@ Object.defineProperties( BufferGeometry.prototype, {
 
 } );
 
+Object.defineProperties( InstancedBufferGeometry.prototype, {
+
+	maxInstancedCount: {
+		get: function () {
+
+			console.warn( 'THREE.InstancedBufferGeometry: .maxInstancedCount has been renamed to .instanceCount.' );
+			return this.instanceCount;
+
+		},
+		set: function ( value ) {
+
+			console.warn( 'THREE.InstancedBufferGeometry: .maxInstancedCount has been renamed to .instanceCount.' );
+			this.instanceCount = value;
+
+		}
+	}
+
+} );
+
 Object.defineProperties( Raycaster.prototype, {
 
 	linePrecision: {

+ 1 - 1
src/core/InstancedBufferGeometry.d.ts

@@ -8,7 +8,7 @@ export class InstancedBufferGeometry extends BufferGeometry {
 	constructor();
 
 	groups: { start: number; count: number; instances: number }[];
-	maxInstancedCount: number;
+	instanceCount: number;
 
 	addGroup( start: number, count: number, instances: number ): void;
 

+ 3 - 3
src/core/InstancedBufferGeometry.js

@@ -9,7 +9,7 @@ function InstancedBufferGeometry() {
 	BufferGeometry.call( this );
 
 	this.type = 'InstancedBufferGeometry';
-	this.maxInstancedCount = undefined;
+	this.instanceCount = Infinity;
 
 }
 
@@ -23,7 +23,7 @@ InstancedBufferGeometry.prototype = Object.assign( Object.create( BufferGeometry
 
 		BufferGeometry.prototype.copy.call( this, source );
 
-		this.maxInstancedCount = source.maxInstancedCount;
+		this.instanceCount = source.instanceCount;
 
 		return this;
 
@@ -39,7 +39,7 @@ InstancedBufferGeometry.prototype = Object.assign( Object.create( BufferGeometry
 
 		var data = BufferGeometry.prototype.toJSON.call( this );
 
-		data.maxInstancedCount = this.maxInstancedCount;
+		data.instanceCount = this.instanceCount;
 
 		data.isInstancedBufferGeometry = true;
 

+ 7 - 11
src/renderers/WebGLRenderer.js

@@ -875,7 +875,9 @@ function WebGLRenderer( parameters ) {
 
 		} else if ( geometry.isInstancedBufferGeometry ) {
 
-			renderer.renderInstances( geometry, drawStart, drawCount, geometry.maxInstancedCount );
+			var instanceCount = Math.min( geometry.instanceCount, geometry._maxInstanceCount );
+
+			renderer.renderInstances( geometry, drawStart, drawCount, instanceCount );
 
 		} else {
 
@@ -934,9 +936,9 @@ function WebGLRenderer( parameters ) {
 
 							state.enableAttributeAndDivisor( programAttribute, data.meshPerAttribute );
 
-							if ( geometry.maxInstancedCount === undefined ) {
+							if ( geometry._maxInstanceCount === undefined ) {
 
-								geometry.maxInstancedCount = data.meshPerAttribute * data.count;
+								geometry._maxInstanceCount = data.meshPerAttribute * data.count;
 
 							}
 
@@ -955,9 +957,9 @@ function WebGLRenderer( parameters ) {
 
 							state.enableAttributeAndDivisor( programAttribute, geometryAttribute.meshPerAttribute );
 
-							if ( geometry.maxInstancedCount === undefined ) {
+							if ( geometry._maxInstanceCount === undefined ) {
 
-								geometry.maxInstancedCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;
+								geometry._maxInstanceCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;
 
 							}
 
@@ -1875,12 +1877,6 @@ function WebGLRenderer( parameters ) {
 
 			WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );
 
-			if ( material.isShaderMaterial ) {
-
-				material.uniformsNeedUpdate = false; // #15581
-
-			}
-
 		}
 
 		if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) {

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

@@ -101,6 +101,10 @@ function WebGLMaterials( properties ) {
 			uniforms.color.value.copy( material.color );
 			uniforms.opacity.value = material.opacity;
 
+		} else if ( material.isShaderMaterial ) {
+
+			material.uniformsNeedUpdate = false; // #15581
+
 		}
 
 	}