InstancedBatchedSkinnedMesh
@Cody_J_Bennett
by Cody Bennett
HTML
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/[email protected]/build/three.module.js",
"three/addons/": "https://unpkg.com/[email protected]/examples/jsm/"
}
}
</script>
CSS
body {
margin: 0;
}
canvas {
cursor: grab;
display: block;
}
canvas:active {
cursor: grabbing;
}
JavaScript
import * as THREE from 'three'
import Stats from 'three/addons/libs/stats.module.js'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'
import { mergeVertices } from 'three/addons/utils/BufferGeometryUtils.js'
THREE.ShaderChunk.skinning_pars_vertex =
THREE.ShaderChunk.skinning_pars_vertex +
/* glsl */ `
#ifdef USE_BATCHED_SKINNING
attribute vec4 skinIndex;
attribute vec4 skinWeight;
uniform highp usampler2D batchingKeyframeTexture;
uniform highp sampler2D boneTexture;
float getBatchedKeyframe( const in float batchId ) {
int size = textureSize( batchingKeyframeTexture, 0 ).x;
int j = int ( batchId );
int x = j % size;
int y = j / size;
return float( texelFetch( batchingKeyframeTexture, ivec2( x, y ), 0 ).r );
}
mat4 getBatchedBoneMatrix( const in float i ) {
float batchId = getIndirectIndex( gl_DrawID );
float batchKeyframe = getBatchedKeyframe( batchId );
int size = textureSize( boneTexture, 0 ).x;
int j = int( batchKeyframe + i ) * 4;
int x = j % size;
int y = j / size;
vec4 v1 = texelFetch( boneTexture, ivec2( x, y ), 0 );
vec4 v2 = texelFetch( boneTexture, ivec2( x + 1, y ), 0 );
vec4 v3 = texelFetch( boneTexture, ivec2( x + 2, y ), 0 );
vec4 v4 = texelFetch( boneTexture, ivec2( x + 3, y ), 0 );
return mat4( v1, v2, v3, v4 );
}
#endif
`
THREE.ShaderChunk.skinning_vertex =
THREE.ShaderChunk.skinning_vertex +
/* glsl */ `
#ifdef USE_BATCHED_SKINNING
vec4 skinVertex = vec4( transformed, 1.0 );
mat4 boneMatX = getBatchedBoneMatrix( skinIndex.x );
mat4 boneMatY = getBatchedBoneMatrix( skinIndex.y );
...