Răsfoiți Sursa

|threejs] Add logarithmic depth buffer example.

Mario Zechner 2 ani în urmă
părinte
comite
8e84ad990d

+ 155 - 76
spine-ts/index.html

@@ -1,79 +1,158 @@
 <!DOCTYPE html>
 <html>
+  <head>
+    <meta charset="utf-8" />
+    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
+    <title>spine-ts Examples</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1" />
+  </head>
 
-<head>
-	<meta charset='utf-8'>
-	<meta http-equiv='X-UA-Compatible' content='IE=edge'>
-	<title>spine-ts Examples</title>
-	<meta name='viewport' content='width=device-width, initial-scale=1'>
-</head>
-
-<body>
-	<h1>spine-ts Examples</h1>
-	<ul>
-		<li>Canvas</li>
-		<ul>
-			<li><a href="/spine-canvas/example">Example</a></li>
-			<li><a href="/spine-canvas/example/mouse-click.html">Mouse click</a></li>
-		</ul>
-		<li>Pixi</li>
-		<ul>
-			<li><a href="/spine-pixi/example/index.html">Basic example</a></li>
-			<li><a href="/spine-pixi/example/events-example.html">Events example</a></li>
-		</ul>
-		<li>Phaser</li>
-		<ul>
-			<li><a href="/spine-phaser/example/basic-example.html">Basic example</a></li>
-			<li><a href="/spine-phaser/example/events-example.html">Events example</a></li>
-			<li><a href="/spine-phaser/example/mix-and-match-example.html">Mix and match example</a></li>
-			<li><a href="/spine-phaser/example/arcade-physics-example.html">Arcade physics example</a></li>
-			<li><a href="/spine-phaser/example/control-bones-example.html">Control bones example</a></li>
-			<li><a href="/spine-phaser/example/batching-test.html">Batching test</a></li>
-			<li><a href="/spine-phaser/example/multi-scene-test.html">Multi-scene test</a></li>
-			<li><a href="/spine-phaser/example/bounds-test.html">Bounds test</a></li>
-			<li><a href="/spine-phaser/example/visibility-test.html">Visibility test</a></li>
-			<li><a href="/spine-phaser/example/blend-test.html">Blend test</a></li>
-			<li><a href="/spine-phaser/example/camera-pipeline-test.html">Camera pipeline test</a></li>
-			<li><a href="/spine-phaser/example/extended-class-test.html">Extended class</a></li>
-			<li><a href="/spine-phaser/example/canvas-test.html">Canvas test</a></li>
-			<li><a href="/spine-phaser/example/depth-test.html">Depth test</a></li>
-			<li><a href="/spine-phaser/example/render-to-texture-test.html">Render to texture test</a></li>
-		</ul>
-		<li>Player</li>
-		<ul>
-			<li><a href="/spine-player/example/example.html">Example</a></li>
-			<li><a href="/spine-player/example/embedding-binary-example.html">Embedding binary</a></li>
-			<li><a href="/spine-player/example/embedding-json-example.html">Embedding JSON</a></li>
-			<li><a href="/spine-player/example/dispose.html">Disposing a player</a></li>
-		</ul>
-		<li>WebGL</li>
-		<ul>
-			<li><a href="/spine-webgl/example">Example</a></li>
-			<li><a href="/spine-webgl/example/barebones.html">Barebones</a></li>
-			<li><a href="/spine-webgl/example/mix-and-match.html">Mix &amp; match</a></li>
-			<li><a href="/spine-webgl/example/custom-attachment.html">Custom attachment</a></li>
-			<li><a href="/spine-webgl/example/drag-and-drop.html">Drag &amp; drop</a></li>
-			<li><a href="/spine-webgl/example/dress-up.html">Dress-up</a></li>
-			<li><a href="/spine-webgl/example/bone-dragging.html">Bone dragging</a></li>
-			<li><a href="/spine-webgl/demos/additiveblending.html">Additive blending</a></li>
-			<li><a href="/spine-webgl/demos/clipping.html">Clipping</a></li>
-			<li><a href="/spine-webgl/demos/hoverboard.html">Hoverboard</a></li>
-			<li><a href="/spine-webgl/demos/imagechanges.html">Image changes</a></li>
-			<li><a href="/spine-webgl/demos/meshes.html">Meshes</a></li>
-			<li><a href="/spine-webgl/demos/skins.html">Skins</a></li>
-			<li><a href="/spine-webgl/demos/spritesheets.html">Spritesheets</a></li>
-			<li><a href="/spine-webgl/demos/stretchyman.html">Stretchyman</a></li>
-			<li><a href="/spine-webgl/demos/tank.html">Tank</a></li>
-			<li><a href="/spine-webgl/demos/transforms.html">Transforms</a></li>
-			<li><a href="/spine-webgl/demos/transitions.html">Transitions</a></li>
-			<li><a href="/spine-webgl/demos/vine.html">Vine</a></li>
-		</ul>
-		<li>THREE.JS</li>
-		<ul>
-			<li><a href="/spine-threejs/example/index.html">Example</a></li>
-			<li><a href="/spine-threejs/example/coordinate-transform.html">Coordinate transform</a></li>
-		</ul>
-	</ul>
-</body>
-
-</html>
+  <body>
+    <h1>spine-ts Examples</h1>
+    <ul>
+      <li>Canvas</li>
+      <ul>
+        <li><a href="/spine-canvas/example">Example</a></li>
+        <li>
+          <a href="/spine-canvas/example/mouse-click.html">Mouse click</a>
+        </li>
+      </ul>
+      <li>Pixi</li>
+      <ul>
+        <li><a href="/spine-pixi/example/index.html">Basic example</a></li>
+        <li>
+          <a href="/spine-pixi/example/events-example.html">Events example</a>
+        </li>
+      </ul>
+      <li>Phaser</li>
+      <ul>
+        <li>
+          <a href="/spine-phaser/example/basic-example.html">Basic example</a>
+        </li>
+        <li>
+          <a href="/spine-phaser/example/events-example.html">Events example</a>
+        </li>
+        <li>
+          <a href="/spine-phaser/example/mix-and-match-example.html"
+            >Mix and match example</a
+          >
+        </li>
+        <li>
+          <a href="/spine-phaser/example/arcade-physics-example.html"
+            >Arcade physics example</a
+          >
+        </li>
+        <li>
+          <a href="/spine-phaser/example/control-bones-example.html"
+            >Control bones example</a
+          >
+        </li>
+        <li>
+          <a href="/spine-phaser/example/batching-test.html">Batching test</a>
+        </li>
+        <li>
+          <a href="/spine-phaser/example/multi-scene-test.html"
+            >Multi-scene test</a
+          >
+        </li>
+        <li>
+          <a href="/spine-phaser/example/bounds-test.html">Bounds test</a>
+        </li>
+        <li>
+          <a href="/spine-phaser/example/visibility-test.html"
+            >Visibility test</a
+          >
+        </li>
+        <li><a href="/spine-phaser/example/blend-test.html">Blend test</a></li>
+        <li>
+          <a href="/spine-phaser/example/camera-pipeline-test.html"
+            >Camera pipeline test</a
+          >
+        </li>
+        <li>
+          <a href="/spine-phaser/example/extended-class-test.html"
+            >Extended class</a
+          >
+        </li>
+        <li>
+          <a href="/spine-phaser/example/canvas-test.html">Canvas test</a>
+        </li>
+        <li><a href="/spine-phaser/example/depth-test.html">Depth test</a></li>
+        <li>
+          <a href="/spine-phaser/example/render-to-texture-test.html"
+            >Render to texture test</a
+          >
+        </li>
+      </ul>
+      <li>Player</li>
+      <ul>
+        <li><a href="/spine-player/example/example.html">Example</a></li>
+        <li>
+          <a href="/spine-player/example/embedding-binary-example.html"
+            >Embedding binary</a
+          >
+        </li>
+        <li>
+          <a href="/spine-player/example/embedding-json-example.html"
+            >Embedding JSON</a
+          >
+        </li>
+        <li>
+          <a href="/spine-player/example/dispose.html">Disposing a player</a>
+        </li>
+      </ul>
+      <li>WebGL</li>
+      <ul>
+        <li><a href="/spine-webgl/example">Example</a></li>
+        <li><a href="/spine-webgl/example/barebones.html">Barebones</a></li>
+        <li>
+          <a href="/spine-webgl/example/mix-and-match.html">Mix &amp; match</a>
+        </li>
+        <li>
+          <a href="/spine-webgl/example/custom-attachment.html"
+            >Custom attachment</a
+          >
+        </li>
+        <li>
+          <a href="/spine-webgl/example/drag-and-drop.html">Drag &amp; drop</a>
+        </li>
+        <li><a href="/spine-webgl/example/dress-up.html">Dress-up</a></li>
+        <li>
+          <a href="/spine-webgl/example/bone-dragging.html">Bone dragging</a>
+        </li>
+        <li>
+          <a href="/spine-webgl/demos/additiveblending.html"
+            >Additive blending</a
+          >
+        </li>
+        <li><a href="/spine-webgl/demos/clipping.html">Clipping</a></li>
+        <li><a href="/spine-webgl/demos/hoverboard.html">Hoverboard</a></li>
+        <li>
+          <a href="/spine-webgl/demos/imagechanges.html">Image changes</a>
+        </li>
+        <li><a href="/spine-webgl/demos/meshes.html">Meshes</a></li>
+        <li><a href="/spine-webgl/demos/skins.html">Skins</a></li>
+        <li><a href="/spine-webgl/demos/spritesheets.html">Spritesheets</a></li>
+        <li><a href="/spine-webgl/demos/stretchyman.html">Stretchyman</a></li>
+        <li><a href="/spine-webgl/demos/tank.html">Tank</a></li>
+        <li><a href="/spine-webgl/demos/transforms.html">Transforms</a></li>
+        <li><a href="/spine-webgl/demos/transitions.html">Transitions</a></li>
+        <li><a href="/spine-webgl/demos/vine.html">Vine</a></li>
+      </ul>
+      <li>THREE.JS</li>
+      <ul>
+        <li><a href="/spine-threejs/example/index.html">Example</a></li>
+        <li>
+          <a href="/spine-threejs/example/coordinate-transform.html"
+            >Coordinate transform</a
+          >
+        </li>
+        <li>
+          <a href="/spine-threejs/example/logarithmic-depth-buffer.html"
+            >Logarithmic depth buffer</a
+          >
+        </li>
+      </ul>
+    </ul>
+  </body>
+</html>

+ 149 - 140
spine-ts/spine-threejs/example/index.html

@@ -1,141 +1,150 @@
 <html>
-
-<head>
-	<meta charset="UTF-8">
-	<title>spine-threejs</title>
-	<script src="https://unpkg.com/[email protected]/build/three.js"></script>
-	<script src="../dist/iife/spine-threejs.js"></script>
-	<script src="./OrbitalControls.js"></script>
-</head>
-<style>
-	* {
-		margin: 0;
-		padding: 0;
-	}
-
-	body,
-	html {
-		height: 100%
-	}
-
-	canvas {
-		position: absolute;
-		width: 100%;
-		height: 100%;
-	}
-</style>
-
-<body>
-	<script>
-		(function () {
-			let scene, camera, renderer;
-			let geometry, material, mesh, skeletonMesh;
-			let assetManager;
-			let canvas;
-			let controls;
-			let lastFrameTime = Date.now() / 1000;
-
-			let baseUrl = "assets/";
-			let skeletonFile = "raptor-pro.json";
-			let atlasFile = skeletonFile.replace("-pro", "").replace("-ess", "").replace(".json", ".atlas");
-			let animation = "walk";
-
-			function init() {
-				// create the THREE.JS camera, scene and renderer (WebGL)
-				let width = window.innerWidth, height = window.innerHeight;
-				camera = new THREE.PerspectiveCamera(75, width / height, 1, 3000);
-				camera.position.y = 100;
-				camera.position.z = 400;
-				scene = new THREE.Scene();
-				renderer = new THREE.WebGLRenderer();
-				renderer.setSize(width, height);
-				document.body.appendChild(renderer.domElement);
-				canvas = renderer.domElement;
-				controls = new OrbitControls(camera, renderer.domElement);
-
-				// load the assets required to display the Raptor model
-				assetManager = new spine.AssetManager(baseUrl);
-				assetManager.loadText(skeletonFile);
-				assetManager.loadTextureAtlas(atlasFile);
-
-				requestAnimationFrame(load);
-			}
-
-			function load(name, scale) {
-				if (assetManager.isLoadingComplete()) {
-					// Add a box to the scene to which we attach the skeleton mesh
-					geometry = new THREE.BoxGeometry(200, 200, 200);
-					material = new THREE.MeshBasicMaterial({ color: 0xff0000, wireframe: true });
-					mesh = new THREE.Mesh(geometry, material);
-					scene.add(mesh);
-
-					// Load the texture atlas using name.atlas and name.png from the AssetManager.
-					// The function passed to TextureAtlas is used to resolve relative paths.
-					atlas = assetManager.require(atlasFile);
-
-					// Create a AtlasAttachmentLoader that resolves region, mesh, boundingbox and path attachments
-					atlasLoader = new spine.AtlasAttachmentLoader(atlas);
-
-					// Create a SkeletonJson instance for parsing the .json file.
-					let skeletonJson = new spine.SkeletonJson(atlasLoader);
-
-					// Set the scale to apply during parsing, parse the file, and create a new skeleton.
-					skeletonJson.scale = 0.4;
-					let skeletonData = skeletonJson.readSkeletonData(assetManager.require(skeletonFile));
-
-					// Create a SkeletonMesh from the data and attach it to the scene
-					skeletonMesh = new spine.SkeletonMesh(skeletonData, (parameters) => {
-						parameters.depthTest = true;
-						parameters.depthWrite = true;
-						parameters.alphaTest = 0.001;
-					});
-					skeletonMesh.state.setAnimation(0, animation, true);
-					mesh.add(skeletonMesh);
-
-
-					requestAnimationFrame(render);
-				} else requestAnimationFrame(load);
-			}
-
-			let lastTime = Date.now();
-			function render() {
-				// calculate delta time for animation purposes
-				let now = Date.now() / 1000;
-				let delta = now - lastFrameTime;
-				lastFrameTime = now;
-
-				// resize canvas to use full page, adjust camera/renderer
-				resize();
-
-				// Update orbital controls
-				controls.update();
-
-				// update the animation
-				skeletonMesh.update(delta);
-
-				// render the scene
-				renderer.render(scene, camera);
-
-				requestAnimationFrame(render);
-			}
-
-			function resize() {
-				let w = window.innerWidth;
-				let h = window.innerHeight;
-				if (canvas.width != w || canvas.height != h) {
-					canvas.width = w;
-					canvas.height = h;
-				}
-
-				camera.aspect = w / h;
-				camera.updateProjectionMatrix();
-
-				renderer.setSize(w, h);
-			}
-
-			init();
-		}());
-	</script>
-</body>
-
-</html>
+  <head>
+    <meta charset="UTF-8" />
+    <title>spine-threejs</title>
+    <script src="https://unpkg.com/[email protected]/build/three.js"></script>
+    <script src="../dist/iife/spine-threejs.js"></script>
+    <script src="./OrbitalControls.js"></script>
+  </head>
+  <style>
+    * {
+      margin: 0;
+      padding: 0;
+    }
+
+    body,
+    html {
+      height: 100%;
+    }
+
+    canvas {
+      position: absolute;
+      width: 100%;
+      height: 100%;
+    }
+  </style>
+
+  <body>
+    <script>
+      (function () {
+        let scene, camera, renderer;
+        let geometry, material, mesh, skeletonMesh;
+        let assetManager;
+        let canvas;
+        let controls;
+        let lastFrameTime = Date.now() / 1000;
+
+        let baseUrl = "assets/";
+        let skeletonFile = "raptor-pro.json";
+        let atlasFile = skeletonFile
+          .replace("-pro", "")
+          .replace("-ess", "")
+          .replace(".json", ".atlas");
+        let animation = "walk";
+
+        function init() {
+          // create the THREE.JS camera, scene and renderer (WebGL)
+          let width = window.innerWidth,
+            height = window.innerHeight;
+          camera = new THREE.PerspectiveCamera(75, width / height, 1, 3000);
+          camera.position.y = 100;
+          camera.position.z = 400;
+          scene = new THREE.Scene();
+          renderer = new THREE.WebGLRenderer();
+          renderer.setSize(width, height);
+          document.body.appendChild(renderer.domElement);
+          canvas = renderer.domElement;
+          controls = new OrbitControls(camera, renderer.domElement);
+
+          // load the assets required to display the Raptor model
+          assetManager = new spine.AssetManager(baseUrl);
+          assetManager.loadText(skeletonFile);
+          assetManager.loadTextureAtlas(atlasFile);
+
+          requestAnimationFrame(load);
+        }
+
+        function load(name, scale) {
+          if (assetManager.isLoadingComplete()) {
+            // Add a box to the scene to which we attach the skeleton mesh
+            geometry = new THREE.BoxGeometry(200, 200, 200);
+            material = new THREE.MeshBasicMaterial({
+              color: 0xff0000,
+              wireframe: true,
+            });
+            mesh = new THREE.Mesh(geometry, material);
+            scene.add(mesh);
+
+            // Load the texture atlas using name.atlas and name.png from the AssetManager.
+            // The function passed to TextureAtlas is used to resolve relative paths.
+            atlas = assetManager.require(atlasFile);
+
+            // Create a AtlasAttachmentLoader that resolves region, mesh, boundingbox and path attachments
+            atlasLoader = new spine.AtlasAttachmentLoader(atlas);
+
+            // Create a SkeletonJson instance for parsing the .json file.
+            let skeletonJson = new spine.SkeletonJson(atlasLoader);
+
+            // Set the scale to apply during parsing, parse the file, and create a new skeleton.
+            skeletonJson.scale = 0.4;
+            let skeletonData = skeletonJson.readSkeletonData(
+              assetManager.require(skeletonFile)
+            );
+
+            // Create a SkeletonMesh from the data and attach it to the scene
+            skeletonMesh = new spine.SkeletonMesh(
+              skeletonData,
+              (parameters) => {
+                parameters.depthTest = true;
+                parameters.depthWrite = true;
+                parameters.alphaTest = 0.001;
+              }
+            );
+            skeletonMesh.state.setAnimation(0, animation, true);
+            mesh.add(skeletonMesh);
+
+            requestAnimationFrame(render);
+          } else requestAnimationFrame(load);
+        }
+
+        let lastTime = Date.now();
+        function render() {
+          // calculate delta time for animation purposes
+          let now = Date.now() / 1000;
+          let delta = now - lastFrameTime;
+          lastFrameTime = now;
+
+          // resize canvas to use full page, adjust camera/renderer
+          resize();
+
+          // Update orbital controls
+          controls.update();
+
+          // update the animation
+          skeletonMesh.update(delta);
+
+          // render the scene
+          renderer.render(scene, camera);
+
+          requestAnimationFrame(render);
+        }
+
+        function resize() {
+          let w = window.innerWidth;
+          let h = window.innerHeight;
+          if (canvas.width != w || canvas.height != h) {
+            canvas.width = w;
+            canvas.height = h;
+          }
+
+          camera.aspect = w / h;
+          camera.updateProjectionMatrix();
+
+          renderer.setSize(w, h);
+        }
+
+        init();
+      })();
+    </script>
+  </body>
+</html>

+ 186 - 0
spine-ts/spine-threejs/example/logarithmic-depth-buffer.html

@@ -0,0 +1,186 @@
+<html>
+  <head>
+    <meta charset="UTF-8" />
+    <title>spine-threejs</title>
+    <script src="https://unpkg.com/[email protected]/build/three.js"></script>
+    <script src="../dist/iife/spine-threejs.js"></script>
+    <script src="./OrbitalControls.js"></script>
+  </head>
+  <style>
+    * {
+      margin: 0;
+      padding: 0;
+    }
+
+    body,
+    html {
+      height: 100%;
+    }
+
+    canvas {
+      position: absolute;
+      width: 100%;
+      height: 100%;
+    }
+  </style>
+
+  <body>
+    <script>
+      (function () {
+        let scene, camera, renderer;
+        let geometry, material, mesh, skeletonMesh;
+        let assetManager;
+        let canvas;
+        let controls;
+        let lastFrameTime = Date.now() / 1000;
+
+        let baseUrl = "assets/";
+        let skeletonFile = "raptor-pro.json";
+        let atlasFile = skeletonFile
+          .replace("-pro", "")
+          .replace("-ess", "")
+          .replace(".json", ".atlas");
+        let animation = "walk";
+
+        function init() {
+          // create the THREE.JS camera, scene and renderer (WebGL)
+          let width = window.innerWidth,
+            height = window.innerHeight;
+          camera = new THREE.PerspectiveCamera(75, width / height, 1, 3000);
+          camera.position.y = 100;
+          camera.position.z = 400;
+          scene = new THREE.Scene();
+          renderer = new THREE.WebGLRenderer({ logarithmicDepthBuffer: true });
+          renderer.setSize(width, height);
+          document.body.appendChild(renderer.domElement);
+          canvas = renderer.domElement;
+          controls = new OrbitControls(camera, renderer.domElement);
+
+          // load the assets required to display the Raptor model
+          assetManager = new spine.AssetManager(baseUrl);
+          assetManager.loadText(skeletonFile);
+          assetManager.loadTextureAtlas(atlasFile);
+
+          requestAnimationFrame(load);
+        }
+
+        function load(name, scale) {
+          if (assetManager.isLoadingComplete()) {
+            // Add a box to the scene to which we attach the skeleton mesh
+            geometry = new THREE.BoxGeometry(200, 200, 200);
+            material = new THREE.MeshBasicMaterial({
+              color: 0xff0000,
+              wireframe: true,
+            });
+            mesh = new THREE.Mesh(geometry, material);
+            scene.add(mesh);
+
+            // Load the texture atlas using name.atlas and name.png from the AssetManager.
+            // The function passed to TextureAtlas is used to resolve relative paths.
+            atlas = assetManager.require(atlasFile);
+
+            // Create a AtlasAttachmentLoader that resolves region, mesh, boundingbox and path attachments
+            atlasLoader = new spine.AtlasAttachmentLoader(atlas);
+
+            // Create a SkeletonJson instance for parsing the .json file.
+            let skeletonJson = new spine.SkeletonJson(atlasLoader);
+
+            // Set the scale to apply during parsing, parse the file, and create a new skeleton.
+            skeletonJson.scale = 0.4;
+            let skeletonData = skeletonJson.readSkeletonData(
+              assetManager.require(skeletonFile)
+            );
+
+            // Create a SkeletonMesh from the data and attach it to the scene
+            // Provide a custom vertex/fragment shader pair that supports
+            // the logarithmic depth buffer.
+            // See https://discourse.threejs.org/t/shadermaterial-render-order-with-logarithmicdepthbuffer-is-wrong/49221/3
+            skeletonMesh = new spine.SkeletonMesh(
+              skeletonData,
+              (materialParameters) => {
+                materialParameters.vertexShader = `
+                attribute vec4 color;
+                varying vec2 vUv;
+                varying vec4 vColor;
+
+                #include <common>
+                #include <logdepthbuf_pars_vertex>
+
+                void main() {
+                  vUv = uv;
+                  vColor = color;
+                  gl_Position = projectionMatrix*modelViewMatrix*vec4(position,1.0);
+                  #include <logdepthbuf_vertex>
+                }
+                `;
+
+                materialParameters.fragmentShader = `
+                uniform sampler2D map;
+                #ifdef USE_SPINE_ALPHATEST
+                uniform float alphaTest;
+                #endif
+                varying vec2 vUv;
+                varying vec4 vColor;
+
+                #include <common>
+                #include <logdepthbuf_pars_fragment>
+
+                void main(void) {
+                  #include <logdepthbuf_fragment>
+
+                  gl_FragColor = vec4(1, 0, 1, 1); // texture2D(map, vUv)*vColor;
+                  #ifdef USE_SPINE_ALPHATEST
+                  if (gl_FragColor.a < alphaTest) discard;
+                  #endif
+                }
+                `;
+              }
+            );
+            skeletonMesh.state.setAnimation(0, animation, true);
+            mesh.add(skeletonMesh);
+
+            requestAnimationFrame(render);
+          } else requestAnimationFrame(load);
+        }
+
+        let lastTime = Date.now();
+        function render() {
+          // calculate delta time for animation purposes
+          let now = Date.now() / 1000;
+          let delta = now - lastFrameTime;
+          lastFrameTime = now;
+
+          // resize canvas to use full page, adjust camera/renderer
+          resize();
+
+          // Update orbital controls
+          controls.update();
+
+          // update the animation
+          skeletonMesh.update(delta);
+
+          // render the scene
+          renderer.render(scene, camera);
+
+          requestAnimationFrame(render);
+        }
+
+        function resize() {
+          let w = window.innerWidth;
+          let h = window.innerHeight;
+          if (canvas.width != w || canvas.height != h) {
+            canvas.width = w;
+            canvas.height = h;
+          }
+
+          camera.aspect = w / h;
+          camera.updateProjectionMatrix();
+
+          renderer.setSize(w, h);
+        }
+
+        init();
+      })();
+    </script>
+  </body>
+</html>

+ 246 - 188
spine-ts/spine-threejs/src/SkeletonMesh.ts

@@ -27,16 +27,33 @@
  * SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *****************************************************************************/
 
-import { AnimationState, AnimationStateData, BlendMode, ClippingAttachment, Color, MeshAttachment, NumberArrayLike, RegionAttachment, Skeleton, SkeletonClipping, SkeletonData, TextureAtlasRegion, Utils, Vector2 } from "@esotericsoftware/spine-core";
+import {
+  AnimationState,
+  AnimationStateData,
+  BlendMode,
+  ClippingAttachment,
+  Color,
+  MeshAttachment,
+  NumberArrayLike,
+  RegionAttachment,
+  Skeleton,
+  SkeletonClipping,
+  SkeletonData,
+  TextureAtlasRegion,
+  Utils,
+  Vector2,
+} from "@esotericsoftware/spine-core";
 import { MeshBatcher } from "./MeshBatcher";
 import * as THREE from "three";
 import { ThreeJsTexture } from "./ThreeJsTexture";
 
-export type SkeletonMeshMaterialParametersCustomizer = (materialParameters: THREE.ShaderMaterialParameters) => void;
+export type SkeletonMeshMaterialParametersCustomizer = (
+  materialParameters: THREE.ShaderMaterialParameters
+) => void;
 
 export class SkeletonMeshMaterial extends THREE.ShaderMaterial {
-	constructor (customizer: SkeletonMeshMaterialParametersCustomizer) {
-		let vertexShader = `
+  constructor(customizer: SkeletonMeshMaterialParametersCustomizer) {
+    let vertexShader = `
 			attribute vec4 color;
 			varying vec2 vUv;
 			varying vec4 vColor;
@@ -46,7 +63,7 @@ export class SkeletonMeshMaterial extends THREE.ShaderMaterial {
 				gl_Position = projectionMatrix*modelViewMatrix*vec4(position,1.0);
 			}
 		`;
-		let fragmentShader = `
+    let fragmentShader = `
 			uniform sampler2D map;
 			#ifdef USE_SPINE_ALPHATEST
 			uniform float alphaTest;
@@ -61,212 +78,253 @@ export class SkeletonMeshMaterial extends THREE.ShaderMaterial {
 			}
 		`;
 
-		let parameters: THREE.ShaderMaterialParameters = {
-			uniforms: {
-				map: { value: null },
-			},
-			vertexShader: vertexShader,
-			fragmentShader: fragmentShader,
-			side: THREE.DoubleSide,
-			transparent: true,
-			depthWrite: false,
-			alphaTest: 0.0
-		};
-		customizer(parameters);
-		if (parameters.alphaTest && parameters.alphaTest > 0) {
-			parameters.defines = { "USE_SPINE_ALPHATEST": 1 };
-			if (!parameters.uniforms) parameters.uniforms = {};
-			parameters.uniforms["alphaTest"] = { value: parameters.alphaTest };
-		}
-		super(parameters);
-	};
+    let parameters: THREE.ShaderMaterialParameters = {
+      uniforms: {
+        map: { value: null },
+      },
+      vertexShader: vertexShader,
+      fragmentShader: fragmentShader,
+      side: THREE.DoubleSide,
+      transparent: true,
+      depthWrite: true,
+      alphaTest: 0.0,
+    };
+    customizer(parameters);
+    if (parameters.alphaTest && parameters.alphaTest > 0) {
+      parameters.defines = { USE_SPINE_ALPHATEST: 1 };
+      if (!parameters.uniforms) parameters.uniforms = {};
+      parameters.uniforms["alphaTest"] = { value: parameters.alphaTest };
+    }
+    super(parameters);
+  }
 }
 
 export class SkeletonMesh extends THREE.Object3D {
-	tempPos: Vector2 = new Vector2();
-	tempUv: Vector2 = new Vector2();
-	tempLight = new Color();
-	tempDark = new Color();
-	skeleton: Skeleton;
-	state: AnimationState;
-	zOffset: number = 0.1;
+  tempPos: Vector2 = new Vector2();
+  tempUv: Vector2 = new Vector2();
+  tempLight = new Color();
+  tempDark = new Color();
+  skeleton: Skeleton;
+  state: AnimationState;
+  zOffset: number = 0.1;
 
-	private batches = new Array<MeshBatcher>();
-	private nextBatchIndex = 0;
-	private clipper: SkeletonClipping = new SkeletonClipping();
+  private batches = new Array<MeshBatcher>();
+  private nextBatchIndex = 0;
+  private clipper: SkeletonClipping = new SkeletonClipping();
 
-	static QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];
-	static VERTEX_SIZE = 2 + 2 + 4;
+  static QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];
+  static VERTEX_SIZE = 2 + 2 + 4;
 
-	private vertices = Utils.newFloatArray(1024);
-	private tempColor = new Color();
+  private vertices = Utils.newFloatArray(1024);
+  private tempColor = new Color();
 
-	constructor (skeletonData: SkeletonData, private materialCustomerizer: SkeletonMeshMaterialParametersCustomizer = (material) => { }) {
-		super();
+  constructor(
+    skeletonData: SkeletonData,
+    private materialCustomerizer: SkeletonMeshMaterialParametersCustomizer = (
+      material
+    ) => {}
+  ) {
+    super();
 
-		this.skeleton = new Skeleton(skeletonData);
-		let animData = new AnimationStateData(skeletonData);
-		this.state = new AnimationState(animData);
-	}
+    this.skeleton = new Skeleton(skeletonData);
+    let animData = new AnimationStateData(skeletonData);
+    this.state = new AnimationState(animData);
+  }
 
-	update (deltaTime: number) {
-		let state = this.state;
-		let skeleton = this.skeleton;
+  update(deltaTime: number) {
+    let state = this.state;
+    let skeleton = this.skeleton;
 
-		state.update(deltaTime);
-		state.apply(skeleton);
-		skeleton.updateWorldTransform();
+    state.update(deltaTime);
+    state.apply(skeleton);
+    skeleton.updateWorldTransform();
 
-		this.updateGeometry();
-	}
+    this.updateGeometry();
+  }
 
-	dispose () {
-		for (var i = 0; i < this.batches.length; i++) {
-			this.batches[i].dispose();
-		}
-	}
+  dispose() {
+    for (var i = 0; i < this.batches.length; i++) {
+      this.batches[i].dispose();
+    }
+  }
 
-	private clearBatches () {
-		for (var i = 0; i < this.batches.length; i++) {
-			this.batches[i].clear();
-			this.batches[i].visible = false;
-		}
-		this.nextBatchIndex = 0;
-	}
+  private clearBatches() {
+    for (var i = 0; i < this.batches.length; i++) {
+      this.batches[i].clear();
+      this.batches[i].visible = false;
+    }
+    this.nextBatchIndex = 0;
+  }
 
-	private nextBatch () {
-		if (this.batches.length == this.nextBatchIndex) {
-			let batch = new MeshBatcher(10920, this.materialCustomerizer);
-			this.add(batch);
-			this.batches.push(batch);
-		}
-		let batch = this.batches[this.nextBatchIndex++];
-		batch.visible = true;
-		return batch;
-	}
+  private nextBatch() {
+    if (this.batches.length == this.nextBatchIndex) {
+      let batch = new MeshBatcher(10920, this.materialCustomerizer);
+      this.add(batch);
+      this.batches.push(batch);
+    }
+    let batch = this.batches[this.nextBatchIndex++];
+    batch.visible = true;
+    return batch;
+  }
 
-	private updateGeometry () {
-		this.clearBatches();
+  private updateGeometry() {
+    this.clearBatches();
 
-		let tempPos = this.tempPos;
-		let tempUv = this.tempUv;
-		let tempLight = this.tempLight;
-		let tempDark = this.tempDark;
-		let clipper = this.clipper;
+    let tempPos = this.tempPos;
+    let tempUv = this.tempUv;
+    let tempLight = this.tempLight;
+    let tempDark = this.tempDark;
+    let clipper = this.clipper;
 
-		let vertices: NumberArrayLike = this.vertices;
-		let triangles: Array<number> | null = null;
-		let uvs: NumberArrayLike | null = null;
-		let drawOrder = this.skeleton.drawOrder;
-		let batch = this.nextBatch();
-		batch.begin();
-		let z = 0;
-		let zOffset = this.zOffset;
-		for (let i = 0, n = drawOrder.length; i < n; i++) {
-			let vertexSize = clipper.isClipping() ? 2 : SkeletonMesh.VERTEX_SIZE;
-			let slot = drawOrder[i];
-			if (!slot.bone.active) {
-				clipper.clipEndWithSlot(slot);
-				continue;
-			}
-			let attachment = slot.getAttachment();
-			let attachmentColor: Color | null;
-			let texture: ThreeJsTexture | null;
-			let numFloats = 0;
-			if (attachment instanceof RegionAttachment) {
-				let region = <RegionAttachment>attachment;
-				attachmentColor = region.color;
-				vertices = this.vertices;
-				numFloats = vertexSize * 4;
-				region.computeWorldVertices(slot, vertices, 0, vertexSize);
-				triangles = SkeletonMesh.QUAD_TRIANGLES;
-				uvs = region.uvs;
-				texture = <ThreeJsTexture>region.region!.texture;
-			} else if (attachment instanceof MeshAttachment) {
-				let mesh = <MeshAttachment>attachment;
-				attachmentColor = mesh.color;
-				vertices = this.vertices;
-				numFloats = (mesh.worldVerticesLength >> 1) * vertexSize;
-				if (numFloats > vertices.length) {
-					vertices = this.vertices = Utils.newFloatArray(numFloats);
-				}
-				mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, vertexSize);
-				triangles = mesh.triangles;
-				uvs = mesh.uvs;
-				texture = <ThreeJsTexture>mesh.region!.texture;
-			} else if (attachment instanceof ClippingAttachment) {
-				let clip = <ClippingAttachment>(attachment);
-				clipper.clipStart(slot, clip);
-				continue;
-			} else {
-				clipper.clipEndWithSlot(slot);
-				continue;
-			}
+    let vertices: NumberArrayLike = this.vertices;
+    let triangles: Array<number> | null = null;
+    let uvs: NumberArrayLike | null = null;
+    let drawOrder = this.skeleton.drawOrder;
+    let batch = this.nextBatch();
+    batch.begin();
+    let z = 0;
+    let zOffset = this.zOffset;
+    for (let i = 0, n = drawOrder.length; i < n; i++) {
+      let vertexSize = clipper.isClipping() ? 2 : SkeletonMesh.VERTEX_SIZE;
+      let slot = drawOrder[i];
+      if (!slot.bone.active) {
+        clipper.clipEndWithSlot(slot);
+        continue;
+      }
+      let attachment = slot.getAttachment();
+      let attachmentColor: Color | null;
+      let texture: ThreeJsTexture | null;
+      let numFloats = 0;
+      if (attachment instanceof RegionAttachment) {
+        let region = <RegionAttachment>attachment;
+        attachmentColor = region.color;
+        vertices = this.vertices;
+        numFloats = vertexSize * 4;
+        region.computeWorldVertices(slot, vertices, 0, vertexSize);
+        triangles = SkeletonMesh.QUAD_TRIANGLES;
+        uvs = region.uvs;
+        texture = <ThreeJsTexture>region.region!.texture;
+      } else if (attachment instanceof MeshAttachment) {
+        let mesh = <MeshAttachment>attachment;
+        attachmentColor = mesh.color;
+        vertices = this.vertices;
+        numFloats = (mesh.worldVerticesLength >> 1) * vertexSize;
+        if (numFloats > vertices.length) {
+          vertices = this.vertices = Utils.newFloatArray(numFloats);
+        }
+        mesh.computeWorldVertices(
+          slot,
+          0,
+          mesh.worldVerticesLength,
+          vertices,
+          0,
+          vertexSize
+        );
+        triangles = mesh.triangles;
+        uvs = mesh.uvs;
+        texture = <ThreeJsTexture>mesh.region!.texture;
+      } else if (attachment instanceof ClippingAttachment) {
+        let clip = <ClippingAttachment>attachment;
+        clipper.clipStart(slot, clip);
+        continue;
+      } else {
+        clipper.clipEndWithSlot(slot);
+        continue;
+      }
 
-			if (texture != null) {
-				let skeleton = slot.bone.skeleton;
-				let skeletonColor = skeleton.color;
-				let slotColor = slot.color;
-				let alpha = skeletonColor.a * slotColor.a * attachmentColor.a;
-				let color = this.tempColor;
-				color.set(skeletonColor.r * slotColor.r * attachmentColor.r,
-					skeletonColor.g * slotColor.g * attachmentColor.g,
-					skeletonColor.b * slotColor.b * attachmentColor.b,
-					alpha);
+      if (texture != null) {
+        let skeleton = slot.bone.skeleton;
+        let skeletonColor = skeleton.color;
+        let slotColor = slot.color;
+        let alpha = skeletonColor.a * slotColor.a * attachmentColor.a;
+        let color = this.tempColor;
+        color.set(
+          skeletonColor.r * slotColor.r * attachmentColor.r,
+          skeletonColor.g * slotColor.g * attachmentColor.g,
+          skeletonColor.b * slotColor.b * attachmentColor.b,
+          alpha
+        );
 
-				let finalVertices: NumberArrayLike;
-				let finalVerticesLength: number;
-				let finalIndices: NumberArrayLike;
-				let finalIndicesLength: number;
+        let finalVertices: NumberArrayLike;
+        let finalVerticesLength: number;
+        let finalIndices: NumberArrayLike;
+        let finalIndicesLength: number;
 
-				if (clipper.isClipping()) {
-					clipper.clipTriangles(vertices, numFloats, triangles, triangles.length, uvs, color, tempLight, false);
-					let clippedVertices = clipper.clippedVertices;
-					let clippedTriangles = clipper.clippedTriangles;
-					finalVertices = clippedVertices;
-					finalVerticesLength = clippedVertices.length;
-					finalIndices = clippedTriangles;
-					finalIndicesLength = clippedTriangles.length;
-				} else {
-					let verts = vertices;
-					for (let v = 2, u = 0, n = numFloats; v < n; v += vertexSize, u += 2) {
-						verts[v] = color.r;
-						verts[v + 1] = color.g;
-						verts[v + 2] = color.b;
-						verts[v + 3] = color.a;
-						verts[v + 4] = uvs[u];
-						verts[v + 5] = uvs[u + 1];
-					}
-					finalVertices = vertices;
-					finalVerticesLength = numFloats;
-					finalIndices = triangles;
-					finalIndicesLength = triangles.length;
-				}
+        if (clipper.isClipping()) {
+          clipper.clipTriangles(
+            vertices,
+            numFloats,
+            triangles,
+            triangles.length,
+            uvs,
+            color,
+            tempLight,
+            false
+          );
+          let clippedVertices = clipper.clippedVertices;
+          let clippedTriangles = clipper.clippedTriangles;
+          finalVertices = clippedVertices;
+          finalVerticesLength = clippedVertices.length;
+          finalIndices = clippedTriangles;
+          finalIndicesLength = clippedTriangles.length;
+        } else {
+          let verts = vertices;
+          for (
+            let v = 2, u = 0, n = numFloats;
+            v < n;
+            v += vertexSize, u += 2
+          ) {
+            verts[v] = color.r;
+            verts[v + 1] = color.g;
+            verts[v + 2] = color.b;
+            verts[v + 3] = color.a;
+            verts[v + 4] = uvs[u];
+            verts[v + 5] = uvs[u + 1];
+          }
+          finalVertices = vertices;
+          finalVerticesLength = numFloats;
+          finalIndices = triangles;
+          finalIndicesLength = triangles.length;
+        }
 
-				if (finalVerticesLength == 0 || finalIndicesLength == 0) {
-					clipper.clipEndWithSlot(slot);
-					continue;
-				}
+        if (finalVerticesLength == 0 || finalIndicesLength == 0) {
+          clipper.clipEndWithSlot(slot);
+          continue;
+        }
 
-				// Start new batch if this one can't hold vertices/indices
-				if (!batch.canBatch(finalVerticesLength / SkeletonMesh.VERTEX_SIZE, finalIndicesLength)) {
-					batch.end();
-					batch = this.nextBatch();
-					batch.begin();
-				}
+        // Start new batch if this one can't hold vertices/indices
+        if (
+          !batch.canBatch(
+            finalVerticesLength / SkeletonMesh.VERTEX_SIZE,
+            finalIndicesLength
+          )
+        ) {
+          batch.end();
+          batch = this.nextBatch();
+          batch.begin();
+        }
 
-				const slotBlendMode = slot.data.blendMode;
-				const slotTexture = texture.texture;
-				const materialGroup = batch.findMaterialGroup(slotTexture, slotBlendMode);
+        const slotBlendMode = slot.data.blendMode;
+        const slotTexture = texture.texture;
+        const materialGroup = batch.findMaterialGroup(
+          slotTexture,
+          slotBlendMode
+        );
 
-				batch.addMaterialGroup(finalIndicesLength, materialGroup);
-				batch.batch(finalVertices, finalVerticesLength, finalIndices, finalIndicesLength, z);
-				z += zOffset;
-			}
+        batch.addMaterialGroup(finalIndicesLength, materialGroup);
+        batch.batch(
+          finalVertices,
+          finalVerticesLength,
+          finalIndices,
+          finalIndicesLength,
+          z
+        );
+        z += zOffset;
+      }
 
-			clipper.clipEndWithSlot(slot);
-		}
-		clipper.clipEnd();
-		batch.end();
-	}
+      clipper.clipEndWithSlot(slot);
+    }
+    clipper.clipEnd();
+    batch.end();
+  }
 }