Pixi.js: Combiner un canevas Pixi.js et un canevas three.js

Créé le 21 janv. 2015  ·  12Commentaires  ·  Source: pixijs/pixi.js

Salut les gars !

Tout d'abord Merci pour Pixi.js, c'est un excellent outil, je l'adore! la contrepartie parfaite de three.js pour le monde 2D.

Je travaille sur un projet où je souhaiterais avoir cette configuration:

  • Une interface utilisateur 2D écrite en WebGL complet avec Pixi.js
  • Cette UI 2D serait encapsulée à l'origine d'un monde 3D écrit en Three.js
  • Ce monde 3D serait ensuite rendu avec une caméra stéréoscopique VR dans Three.js

Comment procéder pour encapsuler un canevas Pixi.js dans un canevas Three.js?

Merci pour votre temps !

À votre santé

Emmanuel

🤔 Question

Commentaire le plus utile

J'ÉDITE le message car j'ai résolu mon problème, je poste le code de travail juste au cas où quelqu'un rencontrerait le même problème et aurait besoin d'un exemple.

<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>

Tous les 12 commentaires

Si three.js prend en charge une toile en tant que texture, vous pouvez rendre pixi sur une toile hors écran et l'utiliser comme texture dans votre scène three.js.

Sur place! c'est exactement comment nous le faisons!

Le mercredi 21 janvier 2015 à 16 h 45, Chad Engler [email protected]
a écrit:

Si three.js prend en charge un canevas en tant que texture, vous pouvez rendre pixi en
une toile hors écran et utilisez-la comme texture dans votre scène three.js.

-
Répondez directement à cet e-mail ou affichez-le sur GitHub
https://github.com/GoodBoyDigital/pixi.js/issues/1366#issuecomment -70872648
.

Groves de tapis

_ Partenaire technique_

Téléphone: 07708 114496 :: www.goodboydigital.com
Premier étage, unité 9B, Queens Yard, White Post Lane, Londres, E9 5EN
goodboy ©. Tous les droits sont réservés.

Wahou ... Merci beaucoup les gars! :)

C'est ce que j'appelle la rétroaction rapide!

Je pense juste à un petit détail.

Je dois avoir la possibilité de dessiner un panneau d'interface utilisateur 2D (Pixi.js) qui sera rendu sur Top of a 3D World (Three.js).
Mais il est important que ces panneaux d'interface utilisateur 2D aient les propriétés suivantes.

  • Transparence avec un facteur d'opacité de 0 à 100%
  • Effet de flou du monde 3D en arrière-plan

Si j'utilise les astuces de rendu de ma toile et l'applique en tant que texture. J'ai peur que le flou de l'arrière-plan ne soit pas possible?

J'ai joint une image pour illustrer cela.
transparency

Est-ce que le flou du côté Three.js? Rendez simplement l'objet pixi transparent, puis mélangez la texture dans votre scène 3D comme vous le souhaitez.

Merci encore pour votre aide ! Maintenant que vous l'avez dit ... c'est certainement le chemin le plus logique! :)

À votre santé

E

J'ÉDITE le message car j'ai résolu mon problème, je poste le code de travail juste au cas où quelqu'un rencontrerait le même problème et aurait besoin d'un exemple.

<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>

Nous faisons quelque chose comme ça dans un projet. Cela devient un peu délicat car les deux moteurs (pixi et ThreeJS) gardent une trace de l'état de GL pour minimiser les appels redondants. Cela signifie qu'ils ne jouent pas bien les uns avec les autres, vous devez donc réinitialiser leurs indicateurs avant de démarrer les moteurs de rendu.

Avec les nouvelles versions de ThreeJS, vous pouvez utiliser renderer.resetGLState() .

Dans PIXI, c'est un peu plus compliqué. Des choses comme celles-ci seraient utiles comme méthode dans WebGLRenderer. Ceux-ci sont nécessaires avant

    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)
    }

Cela vous permet de rendre l'interface utilisateur au-dessus de la scène 3D sans aucune commutation de tampon d'image.

Obtenir le flou sous votre interface utilisateur est beaucoup plus compliqué. Vous auriez besoin de:

  • rendre la scène 3D dans un tampon d'image
  • activer le test de ciseaux et rendre la ou les régions de flou avec un shader de flou à passes multiples (FBO de ping-pong, etc.)
  • puis rendre l'interface utilisateur 2D par-dessus

Merci pour ce retour très précis et documenté Matt! :)

Comme je suis assez nouveau dans la programmation WebGL, c'est extrêmement utile.
J'ai d'abord hésité à utiliser la bibliothèque Mix 2, surtout qu'un Three.js piraté peut dans une certaine mesure remplacer pixi pour ce dont j'ai besoin.

Mais les excellents exemples, le point central du développement sur la 2D, m'ont vraiment convaincu d'utiliser pixi pour les appels gl2d.

Comme vous semblez avoir également choisi une approche Mix, je suppose que cela confirme que Pixi est certainement un choix plus efficace pour dessiner des éléments 2D avec WebGL.

À votre santé

E

Comme vous semblez avoir également choisi une approche Mix, je suppose que cela confirme que Pixi est certainement un choix plus efficace pour dessiner des éléments 2D avec WebGL.

Eh bien, peut-être. Dans la plupart des cas, les performances supplémentaires sont inutiles (à quelle fréquence avez-vous besoin de 3000 boutons animés à la fois?), Et des choses comme le rendu de texte robuste, la saisie de texte et les événements de défilement peuvent être incroyablement difficiles dans WebGL.

La voie la plus simple consiste simplement à utiliser DOM / CSS pour l'interface utilisateur. Si vous devez absolument choisir WebGL (c'est-à-dire pour certains effets, tests de profondeur, etc.), Pixi sera probablement plus facile que ThreeJS pour l'interface utilisateur 2D.

Je vais fermer cela car il semble répondu.

Ce thread a été automatiquement verrouillé car il n'y a eu aucune activité récente après sa fermeture. Veuillez ouvrir un nouveau numéro pour les bogues associés.

Cette page vous a été utile?
0 / 5 - 0 notes