Youtube Video as Texture

Hi ShapeSpark Team,

I have a client that is looking to put together a trade event that would have 1,500 booth locations in it, these booths would all have a TV with a pitch video playing on them.

Is it possible to have these videos linking from Youtube, as downloading 1,500 videos when the tour loads would make this a really bad user experience.

Ideally something like this:

If not the above, then a place holder image that when clicked displays the youtube video on the tv.


1 Like

Hi, YouTube video’s can’t be used as WebGL texture because YouTube doesn’t expose HTML Video elements for them. What could be done, is to place the videos on some external server and use JavaScript API to load them only when the user clicks on a screen or some other trigger.

I’m not 100% sure if browsers will download anything if you configure the videos not play automatically on the scene load. Videos for WebGL are streamed, so if all of them will be paused it is likely that browsers won’t be downloading anything.

But I’m afraid that with 1500 booths you will run into performance and memory problems. You will need to have at least 1500 separate materials rendered in a render loop(usually scenes have less than 200), geometry and lightmaps will likely be large. 1500 booths will likely be above Shapespark capabilities.

@jan This Javascript API can place the videos directly in a surface inside shapespark or ina a window or frame outside the tour?
This Javascript API is the same like we use for mini maps?

This is the same API, it can place images or videos loaded from external server as textures in 3D.

@jan please can you give me an example? do you can write the lines and I change the video web direction?

It is the last section of GitHub - shapespark/shapespark-viewer-api: JavaScript API for interacting with the Shapespark 3D scene., ‘Replace textures using images or videos from external source.’. The section includes example code: shapespark-viewer-api/body-end.html at master · shapespark/shapespark-viewer-api · GitHub

This is interesting. I tried testing the example code and it works great. But how do I put it behind a trigger? I tried via extensions - script and setting up a trigger but nothing happens when I click it.

Could you share a link to the scene with the script extension not working as you intend to?

You can configure the triggers via the viewer API as well. To make an object type a custom trigger use the onNodeTypeClicked API function: GitHub - shapespark/shapespark-viewer-api: JavaScript API for interacting with the Shapespark 3D scene.. Anchors for sphere/sprite triggers can be added as described in: Trigger Extensions via Javascript - #2 by jan.

Thanks. I tried my best to modify the code but so far got nowhere. I tried the onNodeTypeClicked function everywhere I could think of but to no avail.

Here I got 2 of your sample videos playing on the first screen quite nicely using body-end: 3D scene

But if I try to put this function behind a trigger through viewer API + a trigger, nothing happens:

What I’m actually looking for is having extensions for all 40 or so screens on the first model whose triggers would start the video from an external source on the screen. So I guess I’m not rather searching for a “picker” but a “player”.

The goal is to achieve less strain on the model using this method.

If you’d like to make certain scene object types act as a trigger for video textures fetched from external sources, then body-end.html seems like the best way to go.

I’ve sketched a sample script showing how to do it in the “example-room” scene. Please make copy the vanilla “example-room” scene from C:\Users\<USER>\AppData\Local\Shapespark\app-<VER>\resources\ under a different name in the Document\Shapespark directory, and add the following body-end.html file:

  const viewer = WALK.getViewer();

  viewer.setMaterialEditable('Curtain fabric');
  function createVideoTexture(src, muted, loop) {
    const video = document.createElement('video');
    video.src = src;
    video.autoplay = false;
    video.muted = muted;
    video.loop = loop;
    return viewer.createTextureFromHtmlVideo(video);
  function setUpExternalVideoTexture(triggerNodeTypeName, materialName,
                                     videoSrc, muted, loop) {
    let videoTexture = null;
    viewer.onNodeTypeClicked(triggerNodeTypeName, function() {
      // Create the video texture only once.
      if (!videoTexture) {
        videoTexture = createVideoTexture(videoSrc, muted, loop);
        const material = viewer.findMaterial(materialName);
        material.baseColorTexture = videoTexture;
      if (!videoTexture.isPlaying) {;
      } else {
      return true;

  setUpExternalVideoTexture('Rug', 'Rug', '', false, true);
  setUpExternalVideoTexture('Curtain A', 'Curtain fabric', '', false, true);

When you click the curtains or the rug the original texture will be replaced with a video texture from external source.

That said, I’d first try to use video textures from the scene, as you write in Triggers, video textures and model accessibility - #3 by ville . I believe paused textures shouldn’t consume much memory or computational resources, even after they have been loaded.


Thanks a million! Ok, I’ll proceed as you suggested.

I don’t quite understand, is it possible to link a youtube video as a texture?

No, it is not possible, video textures need to be added from the editor and uploaded as a part of a scene. But you can show YouTube video in a HTML Label popup.

@wojtek, Can we place a power point presentation as a texture to use in meetings please?

1 Like

Changes to YouTube’s Terms of Service

Does this also affects the video in pop-up windows?

Hi. I was trying out fetching videos from external servers onto the texture. The code mentioned here works well. However, I was wondering if there is any way to add controls (like rewind, forward, seek) apart from the play/stop. This would be very helpful for long videos. Thanks

acompanhando a sua pergunta.

Not sure it’d work but since it’s a video object, you could try with something like video.currentTime += 5 for the forward (and -5 for rewind :slight_smile: ) in a function linked to a button of your own. Even the seek could be done this way (little bit more complicated though …). Let us know if it works :slight_smile:

1 Like