I’m trying to use a video as a spot light cookie, but I can only get the first frame to display. If I use the same texture instance on a different piece of geometry I can see the video is playing fine on there, it’s just not updating on the cookie projection. Also, the cookie scale seems to have no effect.
The code I’m using is mainly taken from the example here https://playcanvas.com/editor/scene/1345100 which I can see is working (unless I fork the project, in which case not working at all) so I’m at a loss.
Any suggestions gratefully received.
const args = {
...opts,
affectLightmapped: true,
affectDynamic: true,
normalOffsetBias: 0.2,
color: getColourOpt(opts),
falloffMode: LIGHTFALLOFF_INVERSESQUARED,
};
const light = entity.addComponent('light', args) as LightComponent;
const setupVideoTexture = () => {
try {
video.play();
}
} catch (e) {
// If video is no longer loaded then skip
console.warn('Unable to load video', e);
}
};
const videoUpload = () => {
if (videoTexture) {
videoTexture.upload();
}
};
const destroyVideo = () => {
videoTexture.destroy();
video.remove();
};
const video = document.createElement('video');
video.id = 'light_cookie_vid' + Date.now();
video.loop = true;
// muted attribute is required for videos to autoplay
video.muted = true;
// critical for iOS or the video won't initially play, and will go fullscreen when playing
video.playsInline = true;
// needed because the video is being hosted on a different server url
video.crossOrigin = 'anonymous';
// autoplay the video
video.autoplay = true;
// iOS video texture playback requires that you add the video to the DOMParser
// with at least 1x1 as the video's dimensions
var style = video.style;
style.width = '1px';
style.height = '1px';
style.position = 'absolute';
style.opacity = '0';
style.zIndex = '-1000';
style.pointerEvents = 'none';
document.body.appendChild(video);
// Create a texture to hold the video frame data
const videoTexture = new Texture(app.graphicsDevice, {
format: PIXELFORMAT_R8_G8_B8,
minFilter: FILTER_LINEAR_MIPMAP_LINEAR,
magFilter: FILTER_LINEAR,
addressU: ADDRESS_CLAMP_TO_EDGE,
addressV: ADDRESS_CLAMP_TO_EDGE,
mipmaps: true,
});
videoTexture.setSource(video);
video.addEventListener('canplaythrough', setupVideoTexture);
video.src = spotOpts.cookieURL;
document.body.appendChild(video);
video.load();
app.scene.lighting.cookiesEnabled = true;
light.cookie = videoTexture;
light.cookieScale = new Vec2(1.777777, 1);
app.on('destroy', function () {
app.off('update', videoUpload);
video.removeEventListener('canplaythrough', setupVideoTexture);
destroyVideo();
});
app.on('update', videoUpload);