Combining Three.js and pixi.js

Recommended Posts

Hi there,

I'm pretty new to pixi and webgl in general and was wondering about something very specific. I'm running through a POC for building up a 3D game (based on Three.js) with all its UI managed by pixi.js
I found a couple of suggestions and ideas: rendering three.js renderer on a background sprite of pixi or output pixis's rendered on a texture that would be attached to a texture of a mesh that would be displayed by Three.js's renderer. The problem that this solutions lead to performance issues.

I pretty easily found an old talking about this (Right Here)  and mainly a person nicknamed "mattdesl" suggested this :


It gets a little tricky since both engines (pixi and ThreeJS) keep track of GL state to minimize redundant calls. This means that they don't play nicely with each other, so you need to reset their flags before starting the renderers.

With new versions of ThreeJS you can use renderer.resetGLState().

In PIXI, it's a bit more complicated. Things like this would be useful to have as a method in WebGLRenderer. These are needed before

    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)

    gl.frontFace( gl.CCW )    
    gl.cullFace( gl.FRONT )
    gl.colorMask(true, true, true, true)

    var shaderManager = session.shaderManager

    shaderManager._currentId = undefined
    for (var i=0; i<shaderManager.attribState.length; i++)
        shaderManager.attribState[i] = false

    var blend = session.blendModeManager.currentBlendMode
    if (blend in PIXI.blendModesWebGL) {
        session.blendModeManager.currentBlendMode = undefined

This allows you to render the UI on top of the 3D scene without any frame buffer switching.

Achieving the blur underneath your UI is significantly more complicated. You would need to:

  • render the 3D scene to a frame buffer
  • enable scissor test and render the blur region(s) with a multi pass blur shader (ping-ponging FBOs etc)
  • then render 2D UI on top

Basically rendering three.js into a frame buffer and then render pixi.js over it. I will have to first render three.js on a framebuffer and pass it to pixi (how can I achiever the latter ?) but mainly my question is about the GL state reset that this quote talk about ! Is this still valid as a concern ? how can I access the blendModeManager and the ShaderManager ?

Thank you for your help guys. I will update you with my progress.

Share this post

Link to post
Share on other sites

Isn't combining PIXI and THREE as simple as this?

var THREE_TEXTURE = PIXI.BaseTexture.fromCanvas(renderer.domElement, PIXI.SCALE_MODES.LINEAR);    // 'renderer.domElement' the view, canvas-element in THREE
var THREE_SPRITE = new PIXI.Sprite.from(new PIXI.Texture(THREE_TEXTURE));
app.stage.addChild(THREE_SPRITE); // 'app.stage': PIXI's stage

Then simply update that PIXI BaseTexture within requestAnimationFrame after THREE rendered its content.. (in that same function)

// all kinds of THREE things

// and then:  

var render = function() {  
    // render the THREE scene, whatever you want... 
    // and this simple thing will update PIXI's baseTexture every frame.

    // course make the RaF loop:



render();  // init it.. 

This works, even on an iPad mini. Can't find anything wrong with it. It keeps running at 60 FPS, even on a heavy project I'm working on.

One canvas element (PIXI's).



Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.