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 );
         ...