[SOLVED] Render second scene as texture on cube. What am I missing?

I am trying to render a scene as a texture on a cube in another scene.

I’ve got the following, but the green color is not appearing on the cube as I’m expecting:

If we comment out the renderTarget, and render the second scene to a camera, we do see the green color (scroll down):

What am I missing?

AFAICS, you are using two instances of WebGLRenderer. renderer2 is used to produce the render target which is used as a texture when rendering scene with the first instance of WebGLRenderer.

This is not valid. Each WebGLRenderer has its own WebGL rendering context. And it’s not valid to share resource between different contexts. Meaning you can’t create a custom framebuffer (render target) in one context and use it in another one.

Please try to rewrite your codepen with just one instance of WebGLRenderer.

Indeed that does the trick. I had seen another comment from you about this, and was wondering if this was the case.

However, I don’t understand why it shouldn’t work. Shouldn’t we be able to pass a texture onto a map property of a material and it should just work like with any other texture regardless of how we update that texture?

Here’s the example working how you suggested:

@Mugen87 Now that we’re on this topic specifically, is there a way to have two separate scenes and renderers, and do it the first way that I was trying?

I’m wondering, because there are times when one can not access the underlying renderer, but they can pass in objects from the outside. It is intuitive that we should be able to render with a second renderer and scene, stick it onto the object’s material’s map, and pass that object into the library that creates the first scene.

The thing that should matter is that, even if the second renderer and scene has its own WebGL context, it should use that context to update its own texture, and then once that texture is passed into the main scene in the form of a material map it should just work like with any other textures.

Maybe I’m missing something in the first approach.

Sorry, I can only say that what you have in mind is technically not possible. And implementing some sort of abstraction on engine-level will lead to unjustifiable complexity and surely downgrade performance. Please forget this whole idea, you really heading in the wrong direction.

Is using two WebGL contexts a very bad idea? I get that using one context is faster. But speed requirements depend on use case.

How does it compare to using a separate canvas as a texture? (which is currently possible)

Also something that you should think about is developer experience, which I don’t think is the wrong direction to be thinking about.

I was doing what was intuitive: I’ve always passed arbitrary textures into material.map properties, and it always worked. The fact that this one doesn’t, it not intuitive at all.

And as I mentioned, not everyone has access to underlying renderers, so the technique that you told me to use only works part of the time, not all the time.

@Mugen87 Even if there’s a performance hit, I’d like to try and figure how to update the renderTarget’s texture and pass it into the other scene.

I have no choice, and I do not want to fork the library that wraps Three.js just to make new APIs to access the underlying renderer. That would be no good. :-1: Having to fork libs is a developer’s last resort (a bad developer experience).

Maybe I need to render my scene (the second scene) to a canvas, and then just use a canvas texture.

Yes, I know, that will be slower!

There we go! The following example shows a way to use two separate renderers (which is necessary in some cases).

The second scene renders to the second renderer’s canvas which is not placed in the DOM (therefore not visible), then this second canvas is passed to a CanvasTexture, and finally the CanvasTexture is used at the material map of an object in the first scene:

TODO:

  • [ ] Find out why passing the texture from the renderTarget does not work. In my opinion, it should work as with a CanvasTexture of the previous example.