Pixi.js: Combinando uma tela Pixi.js e uma tela three.js

Criado em 21 jan. 2015  ·  12Comentários  ·  Fonte: pixijs/pixi.js

Oi pessoal !

Em primeiro lugar, obrigado pelo Pixi.js, é uma ótima ferramenta, adorei! a contrapartida perfeita de three.js para o mundo 2D.

Estou trabalhando em um projeto em que gostaria de ter esta configuração:

  • Uma IU 2D escrita em WebGL completo com Pixi.js
  • Esta IU 2D seria encapsulada na origem de um mundo 3D escrito em Three.js
  • Este mundo 3D seria então renderizado com uma câmera estereoscópica VR em Three.js

Como você procederia para encapsular um Canvas Pixi.js dentro de um Canvas Three.js?

Obrigado pelo seu tempo !

Felicidades

Emmanuel

🤔 Question

Comentários muito úteis

EDITO o post como ai já resolvi meu problema, posto o código de trabalho apenas no caso de alguém acertar o mesmo problema e precisar de um exemplo.

<body>
    <script src="js/pixi.js"></script>
    <script src="js/three.min.js"></script>
    <script>
        width = window.innerWidth;
        height = window.innerHeight;

        //-------------------------------------------------------------------------------------
        // 3D Scene canvas
        //-------------------------------------------------------------------------------------
        var scene_3D = new THREE.Scene();
        scene_3D.fog = new THREE.Fog( "#a1a1a1", 2000, 4000 );

        var camera = new THREE.PerspectiveCamera( 75, width / height, 1, 10000 );
        camera.position.set( 0, 0, 700);
        camera.updateProjectionMatrix();

        var canvas_3D = new THREE.WebGLRenderer( { antialias: true } );
        canvas_3D.setSize( width, height );
        canvas_3D.setClearColor( scene_3D.fog.color, 1 );
        document.body.appendChild( canvas_3D.domElement );

        var geometry = new THREE.BoxGeometry( 500, 500, 500 );
        var material = new THREE.MeshNormalMaterial();
        var cube = new THREE.Mesh( geometry, material );
        cube.position.z = -500;
        cube.rotation.z = -45;
        scene_3D.add( cube );

        //-------------------------------------------------------------------------------------
        // 2D UI canvas
        //-------------------------------------------------------------------------------------
        var scene_UI = new PIXI.Stage( 0x66FF99 );

        var canvas_UI = PIXI.autoDetectRenderer(width, height, {transparent:true});
        canvas_UI.view.style.position = "absolute";
        canvas_UI.view.style.top = "0px";
        canvas_UI.view.style.left = "0px";

        var graphics = new PIXI.Graphics();
        graphics.beginFill( 0xe60630 );
        graphics.moveTo( width/2-200, height/2+100 );
        graphics.lineTo( width/2-200, height/2-100 );
        graphics.lineTo( width/2+200, height/2-100 );
        graphics.lineTo( width/2+200, height/2+100 );
        graphics.endFill();

        scene_UI.addChild( graphics );

        //-------------------------------------------------------------------------------------
        // Map 2D UI canvas on 3D Plane
        //-------------------------------------------------------------------------------------
        var texture_UI = new THREE.Texture( canvas_UI.view );
        texture_UI.needsUpdate = true;

        var material_UI = new THREE.MeshBasicMaterial( {map: texture_UI, side:THREE.DoubleSide } );
        material_UI.transparent = true;

        var mesh_UI = new THREE.Mesh( new THREE.PlaneGeometry(width, height), material_UI );
        mesh_UI.position.set(0,0,0);
        scene_3D.add( mesh_UI );

        //-------------------------------------------------------------------------------------
        // Render Animation
        //-------------------------------------------------------------------------------------
        function animate() {
            requestAnimationFrame( animate );
            canvas_UI.render( scene_UI );

            cube.rotation.y += 0.01;
            canvas_3D.render( scene_3D, camera );
        }
        animate();
    </script>
</body>

Todos 12 comentários

Se three.js oferece suporte a uma tela como textura, você pode renderizar pixi em uma tela fora da tela e usá-la como uma textura em sua cena do three.js.

Spot on! é exatamente assim que fazemos!

Na quarta-feira, 21 de janeiro de 2015 às 4:45 PM, Chad Engler [email protected]
escrevi:

Se three.js suporta uma tela como textura, então você pode renderizar pixi para
uma tela fora da tela e use-a como uma textura em sua cena do three.js.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/GoodBoyDigital/pixi.js/issues/1366#issuecomment -70872648
.

Mat Groves

_ Parceiro Técnico_

Telefone: 07708 114496 :: www.goodboydigital.com
Primeiro andar, Unidade 9B, Queens Yard, White Post Lane, Londres, E9 5EN
goodboy ©. Todos os direitos reservados.

Wahou ... Muito obrigado pessoal! :)

Isso é o que chamo de feedback rápido!

Estou apenas pensando em um pequeno detalhe.

Preciso ter a capacidade de desenhar um painel de interface do usuário 2D (Pixi.js) que será renderizado no topo de um mundo 3D (Three.js).
Mas é importante que esse painel de IU 2D tenha as seguintes propriedades.

  • Transparência com um fator de opacidade de 0-100%
  • Efeito de desfoque do mundo 3D em segundo plano

Se eu usar os truques de renderizar minha tela e aplicá-la como uma textura. Receio que o desfoque do fundo não seja possível?

Anexei uma imagem para ilustrar isso.
transparency

O desfoque do lado do Three.js? Basta tornar o objeto pixi transparente e, em seguida, mesclar a textura em sua cena 3D como quiser.

Obrigado novamente por sua ajuda ! Agora que você disse ... é definitivamente o caminho mais lógico! :)

Felicidades

E

EDITO o post como ai já resolvi meu problema, posto o código de trabalho apenas no caso de alguém acertar o mesmo problema e precisar de um exemplo.

<body>
    <script src="js/pixi.js"></script>
    <script src="js/three.min.js"></script>
    <script>
        width = window.innerWidth;
        height = window.innerHeight;

        //-------------------------------------------------------------------------------------
        // 3D Scene canvas
        //-------------------------------------------------------------------------------------
        var scene_3D = new THREE.Scene();
        scene_3D.fog = new THREE.Fog( "#a1a1a1", 2000, 4000 );

        var camera = new THREE.PerspectiveCamera( 75, width / height, 1, 10000 );
        camera.position.set( 0, 0, 700);
        camera.updateProjectionMatrix();

        var canvas_3D = new THREE.WebGLRenderer( { antialias: true } );
        canvas_3D.setSize( width, height );
        canvas_3D.setClearColor( scene_3D.fog.color, 1 );
        document.body.appendChild( canvas_3D.domElement );

        var geometry = new THREE.BoxGeometry( 500, 500, 500 );
        var material = new THREE.MeshNormalMaterial();
        var cube = new THREE.Mesh( geometry, material );
        cube.position.z = -500;
        cube.rotation.z = -45;
        scene_3D.add( cube );

        //-------------------------------------------------------------------------------------
        // 2D UI canvas
        //-------------------------------------------------------------------------------------
        var scene_UI = new PIXI.Stage( 0x66FF99 );

        var canvas_UI = PIXI.autoDetectRenderer(width, height, {transparent:true});
        canvas_UI.view.style.position = "absolute";
        canvas_UI.view.style.top = "0px";
        canvas_UI.view.style.left = "0px";

        var graphics = new PIXI.Graphics();
        graphics.beginFill( 0xe60630 );
        graphics.moveTo( width/2-200, height/2+100 );
        graphics.lineTo( width/2-200, height/2-100 );
        graphics.lineTo( width/2+200, height/2-100 );
        graphics.lineTo( width/2+200, height/2+100 );
        graphics.endFill();

        scene_UI.addChild( graphics );

        //-------------------------------------------------------------------------------------
        // Map 2D UI canvas on 3D Plane
        //-------------------------------------------------------------------------------------
        var texture_UI = new THREE.Texture( canvas_UI.view );
        texture_UI.needsUpdate = true;

        var material_UI = new THREE.MeshBasicMaterial( {map: texture_UI, side:THREE.DoubleSide } );
        material_UI.transparent = true;

        var mesh_UI = new THREE.Mesh( new THREE.PlaneGeometry(width, height), material_UI );
        mesh_UI.position.set(0,0,0);
        scene_3D.add( mesh_UI );

        //-------------------------------------------------------------------------------------
        // Render Animation
        //-------------------------------------------------------------------------------------
        function animate() {
            requestAnimationFrame( animate );
            canvas_UI.render( scene_UI );

            cube.rotation.y += 0.01;
            canvas_3D.render( scene_3D, camera );
        }
        animate();
    </script>
</body>

Estamos fazendo algo assim em um projeto. Fica um pouco complicado, pois os dois engines (pixi e ThreeJS) controlam o estado GL para minimizar chamadas redundantes. Isso significa que eles não funcionam bem uns com os outros, então você precisa redefinir seus sinalizadores antes de iniciar os renderizadores.

Com as novas versões do ThreeJS, você pode usar renderer.resetGLState() .

No PIXI, é um pouco mais complicado. Coisas como essas seriam úteis como um método no WebGLRenderer. Estes são necessários antes

    gl.disable(gl.DEPTH_TEST)
    gl.enable(gl.BLEND)
    gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
    gl.disable(gl.STENCIL_TEST)
    gl.disable(gl.CULL_FACE)

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

    var shaderManager = session.shaderManager

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

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

Isso permite que você renderize a IU no topo da cena 3D sem qualquer troca de buffer de quadro.

Conseguir o desfoque sob sua IU é significativamente mais complicado. Você precisaria:

  • renderizar a cena 3D em um frame buffer
  • habilite o teste de tesoura e renderize a (s) região (ões) de desfoque com um sombreador de desfoque de várias passagens (ping-ponging FBOs etc)
  • em seguida, renderize a interface do usuário 2D no topo

Obrigado por este feedback muito preciso e documentado Matt! :)

Como eu sou muito novo na programação WebGL, isso é extremamente útil.
Hesitei primeiro em usar a biblioteca Mix 2, especialmente porque um Three.js hackeado pode, de certa forma, substituir o pixi para o que eu preciso.

Mas os exemplos excelentes, o próprio ponto de foco do dev em 2D, realmente me convenceram a usar pixi para chamadas gl2d.

Como você parece ter escolhido uma abordagem Mix também, acho que isso confirma que Pixi é definitivamente uma escolha mais eficiente para desenhar elementos 2D com WebGL.

Felicidades

E

Como você parece ter escolhido uma abordagem Mix também, acho que isso confirma que Pixi é definitivamente uma escolha mais eficiente para desenhar elementos 2D com WebGL.

Bem, talvez. Na maioria dos casos, o desempenho extra é discutível (com que frequência você precisa de 3.000 botões animados ao mesmo tempo?), E coisas como renderização robusta de texto, entrada de texto e eventos de rolagem podem ser incrivelmente desafiadores em WebGL.

O caminho mais fácil é usar DOM / CSS para UI. Se você realmente precisa escolher WebGL (ou seja, para certos efeitos, testes de profundidade, etc), Pixi provavelmente será mais fácil do que ThreeJS para interface de usuário 2D.

Vou fechar isso já que parece respondido.

Este tópico foi bloqueado automaticamente, pois não houve nenhuma atividade recente depois que ele foi fechado. Abra uma nova edição para bugs relacionados.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

pr1ntr picture pr1ntr  ·  25Comentários

tobireif picture tobireif  ·  24Comentários

mreinstein picture mreinstein  ·  39Comentários

doebi picture doebi  ·  30Comentários

KagiJPN picture KagiJPN  ·  24Comentários