Working with external webgl2 context

Hi,

I have a Babylon engine that needs to work with an external webgl2 implementation as per new requirements.

Babylon does support this requirement by passing WebGL context 2 in the engine parameter.

I have created a small application that mimics

  • an external webgl2 engine - this is a small pure webgl2 code that renders a color cube.

I have also created a small Babylon scene with a simple Sphere.

I created a render loop callback where I call the

  • WebGL2 Scene first, clear background and enable depth buffer.
    renderGLCube(weglgl2Context, canvas.width, canvas.height, time+=0.01);

  • I render the Babylon scene next to where I render Sphere.
    renderBabylonSphere()

Now, if I render them individually they work well. In the below image, you can see the output.

The problem appears when both scenes are rendered together and in the Babylon JS scene.

  • The color of the sphere gets influenced.
  • The depth is not working, is my understanding correct here?

See the below output.
webgl2-babylon-mixing

In my case, the external engine could be any other third-party WebGL2 implementation.
Source code: GitHub - giraphics/babylonjs-external-webglcontext2: Babylon with external GL context example

Query: How can I make the Babylon scene rendering correct without getting influenced by an external engine, I really don’t know in real situations what global webgl2 states that engine is going to affect.

autoClear is for the background color only, you should also set autoClearDepthAndStencil to false to prevent Babylon.js from clearing the depth/stencil.

1 Like

Hi @Evgeni_Popov,

The depth issue is resolved, thanks for your suggestion.

However, there is one issue still remaining I am battling with which is the incorrect sphere color.
webgl2-babylon-mixing-depth-fixed

I try to set the engine’s wipe cache it restores the sphere color but completely wipes my custom webgl2 custom scene.

      scene.beforeRender = () => {
        engine.wipeCaches(true);
      };

Any help on the issue is highly appreciated.

Try scene.resetCachedMaterial() instead.

However, the problem is that each engine assumes that no one will change the WebGL state(s) it has defined… To be safe, you should save all WebGL states before calling the external engine, and put them back afterwards. The problem is that it can be slow to do this every frame (also, I don’t think there is a single function to save/restore states in WebGL, it’s probably not easy to do).

Thanks, @Evgeni_Popov I understand that keeping track of WebGL global states is tough.
The scene.resetCachedMaterial() again raises the depth issue.

This is an experimental project, and I learned how to better use Babylon with external context. Thanks for your help. I am closing this issue.

Hi all, I am also having similar problems here.

I tried to draw something like background with native WebGL, then draw dynamic 3d scene with babylon. It seems the gl calls will break the Babylon’s rendering states (like binding of buffers / shader programs).

Does Babylon have some kind of reset function like Three.js’s WebGLRenderer.resetState. In three.js this function did exactly the staffs like:

renderLoop = () => {
    // draw with native WebGL calls
    webglRenderer.render(webglScene, webglCamera);
    // draw with Three.js scene
    threeRenderer.resetState();
    threeRenderer.render(threeScene, threeCamera);
    requestAnimationFrame(renderLoop);
}

You can try to call engine.wipeCaches(true) and see if that helps. This doc page shows how PIXI and Babylon.js can work together:

https://doc.babylonjs.com/communityExtensions/Babylon.js+ExternalLibraries/BabylonJS_and_PixiJS

2 Likes

Thanks, Evgeni! The Pixi example is quite helpful. I eventually did it like this:

renderLoop = () => {

    // external webgl renderer
    webglRenderer.reset(); // reset states needed by the external renderer
    webglRenderer.render(webglScene, webglCamera);

    // babylon scene
    engine.wipeCaches(true); // reset states needed by babylon
    babylonScene.render();

    requestAnimationFrame(renderLoop);
}

The engine.wipeCaches(true) will take care of resetting the states needed by Babylon, while the webglRenderer.reset() resets the states needed by Pixi.

Is this implementation logic correct? Each renderer should reset its own states before rendering, when integrating with others.

It seems fine to me!

2 Likes