[threejs] Fix clipping not being ended, better alpha test support.

This commit is contained in:
Mario Zechner 2022-03-08 22:03:01 +01:00
parent 5ff19ea31c
commit 6887aa617a
5 changed files with 45 additions and 8 deletions

View File

@ -238,6 +238,7 @@
* `SkeletonMesh` now takes an optional `SkeletonMeshMaterialParametersCustomizer` function that allows you to modify the `ShaderMaterialParameters` before the material is finalized. Use it to modify things like THREEJS' `Material.depthTest` etc. See #1590. * `SkeletonMesh` now takes an optional `SkeletonMeshMaterialParametersCustomizer` function that allows you to modify the `ShaderMaterialParameters` before the material is finalized. Use it to modify things like THREEJS' `Material.depthTest` etc. See #1590.
* **Breaking change:** the global object `spine.canvas` no longer exists. All classes and functions are now exposed on the global `spine` object directly. Simply replace any reference to `spine.threejs.` in your source code with `spine.`. * **Breaking change:** the global object `spine.canvas` no longer exists. All classes and functions are now exposed on the global `spine` object directly. Simply replace any reference to `spine.threejs.` in your source code with `spine.`.
* **Breaking change:** the default fragment shader of `SkeletonMeshMaterial` now explicitely discards fragments with alpha < 0.5. See https://github.com/EsotericSoftware/spine-runtimes/issues/1985 * **Breaking change:** the default fragment shader of `SkeletonMeshMaterial` now explicitely discards fragments with alpha < 0.5. See https://github.com/EsotericSoftware/spine-runtimes/issues/1985
* **Breaking change:** reversal of the previous breaking change: the default fragment shader of `SkeletonMeshMaterial` does no longer discard fragments with alpha < 0.5. Pass a `SkeletonMeshMaterialParametersCustomizer` to the `SkeletonMesh` constructor, and modify `parameters.alphaTest` to be > 0.
### Player ### Player
* Added `SpinePlayerConfig.rawDataURIs`. Allows to embed data URIs for skeletons, atlases and atlas page images directly in the HTML/JS without needing to load it from a separate file. See the example for a demonstration. * Added `SpinePlayerConfig.rawDataURIs`. Allows to embed data URIs for skeletons, atlases and atlas page images directly in the HTML/JS without needing to load it from a separate file. See the example for a demonstration.

View File

@ -17,6 +17,20 @@
"name": "drag-and-drop", "name": "drag-and-drop",
"url": "http://localhost:8080/spine-webgl/example/drag-and-drop.html", "url": "http://localhost:8080/spine-webgl/example/drag-and-drop.html",
"webRoot": "${workspaceFolder}" "webRoot": "${workspaceFolder}"
},
{
"type": "pwa-chrome",
"request": "launch",
"name": "barebones-dragon",
"url": "http://localhost:8080/spine-webgl/example/barebones-dragon.html",
"webRoot": "${workspaceFolder}"
},
{
"type": "pwa-chrome",
"request": "launch",
"name": "threejs-example",
"url": "http://localhost:8080/spine-threejs/example/index.html",
"webRoot": "${workspaceFolder}"
} }
] ]
} }

View File

@ -50,26 +50,35 @@ export class SkeletonMeshMaterial extends THREE.ShaderMaterial {
`; `;
let fragmentShader = ` let fragmentShader = `
uniform sampler2D map; uniform sampler2D map;
#ifdef USE_ALPHATEST
uniform float alphaTest;
#endif
varying vec2 vUv; varying vec2 vUv;
varying vec4 vColor; varying vec4 vColor;
void main(void) { void main(void) {
gl_FragColor = texture2D(map, vUv)*vColor; gl_FragColor = texture2D(map, vUv)*vColor;
if (gl_FragColor.a < 0.5) discard; #ifdef USE_ALPHATEST
if (gl_FragColor.a < alphaTest) discard;
#endif
} }
`; `;
let parameters: THREE.ShaderMaterialParameters = { let parameters: THREE.ShaderMaterialParameters = {
uniforms: { uniforms: {
map: { type: "t", value: null } as any map: { value: null },
}, },
vertexShader: vertexShader, vertexShader: vertexShader,
fragmentShader: fragmentShader, fragmentShader: fragmentShader,
side: THREE.DoubleSide, side: THREE.DoubleSide,
transparent: true, transparent: true,
depthWrite: false, depthWrite: false,
alphaTest: 0.5 alphaTest: 0.0
}; };
customizer(parameters); customizer(parameters);
if (parameters.alphaTest > 0) {
parameters.defines = { "USE_ALPHATEST": 1 };
parameters.uniforms["alphaTest"] = { value: parameters.alphaTest };
}
super(parameters); super(parameters);
}; };
} }
@ -194,7 +203,10 @@ export class SkeletonMesh extends THREE.Object3D {
let clip = <ClippingAttachment>(attachment); let clip = <ClippingAttachment>(attachment);
clipper.clipStart(slot, clip); clipper.clipStart(slot, clip);
continue; continue;
} else continue; } else {
clipper.clipEndWithSlot(slot);
continue;
}
if (texture != null) { if (texture != null) {
let skeleton = slot.bone.skeleton; let skeleton = slot.bone.skeleton;

View File

@ -12,6 +12,8 @@
<div style="position: absolute; top: 1em; left: 1em; z-index: 1; color: #ccc;"> <div style="position: absolute; top: 1em; left: 1em; z-index: 1; color: #ccc;">
<label style="margin-right: 0.5em;">Animations</label> <label style="margin-right: 0.5em;">Animations</label>
<select id="animations"></select> <select id="animations"></select>
<label>PMA</label>
<input type="checkbox" id="pma" checked>
</div> </div>
<script src="drag-and-drop.js"></script> <script src="drag-and-drop.js"></script>
</body> </body>

View File

@ -3,6 +3,7 @@ class App {
this.skeleton = null; this.skeleton = null;
this.animationState = null; this.animationState = null;
this.canvas = null; this.canvas = null;
this.pma = true;
} }
loadAssets(canvas) { loadAssets(canvas) {
@ -20,7 +21,13 @@ class App {
// Setup listener for animation selection box // Setup listener for animation selection box
let animationSelectBox = document.body.querySelector("#animations"); let animationSelectBox = document.body.querySelector("#animations");
animationSelectBox.onchange = () => { animationSelectBox.onchange = () => {
this.animationState.setAnimation(0, animationSelectBox.value, true); // this.animationState.setAnimation(0, animationSelectBox.value, true);
}
// Setup listener for the PMA checkbox
let pmaCheckbox = document.body.querySelector("#pma");
pmaCheckbox.onchange = () => {
this.pma = pmaCheckbox.checked;
} }
// Setup the drag and drop listener // Setup the drag and drop listener
@ -117,7 +124,7 @@ class App {
animationSelectBox.appendChild(option); animationSelectBox.appendChild(option);
} }
if (animationName) this.animationState.setAnimation(0, animationName, true); // if (animationName) this.animationState.setAnimation(0, animationName, true);
// Center the skeleton in the viewport // Center the skeleton in the viewport
this.centerSkeleton(); this.centerSkeleton();
@ -153,10 +160,11 @@ class App {
renderer.resize(spine.ResizeMode.Expand); renderer.resize(spine.ResizeMode.Expand);
canvas.clear(0.2, 0.2, 0.2, 1); canvas.clear(0.2, 0.2, 0.2, 1);
renderer.begin(); renderer.begin();
renderer.line(-10000, 0, 10000, 0, spine.Color.RED); renderer.line(-10000, 0, 10000, 0, spine.Color.RED);
renderer.line(0, -10000, 0, 10000, spine.Color.GREEN); renderer.line(0, -10000, 0, 10000, spine.Color.GREEN);
renderer.drawSkeleton(this.skeleton, true); renderer.drawSkeleton(this.skeleton, this.pma);
renderer.end(); renderer.end();
} }
} }