So, I've been messing around with opacity fade-in/fade-outs of glTF models in Aframe, and have achieved good results using Piotr Adam Milewski's model-opacity script (from here), and have looped my daisy-chained animation sequences using Tired Eyes' animation-manager script (from here).
However, I'm having difficulties trying to work out how to also animate the opacity of the model's shadow, as at the moment its shadow still remains visible after the model is no longer visible.
Demo Link 👇
I've remixed a Glitch (of Ada Rose Cannon's AR Starter Kit) which you can find here to show what I mean (see line 204 in the Glitch for the model fade-in/out).
I'd be really grateful if anyone can shed any light on whether it's possible to animate the Aframe shadow to match the model's opacity. Many thanks, in advance, for any advice 🙂
I'm afraid a built-in solution is not yet ready (issue / PR)
For a single object, you could just use a ShadowMaterial, which has a opacity
property, which could be animated along with the objects opacity:
<script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>
<script src="https://gftruj.github.io/webzamples/aframe/models/components/model-opacity.js"></script>
<script>
AFRAME.registerComponent("relative-shadow", {
schema: {
target: { type: "selector" }
},
init: function() {
const mesh = this.el.getObject3D("mesh"); // grab the mesh
const oldMaterial = mesh.material; // store the old material
mesh.material = this.material = new THREE.ShadowMaterial(); // apply a shadow material
oldMaterial.dispose(); // dispose the old material
},
update: function() {
this.opacitySource = this.data.target.components["model-opacity"]; // react to the target being set
},
tick: function() {
if (!this.opacitySource) return; // wait until we can access the opacity value
// update the opacity using the t-rex material opacity from the component
this.material.opacity = this.opacitySource.data.opacity;
}
})
</script>
<a-scene>
<a-asset-item id="spino" src="https://rawcdn.githack.com/krlosflip22/aframe-ar-sample/c91a7a9dd8b1428bc8e68bc1b5d8641d7241fd1b/spinosaurus.glb"></a-asset-item>
<a-gltf-model id="trex" position="0 1 -4" shadow="cast: true" scale="0.5 0.5 0.5" src="#spino" model-opacity
animation="property: model-opacity.opacity; to: 0; dur: 1000; dir: alternate; loop: true;"></a-gltf-model>
<a-plane rotation="-90 0 0" scale="40 40 40"
relative-shadow="target: #trex" shadow="receive: true"></a-plane>
<a-sky color="#ECECEC"></a-sky>
</a-scene>
For multiple objects, a simple yet effective solution would be faking shadows - have transparent radial gradient images below the objects like in the threejs fundamentals example. You could control the opacity of each one of them:
<iframe width="100%" height="100%" src="https://r105.threejsfundamentals.org/threejs/threejs-shadows-fake.html"></iframe>