|
@@ -3281,6 +3281,29 @@ class Quaternion {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ random() {
|
|
|
+
|
|
|
+ // Derived from http://planning.cs.uiuc.edu/node198.html
|
|
|
+ // Note, this source uses w, x, y, z ordering,
|
|
|
+ // so we swap the order below.
|
|
|
+
|
|
|
+ const u1 = Math.random();
|
|
|
+ const sqrt1u1 = Math.sqrt( 1 - u1 );
|
|
|
+ const sqrtu1 = Math.sqrt( u1 );
|
|
|
+
|
|
|
+ const u2 = 2 * Math.PI * Math.random();
|
|
|
+
|
|
|
+ const u3 = 2 * Math.PI * Math.random();
|
|
|
+
|
|
|
+ return this.set(
|
|
|
+ sqrt1u1 * Math.cos( u2 ),
|
|
|
+ sqrtu1 * Math.sin( u3 ),
|
|
|
+ sqrtu1 * Math.cos( u3 ),
|
|
|
+ sqrt1u1 * Math.sin( u2 ),
|
|
|
+ );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
equals( quaternion ) {
|
|
|
|
|
|
return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );
|
|
@@ -4046,6 +4069,22 @@ class Vector3 {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ randomDirection() {
|
|
|
+
|
|
|
+ // Derived from https://mathworld.wolfram.com/SpherePointPicking.html
|
|
|
+
|
|
|
+ const u = ( Math.random() - 0.5 ) * 2;
|
|
|
+ const t = Math.random() * Math.PI * 2;
|
|
|
+ const f = Math.sqrt( 1 - u ** 2 );
|
|
|
+
|
|
|
+ this.x = f * Math.cos( t );
|
|
|
+ this.y = f * Math.sin( t );
|
|
|
+ this.z = u;
|
|
|
+
|
|
|
+ return this;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
|
|
|
Vector3.prototype.isVector3 = true;
|
|
@@ -12774,11 +12813,11 @@ var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_META
|
|
|
|
|
|
var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif";
|
|
|
|
|
|
-var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n#endif";
|
|
|
+var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] > 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1, 2 ) * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\t\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\t\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\t\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n\t#endif\n#endif";
|
|
|
|
|
|
-var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\tuniform float morphTargetBaseInfluence;\n\t#ifndef USE_MORPHNORMALS\n\t\tuniform float morphTargetInfluences[ 8 ];\n\t#else\n\t\tuniform float morphTargetInfluences[ 4 ];\n\t#endif\n#endif";
|
|
|
+var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\tuniform float morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t\tuniform sampler2DArray morphTargetsTexture;\n\t\tuniform vec2 morphTargetsTextureSize;\n\t\tvec3 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset, const in int stride ) {\n\t\t\tfloat texelIndex = float( vertexIndex * stride + offset );\n\t\t\tfloat y = floor( texelIndex / morphTargetsTextureSize.x );\n\t\t\tfloat x = texelIndex - y * morphTargetsTextureSize.x;\n\t\t\tvec3 morphUV = vec3( ( x + 0.5 ) / morphTargetsTextureSize.x, y / morphTargetsTextureSize.y, morphTargetIndex );\n\t\t\treturn texture( morphTargetsTexture, morphUV ).xyz;\n\t\t}\n\t#else\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\tuniform float morphTargetInfluences[ 8 ];\n\t\t#else\n\t\t\tuniform float morphTargetInfluences[ 4 ];\n\t\t#endif\n\t#endif\n#endif";
|
|
|
|
|
|
-var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\t\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\t\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\t\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\t\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t#endif\n#endif";
|
|
|
+var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\t#ifndef USE_MORPHNORMALS\n\t\t\t\tif ( morphTargetInfluences[ i ] > 0.0 ) transformed += getMorph( gl_VertexID, i, 0, 1 ) * morphTargetInfluences[ i ];\n\t\t\t#else\n\t\t\t\tif ( morphTargetInfluences[ i ] > 0.0 ) transformed += getMorph( gl_VertexID, i, 0, 2 ) * morphTargetInfluences[ i ];\n\t\t\t#endif\n\t\t}\n\t#else\n\t\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\t\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\t\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\t\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\t\t\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\t\t\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\t\t\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t\t#endif\n\t#endif\n#endif";
|
|
|
|
|
|
var normal_fragment_begin = "float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\t#ifdef USE_TANGENT\n\t\tvec3 tangent = normalize( vTangent );\n\t\tvec3 bitangent = normalize( vBitangent );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\ttangent = tangent * faceDirection;\n\t\t\tbitangent = bitangent * faceDirection;\n\t\t#endif\n\t\t#if defined( TANGENTSPACE_NORMALMAP ) || defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tmat3 vTBN = mat3( tangent, bitangent, normal );\n\t\t#endif\n\t#endif\n#endif\nvec3 geometryNormal = normal;";
|
|
|
|
|
@@ -16475,6 +16514,31 @@ function WebGLInfo( gl ) {
|
|
|
|
|
|
}
|
|
|
|
|
|
+class DataTexture2DArray extends Texture {
|
|
|
+
|
|
|
+ constructor( data = null, width = 1, height = 1, depth = 1 ) {
|
|
|
+
|
|
|
+ super( null );
|
|
|
+
|
|
|
+ this.image = { data, width, height, depth };
|
|
|
+
|
|
|
+ this.magFilter = NearestFilter;
|
|
|
+ this.minFilter = NearestFilter;
|
|
|
+
|
|
|
+ this.wrapR = ClampToEdgeWrapping;
|
|
|
+
|
|
|
+ this.generateMipmaps = false;
|
|
|
+ this.flipY = false;
|
|
|
+ this.unpackAlignment = 1;
|
|
|
+
|
|
|
+ this.needsUpdate = true;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+DataTexture2DArray.prototype.isDataTexture2DArray = true;
|
|
|
+
|
|
|
function numericalSort( a, b ) {
|
|
|
|
|
|
return a[ 0 ] - b[ 0 ];
|
|
@@ -16487,10 +16551,12 @@ function absNumericalSort( a, b ) {
|
|
|
|
|
|
}
|
|
|
|
|
|
-function WebGLMorphtargets( gl ) {
|
|
|
+function WebGLMorphtargets( gl, capabilities, textures ) {
|
|
|
|
|
|
const influencesList = {};
|
|
|
const morphInfluences = new Float32Array( 8 );
|
|
|
+ const morphTextures = new WeakMap();
|
|
|
+ const morph = new Vector3();
|
|
|
|
|
|
const workInfluences = [];
|
|
|
|
|
@@ -16504,115 +16570,220 @@ function WebGLMorphtargets( gl ) {
|
|
|
|
|
|
const objectInfluences = object.morphTargetInfluences;
|
|
|
|
|
|
- // When object doesn't have morph target influences defined, we treat it as a 0-length array
|
|
|
- // This is important to make sure we set up morphTargetBaseInfluence / morphTargetInfluences
|
|
|
+ if ( capabilities.isWebGL2 === true ) {
|
|
|
|
|
|
- const length = objectInfluences === undefined ? 0 : objectInfluences.length;
|
|
|
+ // instead of using attributes, the WebGL 2 code path encodes morph targets
|
|
|
+ // into an array of data textures. Each layer represents a single morph target.
|
|
|
|
|
|
- let influences = influencesList[ geometry.id ];
|
|
|
+ const numberOfMorphTargets = geometry.morphAttributes.position.length;
|
|
|
|
|
|
- if ( influences === undefined || influences.length !== length ) {
|
|
|
+ let entry = morphTextures.get( geometry );
|
|
|
|
|
|
- // initialise list
|
|
|
+ if ( entry === undefined || entry.count !== numberOfMorphTargets ) {
|
|
|
|
|
|
- influences = [];
|
|
|
+ if ( entry !== undefined ) entry.texture.dispose();
|
|
|
|
|
|
- for ( let i = 0; i < length; i ++ ) {
|
|
|
+ const hasMorphNormals = geometry.morphAttributes.normal !== undefined;
|
|
|
|
|
|
- influences[ i ] = [ i, 0 ];
|
|
|
+ const morphTargets = geometry.morphAttributes.position;
|
|
|
+ const morphNormals = geometry.morphAttributes.normal || [];
|
|
|
|
|
|
- }
|
|
|
+ const numberOfVertices = geometry.attributes.position.count;
|
|
|
+ const numberOfVertexData = ( hasMorphNormals === true ) ? 2 : 1; // (v,n) vs. (v)
|
|
|
|
|
|
- influencesList[ geometry.id ] = influences;
|
|
|
+ let width = numberOfVertices * numberOfVertexData;
|
|
|
+ let height = 1;
|
|
|
|
|
|
- }
|
|
|
+ if ( width > capabilities.maxTextureSize ) {
|
|
|
|
|
|
- // Collect influences
|
|
|
+ height = Math.ceil( width / capabilities.maxTextureSize );
|
|
|
+ width = capabilities.maxTextureSize;
|
|
|
|
|
|
- for ( let i = 0; i < length; i ++ ) {
|
|
|
+ }
|
|
|
|
|
|
- const influence = influences[ i ];
|
|
|
+ const buffer = new Float32Array( width * height * 4 * numberOfMorphTargets );
|
|
|
|
|
|
- influence[ 0 ] = i;
|
|
|
- influence[ 1 ] = objectInfluences[ i ];
|
|
|
+ const texture = new DataTexture2DArray( buffer, width, height, numberOfMorphTargets );
|
|
|
+ texture.format = RGBAFormat; // using RGBA since RGB might be emulated (and is thus slower)
|
|
|
+ texture.type = FloatType;
|
|
|
|
|
|
- }
|
|
|
+ // fill buffer
|
|
|
|
|
|
- influences.sort( absNumericalSort );
|
|
|
+ const vertexDataStride = numberOfVertexData * 4;
|
|
|
|
|
|
- for ( let i = 0; i < 8; i ++ ) {
|
|
|
+ for ( let i = 0; i < numberOfMorphTargets; i ++ ) {
|
|
|
|
|
|
- if ( i < length && influences[ i ][ 1 ] ) {
|
|
|
+ const morphTarget = morphTargets[ i ];
|
|
|
+ const morphNormal = morphNormals[ i ];
|
|
|
|
|
|
- workInfluences[ i ][ 0 ] = influences[ i ][ 0 ];
|
|
|
- workInfluences[ i ][ 1 ] = influences[ i ][ 1 ];
|
|
|
+ const offset = width * height * 4 * i;
|
|
|
|
|
|
- } else {
|
|
|
+ for ( let j = 0; j < morphTarget.count; j ++ ) {
|
|
|
+
|
|
|
+ morph.fromBufferAttribute( morphTarget, j );
|
|
|
+
|
|
|
+ const stride = j * vertexDataStride;
|
|
|
+
|
|
|
+ buffer[ offset + stride + 0 ] = morph.x;
|
|
|
+ buffer[ offset + stride + 1 ] = morph.y;
|
|
|
+ buffer[ offset + stride + 2 ] = morph.z;
|
|
|
+
|
|
|
+ if ( hasMorphNormals === true ) {
|
|
|
+
|
|
|
+ morph.fromBufferAttribute( morphNormal, j );
|
|
|
|
|
|
- workInfluences[ i ][ 0 ] = Number.MAX_SAFE_INTEGER;
|
|
|
- workInfluences[ i ][ 1 ] = 0;
|
|
|
+ buffer[ offset + stride + 3 ] = morph.x;
|
|
|
+ buffer[ offset + stride + 4 ] = morph.y;
|
|
|
+ buffer[ offset + stride + 5 ] = morph.z;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ entry = {
|
|
|
+ count: numberOfMorphTargets,
|
|
|
+ texture: texture,
|
|
|
+ size: new Vector2( width, height )
|
|
|
+ };
|
|
|
+
|
|
|
+ morphTextures.set( geometry, entry );
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ //
|
|
|
|
|
|
- workInfluences.sort( numericalSort );
|
|
|
+ let morphInfluencesSum = 0;
|
|
|
|
|
|
- const morphTargets = geometry.morphAttributes.position;
|
|
|
- const morphNormals = geometry.morphAttributes.normal;
|
|
|
+ for ( let i = 0; i < objectInfluences.length; i ++ ) {
|
|
|
|
|
|
- let morphInfluencesSum = 0;
|
|
|
+ morphInfluencesSum += objectInfluences[ i ];
|
|
|
|
|
|
- for ( let i = 0; i < 8; i ++ ) {
|
|
|
+ }
|
|
|
|
|
|
- const influence = workInfluences[ i ];
|
|
|
- const index = influence[ 0 ];
|
|
|
- const value = influence[ 1 ];
|
|
|
+ const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum;
|
|
|
|
|
|
- if ( index !== Number.MAX_SAFE_INTEGER && value ) {
|
|
|
+ program.getUniforms().setValue( gl, 'morphTargetBaseInfluence', morphBaseInfluence );
|
|
|
+ program.getUniforms().setValue( gl, 'morphTargetInfluences', objectInfluences );
|
|
|
|
|
|
- if ( morphTargets && geometry.getAttribute( 'morphTarget' + i ) !== morphTargets[ index ] ) {
|
|
|
+ program.getUniforms().setValue( gl, 'morphTargetsTexture', entry.texture, textures );
|
|
|
+ program.getUniforms().setValue( gl, 'morphTargetsTextureSize', entry.size );
|
|
|
|
|
|
- geometry.setAttribute( 'morphTarget' + i, morphTargets[ index ] );
|
|
|
|
|
|
- }
|
|
|
+ } else {
|
|
|
|
|
|
- if ( morphNormals && geometry.getAttribute( 'morphNormal' + i ) !== morphNormals[ index ] ) {
|
|
|
+ // When object doesn't have morph target influences defined, we treat it as a 0-length array
|
|
|
+ // This is important to make sure we set up morphTargetBaseInfluence / morphTargetInfluences
|
|
|
|
|
|
- geometry.setAttribute( 'morphNormal' + i, morphNormals[ index ] );
|
|
|
+ const length = objectInfluences === undefined ? 0 : objectInfluences.length;
|
|
|
|
|
|
- }
|
|
|
+ let influences = influencesList[ geometry.id ];
|
|
|
|
|
|
- morphInfluences[ i ] = value;
|
|
|
- morphInfluencesSum += value;
|
|
|
+ if ( influences === undefined || influences.length !== length ) {
|
|
|
|
|
|
- } else {
|
|
|
+ // initialise list
|
|
|
|
|
|
- if ( morphTargets && geometry.hasAttribute( 'morphTarget' + i ) === true ) {
|
|
|
+ influences = [];
|
|
|
|
|
|
- geometry.deleteAttribute( 'morphTarget' + i );
|
|
|
+ for ( let i = 0; i < length; i ++ ) {
|
|
|
+
|
|
|
+ influences[ i ] = [ i, 0 ];
|
|
|
|
|
|
}
|
|
|
|
|
|
- if ( morphNormals && geometry.hasAttribute( 'morphNormal' + i ) === true ) {
|
|
|
+ influencesList[ geometry.id ] = influences;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // Collect influences
|
|
|
+
|
|
|
+ for ( let i = 0; i < length; i ++ ) {
|
|
|
+
|
|
|
+ const influence = influences[ i ];
|
|
|
+
|
|
|
+ influence[ 0 ] = i;
|
|
|
+ influence[ 1 ] = objectInfluences[ i ];
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ influences.sort( absNumericalSort );
|
|
|
+
|
|
|
+ for ( let i = 0; i < 8; i ++ ) {
|
|
|
|
|
|
- geometry.deleteAttribute( 'morphNormal' + i );
|
|
|
+ if ( i < length && influences[ i ][ 1 ] ) {
|
|
|
+
|
|
|
+ workInfluences[ i ][ 0 ] = influences[ i ][ 0 ];
|
|
|
+ workInfluences[ i ][ 1 ] = influences[ i ][ 1 ];
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ workInfluences[ i ][ 0 ] = Number.MAX_SAFE_INTEGER;
|
|
|
+ workInfluences[ i ][ 1 ] = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
- morphInfluences[ i ] = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ workInfluences.sort( numericalSort );
|
|
|
+
|
|
|
+ const morphTargets = geometry.morphAttributes.position;
|
|
|
+ const morphNormals = geometry.morphAttributes.normal;
|
|
|
+
|
|
|
+ let morphInfluencesSum = 0;
|
|
|
+
|
|
|
+ for ( let i = 0; i < 8; i ++ ) {
|
|
|
+
|
|
|
+ const influence = workInfluences[ i ];
|
|
|
+ const index = influence[ 0 ];
|
|
|
+ const value = influence[ 1 ];
|
|
|
+
|
|
|
+ if ( index !== Number.MAX_SAFE_INTEGER && value ) {
|
|
|
+
|
|
|
+ if ( morphTargets && geometry.getAttribute( 'morphTarget' + i ) !== morphTargets[ index ] ) {
|
|
|
+
|
|
|
+ geometry.setAttribute( 'morphTarget' + i, morphTargets[ index ] );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( morphNormals && geometry.getAttribute( 'morphNormal' + i ) !== morphNormals[ index ] ) {
|
|
|
+
|
|
|
+ geometry.setAttribute( 'morphNormal' + i, morphNormals[ index ] );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ morphInfluences[ i ] = value;
|
|
|
+ morphInfluencesSum += value;
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ if ( morphTargets && geometry.hasAttribute( 'morphTarget' + i ) === true ) {
|
|
|
+
|
|
|
+ geometry.deleteAttribute( 'morphTarget' + i );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( morphNormals && geometry.hasAttribute( 'morphNormal' + i ) === true ) {
|
|
|
+
|
|
|
+ geometry.deleteAttribute( 'morphNormal' + i );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ morphInfluences[ i ] = 0;
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ // GLSL shader uses formula baseinfluence * base + sum(target * influence)
|
|
|
+ // This allows us to switch between absolute morphs and relative morphs without changing shader code
|
|
|
+ // When baseinfluence = 1 - sum(influence), the above is equivalent to sum((target - base) * influence)
|
|
|
+ const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum;
|
|
|
|
|
|
- // GLSL shader uses formula baseinfluence * base + sum(target * influence)
|
|
|
- // This allows us to switch between absolute morphs and relative morphs without changing shader code
|
|
|
- // When baseinfluence = 1 - sum(influence), the above is equivalent to sum((target - base) * influence)
|
|
|
- const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum;
|
|
|
+ program.getUniforms().setValue( gl, 'morphTargetBaseInfluence', morphBaseInfluence );
|
|
|
+ program.getUniforms().setValue( gl, 'morphTargetInfluences', morphInfluences );
|
|
|
|
|
|
- program.getUniforms().setValue( gl, 'morphTargetBaseInfluence', morphBaseInfluence );
|
|
|
- program.getUniforms().setValue( gl, 'morphTargetInfluences', morphInfluences );
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
@@ -16694,31 +16865,6 @@ function WebGLObjects( gl, geometries, attributes, info ) {
|
|
|
|
|
|
}
|
|
|
|
|
|
-class DataTexture2DArray extends Texture {
|
|
|
-
|
|
|
- constructor( data = null, width = 1, height = 1, depth = 1 ) {
|
|
|
-
|
|
|
- super( null );
|
|
|
-
|
|
|
- this.image = { data, width, height, depth };
|
|
|
-
|
|
|
- this.magFilter = NearestFilter;
|
|
|
- this.minFilter = NearestFilter;
|
|
|
-
|
|
|
- this.wrapR = ClampToEdgeWrapping;
|
|
|
-
|
|
|
- this.generateMipmaps = false;
|
|
|
- this.flipY = false;
|
|
|
- this.unpackAlignment = 1;
|
|
|
-
|
|
|
- this.needsUpdate = true;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-DataTexture2DArray.prototype.isDataTexture2DArray = true;
|
|
|
-
|
|
|
class DataTexture3D extends Texture {
|
|
|
|
|
|
constructor( data = null, width = 1, height = 1, depth = 1 ) {
|
|
@@ -18230,6 +18376,8 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
|
|
|
|
|
|
parameters.morphTargets ? '#define USE_MORPHTARGETS' : '',
|
|
|
parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '',
|
|
|
+ ( parameters.morphTargets && parameters.isWebGL2 ) ? '#define MORPHTARGETS_TEXTURE' : '',
|
|
|
+ ( parameters.morphTargets && parameters.isWebGL2 ) ? '#define MORPHTARGETS_COUNT ' + parameters.morphTargetsCount : '',
|
|
|
parameters.doubleSided ? '#define DOUBLE_SIDED' : '',
|
|
|
parameters.flipSided ? '#define FLIP_SIDED' : '',
|
|
|
|
|
@@ -18281,7 +18429,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
|
|
|
|
|
|
'#endif',
|
|
|
|
|
|
- '#ifdef USE_MORPHTARGETS',
|
|
|
+ '#if ( defined( USE_MORPHTARGETS ) && ! defined( MORPHTARGETS_TEXTURE ) )',
|
|
|
|
|
|
' attribute vec3 morphTarget0;',
|
|
|
' attribute vec3 morphTarget1;',
|
|
@@ -18437,6 +18585,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
|
|
|
versionString = '#version 300 es\n';
|
|
|
|
|
|
prefixVertex = [
|
|
|
+ 'precision mediump sampler2DArray;',
|
|
|
'#define attribute in',
|
|
|
'#define varying out',
|
|
|
'#define texture2D texture'
|
|
@@ -18656,7 +18805,7 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities
|
|
|
'specularMap', 'specularIntensityMap', 'specularTintMap', 'specularTintMapEncoding', 'roughnessMap', 'metalnessMap', 'gradientMap',
|
|
|
'alphaMap', 'alphaTest', 'combine', 'vertexColors', 'vertexAlphas', 'vertexTangents', 'vertexUvs', 'uvsVertexOnly', 'fog', 'useFog', 'fogExp2',
|
|
|
'flatShading', 'sizeAttenuation', 'logarithmicDepthBuffer', 'skinning',
|
|
|
- 'maxBones', 'useVertexTexture', 'morphTargets', 'morphNormals', 'premultipliedAlpha',
|
|
|
+ 'maxBones', 'useVertexTexture', 'morphTargets', 'morphNormals', 'morphTargetsCount', 'premultipliedAlpha',
|
|
|
'numDirLights', 'numPointLights', 'numSpotLights', 'numHemiLights', 'numRectAreaLights',
|
|
|
'numDirLightShadows', 'numPointLightShadows', 'numSpotLightShadows',
|
|
|
'shadowMapEnabled', 'shadowMapType', 'toneMapping', 'physicallyCorrectLights',
|
|
@@ -18856,6 +19005,7 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities
|
|
|
|
|
|
morphTargets: !! object.geometry && !! object.geometry.morphAttributes.position,
|
|
|
morphNormals: !! object.geometry && !! object.geometry.morphAttributes.normal,
|
|
|
+ morphTargetsCount: ( !! object.geometry && !! object.geometry.morphAttributes.position ) ? object.geometry.morphAttributes.position.length : 0,
|
|
|
|
|
|
numDirLights: lights.directional.length,
|
|
|
numPointLights: lights.point.length,
|
|
@@ -25174,7 +25324,7 @@ function WebGLRenderer( parameters = {} ) {
|
|
|
bindingStates = new WebGLBindingStates( _gl, extensions, attributes, capabilities );
|
|
|
geometries = new WebGLGeometries( _gl, attributes, info, bindingStates );
|
|
|
objects = new WebGLObjects( _gl, geometries, attributes, info );
|
|
|
- morphtargets = new WebGLMorphtargets( _gl );
|
|
|
+ morphtargets = new WebGLMorphtargets( _gl, capabilities, textures );
|
|
|
clipping = new WebGLClipping( properties );
|
|
|
programCache = new WebGLPrograms( _this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping );
|
|
|
materials = new WebGLMaterials( properties );
|
|
@@ -26372,6 +26522,7 @@ function WebGLRenderer( parameters = {} ) {
|
|
|
materialProperties.skinning = parameters.skinning;
|
|
|
materialProperties.morphTargets = parameters.morphTargets;
|
|
|
materialProperties.morphNormals = parameters.morphNormals;
|
|
|
+ materialProperties.morphTargetsCount = parameters.morphTargetsCount;
|
|
|
materialProperties.numClippingPlanes = parameters.numClippingPlanes;
|
|
|
materialProperties.numIntersection = parameters.numClipIntersection;
|
|
|
materialProperties.vertexAlphas = parameters.vertexAlphas;
|
|
@@ -26393,6 +26544,7 @@ function WebGLRenderer( parameters = {} ) {
|
|
|
const vertexTangents = !! object.geometry && !! object.geometry.attributes.tangent;
|
|
|
const morphTargets = !! object.geometry && !! object.geometry.morphAttributes.position;
|
|
|
const morphNormals = !! object.geometry && !! object.geometry.morphAttributes.normal;
|
|
|
+ const morphTargetsCount = ( !! object.geometry && !! object.geometry.morphAttributes.position ) ? object.geometry.morphAttributes.position.length : 0;
|
|
|
|
|
|
const materialProperties = properties.get( material );
|
|
|
const lights = currentRenderState.state.lights;
|
|
@@ -26474,6 +26626,10 @@ function WebGLRenderer( parameters = {} ) {
|
|
|
|
|
|
needsProgramChange = true;
|
|
|
|
|
|
+ } else if ( capabilities.isWebGL2 === true && materialProperties.morphTargetsCount !== morphTargetsCount ) {
|
|
|
+
|
|
|
+ needsProgramChange = true;
|
|
|
+
|
|
|
}
|
|
|
|
|
|
} else {
|
|
@@ -33476,7 +33632,7 @@ class IcosahedronGeometry extends PolyhedronGeometry {
|
|
|
|
|
|
class LatheGeometry extends BufferGeometry {
|
|
|
|
|
|
- constructor( points, segments = 12, phiStart = 0, phiLength = Math.PI * 2 ) {
|
|
|
+ constructor( points = [ new Vector2( 0, 0.5 ), new Vector2( 0.5, 0 ), new Vector2( 0, - 0.5 ) ], segments = 12, phiStart = 0, phiLength = Math.PI * 2 ) {
|
|
|
|
|
|
super();
|
|
|
|
|
@@ -46351,7 +46507,7 @@ class Raycaster {
|
|
|
|
|
|
}
|
|
|
|
|
|
- intersectObject( object, recursive = false, intersects = [] ) {
|
|
|
+ intersectObject( object, recursive = true, intersects = [] ) {
|
|
|
|
|
|
intersectObject( object, this, intersects, recursive );
|
|
|
|
|
@@ -46361,7 +46517,7 @@ class Raycaster {
|
|
|
|
|
|
}
|
|
|
|
|
|
- intersectObjects( objects, recursive = false, intersects = [] ) {
|
|
|
+ intersectObjects( objects, recursive = true, intersects = [] ) {
|
|
|
|
|
|
for ( let i = 0, l = objects.length; i < l; i ++ ) {
|
|
|
|