How can I optimize the performance of rendering gltf data with stencil material (capping)?

I’m using the example of the following link, https://github.com/mrdoob/three.js/blob/129635bdb5cbfa11f1b31522889846e862da43d0/examples/webgl_clipping_stencil.html to implement capping the meshes.

My gltf file includes more than 20000 meshes, so when I apply x,y,z clipping planes for each mesh, the rendering is pretty slow and the FPS on the stats UI indicates 4 ~ 6 FPS.
Is there a way to increase the performance?

This is my loading gltf code.

let object, planeObjects;

function initLoaders(renderer, workerLimit = undefined) {
	let ktx2Loader = new KTX2Loader()
		.setTranscoderPath("libs/basis/")
		.detectSupport(renderer);

	if (workerLimit) ktx2Loader.setWorkerLimit(workerLimit);

	let dracoLoader = new DRACOLoader().setDecoderPath("libs/draco/");
	if (workerLimit) dracoLoader.setWorkerLimit(workerLimit);

	const gltfLoader = new GLTFLoader()
		.setCrossOrigin("anonymous")
		.setDRACOLoader(dracoLoader)
		.setKTX2Loader(ktx2Loader)
		.setMeshoptDecoder(MeshoptDecoder);

	return gltfLoader;
}

loader.load("./mydata.glb", (gltf) => {
		const fscene = gltf.scene || gltf.scenes[0];


		object = new THREE.Group();
		scene.add(object);

		// Set up clip plane rendering
		planeObjects = [];
		const planeGeoms = [
			new THREE.PlaneGeometry(bodySize[2], bodySize[1]),
			new THREE.PlaneGeometry(bodySize[0], bodySize[2]),
			new THREE.PlaneGeometry(bodySize[0], bodySize[1]),
		];
		fscene.traverse((child) => {
			if (child.isMesh) {
				for (let i = 0; i < 3; i++) {
					const poGroup = new THREE.Group();
					const plane = planes[i];
					const stencilGroup = createPlaneStencilGroup(
						child.geometry,
						plane,
						i + 1
					);
					// plane is clipped by the other clipping planes
					const planeMat = new THREE.MeshStandardMaterial({
						color: "#611E1E",
						metalness: 0.1,
						roughness: 0.75,
						clippingPlanes: planes.filter((p) => p !== plane),

						stencilWrite: true,
						stencilRef: 0,
						stencilFunc: THREE.NotEqualStencilFunc,
						stencilFail: THREE.ReplaceStencilOp,
						stencilZFail: THREE.ReplaceStencilOp,
						stencilZPass: THREE.ReplaceStencilOp,
					});
					const po = new THREE.Mesh(planeGeoms[i], planeMat);
					po.onAfterRender = function (renderer) {
						renderer.clearStencil();
					};

					po.renderOrder = i + 1.1;

					object.add(stencilGroup);
					poGroup.add(po);
					planeObjects.push(po);
					scene.add(poGroup);
				}


				child.material.clippingPlanes = planes;
				child.material.shadowSide = THREE.DoubleSide;
				child.material.clipShadows = true;
				child.material.needsUpdate = true;
				object.add(child);
			}
		});


function animate() {

	requestAnimationFrame(animate);

	for (let i = 0; i < planeObjects.length; i++) {
		const plane = planes[i % 3];
		const po = planeObjects[i];
		plane.coplanarPoint(po.position);
		po.lookAt(
			po.position.x - plane.normal.x,
			po.position.y - plane.normal.y,
			po.position.z - plane.normal.z
		);
	}

	renderer.render(scene, camera);
}