Skip to content

Commit

Permalink
WebGLRenderer: Support more than 8 morph targets.
Browse files Browse the repository at this point in the history
  • Loading branch information
Mugen87 committed Aug 27, 2021
1 parent 0179bad commit df7ed79
Show file tree
Hide file tree
Showing 7 changed files with 258 additions and 77 deletions.
8 changes: 7 additions & 1 deletion src/renderers/WebGLRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,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 );
Expand Down Expand Up @@ -1499,6 +1499,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;
Expand All @@ -1520,6 +1521,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;
Expand Down Expand Up @@ -1601,6 +1603,10 @@ function WebGLRenderer( parameters = {} ) {

needsProgramChange = true;

} else if ( capabilities.isWebGL2 === true && materialProperties.morphTargetsCount !== morphTargetsCount ) {

needsProgramChange = true;

}

} else {
Expand Down
21 changes: 17 additions & 4 deletions src/renderers/shaders/ShaderChunk/morphnormal_vertex.glsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,23 @@ export default /* glsl */`
// When morphTargetsRelative is false, this is set to 1 - sum(influences); this results in normal = sum((target - base) * influence)
// When morphTargetsRelative is true, this is set to 1; as a result, all morph targets are simply added to the base after weighting
objectNormal *= morphTargetBaseInfluence;
objectNormal += morphNormal0 * morphTargetInfluences[ 0 ];
objectNormal += morphNormal1 * morphTargetInfluences[ 1 ];
objectNormal += morphNormal2 * morphTargetInfluences[ 2 ];
objectNormal += morphNormal3 * morphTargetInfluences[ 3 ];
#ifdef MORPHTARGETS_TEXTURE
for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {
if ( morphTargetInfluences[ i ] > 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1.0, 2.0 ) * morphTargetInfluences[ i ];
}
#else
objectNormal += morphNormal0 * morphTargetInfluences[ 0 ];
objectNormal += morphNormal1 * morphTargetInfluences[ 1 ];
objectNormal += morphNormal2 * morphTargetInfluences[ 2 ];
objectNormal += morphNormal3 * morphTargetInfluences[ 3 ];
#endif
#endif
`;
33 changes: 30 additions & 3 deletions src/renderers/shaders/ShaderChunk/morphtarget_pars_vertex.glsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,40 @@ export default /* glsl */`
uniform float morphTargetBaseInfluence;
#ifndef USE_MORPHNORMALS
#ifdef MORPHTARGETS_TEXTURE
uniform float morphTargetInfluences[ 8 ];
uniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];
uniform sampler2DArray morphTargets;
uniform int morphTargetsWidth;
vec3 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in float offset, const in float stride ) {
float j = float( vertexIndex ) * stride + offset;
float x = mod( j, float( morphTargetsWidth ) );
float y = floor( j / float( morphTargetsWidth ) );
float dx = 1.0 / float( morphTargetsWidth );
float dy = 1.0 / float( morphTargetsWidth );
x = dx * ( x + 0.5 );
y = dy * ( y + 0.5 );
vec3 morphUV = vec3( x, y, morphTargetIndex );
return texture( morphTargets, morphUV ).xyz;
}
#else
uniform float morphTargetInfluences[ 4 ];
#ifndef USE_MORPHNORMALS
uniform float morphTargetInfluences[ 8 ];
#else
uniform float morphTargetInfluences[ 4 ];
#endif
#endif
Expand Down
39 changes: 30 additions & 9 deletions src/renderers/shaders/ShaderChunk/morphtarget_vertex.glsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,38 @@ export default /* glsl */`
// When morphTargetsRelative is false, this is set to 1 - sum(influences); this results in position = sum((target - base) * influence)
// When morphTargetsRelative is true, this is set to 1; as a result, all morph targets are simply added to the base after weighting
transformed *= morphTargetBaseInfluence;
transformed += morphTarget0 * morphTargetInfluences[ 0 ];
transformed += morphTarget1 * morphTargetInfluences[ 1 ];
transformed += morphTarget2 * morphTargetInfluences[ 2 ];
transformed += morphTarget3 * morphTargetInfluences[ 3 ];
#ifndef USE_MORPHNORMALS
#ifdef MORPHTARGETS_TEXTURE
transformed += morphTarget4 * morphTargetInfluences[ 4 ];
transformed += morphTarget5 * morphTargetInfluences[ 5 ];
transformed += morphTarget6 * morphTargetInfluences[ 6 ];
transformed += morphTarget7 * morphTargetInfluences[ 7 ];
for ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {
#ifndef USE_MORPHNORMALS
if ( morphTargetInfluences[ i ] > 0.0 ) transformed += getMorph( gl_VertexID, i, 0.0, 1.0 ) * morphTargetInfluences[ i ];
#else
if ( morphTargetInfluences[ i ] > 0.0 ) transformed += getMorph( gl_VertexID, i, 0.0, 2.0 ) * morphTargetInfluences[ i ];
#endif
}
#else
transformed += morphTarget0 * morphTargetInfluences[ 0 ];
transformed += morphTarget1 * morphTargetInfluences[ 1 ];
transformed += morphTarget2 * morphTargetInfluences[ 2 ];
transformed += morphTarget3 * morphTargetInfluences[ 3 ];
#ifndef USE_MORPHNORMALS
transformed += morphTarget4 * morphTargetInfluences[ 4 ];
transformed += morphTarget5 * morphTargetInfluences[ 5 ];
transformed += morphTarget6 * morphTargetInfluences[ 6 ];
transformed += morphTarget7 * morphTargetInfluences[ 7 ];
#endif
#endif
Expand Down
Loading

0 comments on commit df7ed79

Please sign in to comment.