diff --git a/examples/screenshots/webgl_instancing_morph.jpg b/examples/screenshots/webgl_instancing_morph.jpg
index 80c4a5a3ef1660..49e33fcb83fc1c 100644
Binary files a/examples/screenshots/webgl_instancing_morph.jpg and b/examples/screenshots/webgl_instancing_morph.jpg differ
diff --git a/examples/webgl_instancing_morph.html b/examples/webgl_instancing_morph.html
index dab774e81c3aac..a83d2cb9eb9fee 100644
--- a/examples/webgl_instancing_morph.html
+++ b/examples/webgl_instancing_morph.html
@@ -1,12 +1,24 @@
+
- three.js webgl - instancing - Morph Target Animations
+ three.js webgl - morph targets - instancing
+
+
+
+
-
diff --git a/src/renderers/shaders/ShaderChunk/morphtarget_pars_vertex.glsl.js b/src/renderers/shaders/ShaderChunk/morphtarget_pars_vertex.glsl.js
index 7cb8769e0cbbde..23121e311a0f89 100644
--- a/src/renderers/shaders/ShaderChunk/morphtarget_pars_vertex.glsl.js
+++ b/src/renderers/shaders/ShaderChunk/morphtarget_pars_vertex.glsl.js
@@ -20,12 +20,34 @@ export default /* glsl */`
vec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {
- int texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;
+ int texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + 3 * offset;
+
int y = texelIndex / morphTargetsTextureSize.x;
int x = texelIndex - y * morphTargetsTextureSize.x;
ivec3 morphUV = ivec3( x, y, morphTargetIndex );
- return texelFetch( morphTargetsTexture, morphUV, 0 );
+
+ vec4 ret = vec4(0.);
+
+ ret.x = texelFetch( morphTargetsTexture, morphUV, 0 ).r;
+
+ morphUV.x++;
+
+ ret.y = texelFetch( morphTargetsTexture, morphUV, 0 ).r;
+
+ morphUV.x++;
+
+ ret.z = texelFetch( morphTargetsTexture, morphUV, 0 ).r;
+
+ #if MORPHTARGETS_TEXTURE_STRIDE == 10
+
+ morphUV.x++;
+
+ ret.a = offset == 2 ? texelFetch( morphTargetsTexture, morphUV, 0 ).r : 0.;
+
+ #endif
+
+ return ret;
}
diff --git a/src/renderers/webgl/WebGLMorphtargets.js b/src/renderers/webgl/WebGLMorphtargets.js
index 8e39bcfa99578d..d766816601e704 100644
--- a/src/renderers/webgl/WebGLMorphtargets.js
+++ b/src/renderers/webgl/WebGLMorphtargets.js
@@ -1,4 +1,4 @@
-import { FloatType } from '../../constants.js';
+import { FloatType, RedFormat } from '../../constants.js';
import { DataArrayTexture } from '../../textures/DataArrayTexture.js';
import { Vector4 } from '../../math/Vector4.js';
import { Vector2 } from '../../math/Vector2.js';
@@ -58,41 +58,42 @@ function WebGLMorphtargets( gl, capabilities, textures ) {
let vertexDataCount = 0;
- if ( hasMorphPosition === true ) vertexDataCount = 1;
- if ( hasMorphNormals === true ) vertexDataCount = 2;
- if ( hasMorphColors === true ) vertexDataCount = 3;
+ if ( hasMorphPosition === true ) vertexDataCount = 3;
+ if ( hasMorphNormals === true ) vertexDataCount = 6;
+ if ( hasMorphColors === true ) vertexDataCount = 10;
let width = geometry.attributes.position.count * vertexDataCount;
let height = 1;
if ( width > capabilities.maxTextureSize ) {
- height = Math.ceil( width / capabilities.maxTextureSize );
- width = capabilities.maxTextureSize;
+ // Align width on stride to simplify the texel fetching in the shader
+ const strideWidth = Math.floor( capabilities.maxTextureSize / vertexDataCount ) * vertexDataCount;
+ height = Math.ceil( width / strideWidth );
+ width = strideWidth;
}
- const buffer = new Float32Array( width * height * 4 * morphTargetsCount );
+ const buffer = new Float32Array( width * height * morphTargetsCount );
const texture = new DataArrayTexture( buffer, width, height, morphTargetsCount );
texture.type = FloatType;
+ texture.format = RedFormat;
texture.needsUpdate = true;
// fill buffer
- const vertexDataStride = vertexDataCount * 4;
-
for ( let i = 0; i < morphTargetsCount; i ++ ) {
const morphTarget = morphTargets[ i ];
const morphNormal = morphNormals[ i ];
const morphColor = morphColors[ i ];
- const offset = width * height * 4 * i;
+ const offset = width * height * i;
for ( let j = 0; j < morphTarget.count; j ++ ) {
- const stride = j * vertexDataStride;
+ const stride = j * vertexDataCount;
if ( hasMorphPosition === true ) {
@@ -101,7 +102,6 @@ function WebGLMorphtargets( gl, capabilities, textures ) {
buffer[ offset + stride + 0 ] = morph.x;
buffer[ offset + stride + 1 ] = morph.y;
buffer[ offset + stride + 2 ] = morph.z;
- buffer[ offset + stride + 3 ] = 0;
}
@@ -109,10 +109,9 @@ function WebGLMorphtargets( gl, capabilities, textures ) {
morph.fromBufferAttribute( morphNormal, j );
- buffer[ offset + stride + 4 ] = morph.x;
- buffer[ offset + stride + 5 ] = morph.y;
- buffer[ offset + stride + 6 ] = morph.z;
- buffer[ offset + stride + 7 ] = 0;
+ buffer[ offset + stride + 3 ] = morph.x;
+ buffer[ offset + stride + 4 ] = morph.y;
+ buffer[ offset + stride + 5 ] = morph.z;
}
@@ -120,10 +119,10 @@ function WebGLMorphtargets( gl, capabilities, textures ) {
morph.fromBufferAttribute( morphColor, j );
- buffer[ offset + stride + 8 ] = morph.x;
- buffer[ offset + stride + 9 ] = morph.y;
- buffer[ offset + stride + 10 ] = morph.z;
- buffer[ offset + stride + 11 ] = ( morphColor.itemSize === 4 ) ? morph.w : 1;
+ buffer[ offset + stride + 6 ] = morph.x;
+ buffer[ offset + stride + 7 ] = morph.y;
+ buffer[ offset + stride + 8 ] = morph.z;
+ buffer[ offset + stride + 9 ] = ( morphColor.itemSize === 4 ) ? morph.w : 1;
}
diff --git a/src/renderers/webgl/WebGLPrograms.js b/src/renderers/webgl/WebGLPrograms.js
index c58f21532161b7..8fd235285746a0 100644
--- a/src/renderers/webgl/WebGLPrograms.js
+++ b/src/renderers/webgl/WebGLPrograms.js
@@ -80,9 +80,9 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities
let morphTextureStride = 0;
- if ( geometry.morphAttributes.position !== undefined ) morphTextureStride = 1;
- if ( geometry.morphAttributes.normal !== undefined ) morphTextureStride = 2;
- if ( geometry.morphAttributes.color !== undefined ) morphTextureStride = 3;
+ if ( geometry.morphAttributes.position !== undefined ) morphTextureStride = 3;
+ if ( geometry.morphAttributes.normal !== undefined ) morphTextureStride = 6;
+ if ( geometry.morphAttributes.color !== undefined ) morphTextureStride = 10;
//