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 + + +
+ three.js webgl - morph targets - instancing
+ model by Face Cap +
+ - 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; //