Pixi.js: Kombinieren einer Pixi.js-Zeichenfläche und einer three.js-Zeichenfläche

Erstellt am 21. Jan. 2015  ·  12Kommentare  ·  Quelle: pixijs/pixi.js

Hallo Leute !

Zunächst einmal Danke für Pixi.js, es ist ein großartiges Tool, ich liebe es! das perfekte Gegenstück von three.js für die 2D-Welt.

Ich arbeite an einem Projekt, in dem ich diese Konfiguration haben möchte:

  • Eine 2D-Benutzeroberfläche, die in vollständigem WebGL mit Pixi.js geschrieben wurde
  • Diese 2D-Benutzeroberfläche würde am Ursprung einer in Three.js geschriebenen 3D-Welt gekapselt
  • Diese 3D-Welt würde dann mit einer stereoskopischen VR-Kamera in Three.js gerendert

Wie würden Sie vorgehen, um eine Pixi.js-Leinwand in eine Three.js-Leinwand zu kapseln?

Vielen Dank für Ihre Zeit !

Prost

Emmanuel

🤔 Question

Hilfreichster Kommentar

Ich bearbeite den Beitrag, da ich mein Problem gelöst habe. Ich poste den Arbeitscode für den Fall, dass jemand das gleiche Problem hat und ein Beispiel benötigt.

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

Alle 12 Kommentare

Wenn three.js eine Zeichenfläche als Textur unterstützt, können Sie Pixi auf einer Leinwand außerhalb des Bildschirms rendern und diese als Textur in Ihrer three.js-Szene verwenden.

Genau richtig! Genau so machen wir es!

Am Mittwoch, 21. Januar 2015, um 16:45 Uhr, Chad Engler [email protected]
schrieb:

Wenn three.js eine Zeichenfläche als Textur unterstützt, können Sie Pixi in rendern
eine Offscreen-Leinwand und verwenden Sie diese als Textur in Ihrer three.js-Szene.

- -
Antworte direkt auf diese E-Mail oder sieh sie dir auf GitHub an
https://github.com/GoodBoyDigital/pixi.js/issues/1366#issuecomment -70872648
.

Mat Groves

Technischer Partner

Telefon: 07708 114496 :: www.goodboydigital.com
Erster Stock, Einheit 9B, Queens Yard, White Post Lane, London, E9 5EN
goodboy ©. Alle Rechte vorbehalten.

Wahou ... Vielen Dank Jungs! :) :)

Das nenne ich schnelles Feedback!

Ich denke nur an ein kleines Detail.

Ich muss in der Lage sein, 2D-UI-Bedienfelder (Pixi.js) zu zeichnen, die über einer 3D-Welt (Three.js) gerendert werden.
Es ist jedoch wichtig, dass diese 2D-Benutzeroberfläche die folgenden Eigenschaften aufweist.

  • Transparenz mit einem Opazitätsfaktor von 0-100%
  • Unschärfeeffekt der 3D-Welt im Hintergrund

Wenn ich die Tricks des Renderns meiner Leinwand verwende und sie als Textur anwende. Ich fürchte, dass die Unschärfe des Hintergrunds nicht möglich sein wird?

Ich habe ein Bild angehängt, um dies zu veranschaulichen.
transparency

Machen Sie die Unschärfe auf der Three.js-Seite? Machen Sie das Pixi-Objekt einfach transparent und mischen Sie die Textur in Ihre 3D-Szene, wie Sie möchten.

Danke nochmal für deine Hilfe ! Jetzt wo du es gesagt hast ... ist es definitiv der logischste Weg! :) :)

Prost

E.

Ich bearbeite den Beitrag, da ich mein Problem gelöst habe. Ich poste den Arbeitscode für den Fall, dass jemand das gleiche Problem hat und ein Beispiel benötigt.

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

Wir machen so etwas in einem Projekt. Es wird etwas schwierig, da beide Engines (pixi und ThreeJS) den GL-Status verfolgen, um redundante Anrufe zu minimieren. Dies bedeutet, dass sie nicht gut miteinander spielen. Sie müssen daher ihre Flags zurücksetzen, bevor Sie die Renderer starten.

Mit neuen Versionen von ThreeJS können Sie renderer.resetGLState() .

In PIXI ist es etwas komplizierter. Solche Dinge wären nützlich, um sie als Methode in WebGLRenderer zu haben. Diese werden vorher benötigt

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

Auf diese Weise können Sie die Benutzeroberfläche über der 3D-Szene rendern, ohne den Bildpuffer wechseln zu müssen.

Das Erreichen der Unschärfe unter Ihrer Benutzeroberfläche ist erheblich komplizierter. Sie müssten:

  • Rendern Sie die 3D-Szene in einen Bildpuffer
  • Aktivieren Sie den Scherentest und rendern Sie die Unschärfebereiche mit einem Multi-Pass-Unschärfeshader (Ping-Ponging-FBOs usw.).
  • Rendern Sie dann die 2D-Benutzeroberfläche oben

Vielen Dank für dieses sehr präzise und dokumentierte Feedback Matt! :) :)

Da ich ziemlich neu in der WebGL-Programmierung bin, ist dies äußerst hilfreich.
Ich zögerte zuerst mit der Mix 2-Bibliothek, insbesondere, dass ein gehackter Three.js in gewissem Umfang Pixi für das ersetzen kann, was ich brauche.

Aber die hervorragenden Beispiele, der eigentliche Fokus des Entwicklers auf 2D, haben mich wirklich überzeugt, pixi für gl2d-Aufrufe zu verwenden.

Da Sie sich anscheinend auch für einen Mix-Ansatz entschieden haben, bestätigt dies vermutlich, dass Pixi definitiv eine effizientere Wahl für das Zeichnen von 2D-Elementen mit WebGL ist.

Prost

E.

Da Sie sich anscheinend auch für einen Mix-Ansatz entschieden haben, bestätigt dies vermutlich, dass Pixi definitiv eine effizientere Wahl für das Zeichnen von 2D-Elementen mit WebGL ist.

Vielleicht. In den meisten Fällen ist die zusätzliche Leistung umstritten (wie oft müssen 3000 Schaltflächen gleichzeitig animiert werden?), Und Dinge wie robustes Text-Rendering, Texteingabe und Bildlaufereignisse können in WebGL eine unglaubliche Herausforderung darstellen.

Am einfachsten ist es, DOM / CSS für die Benutzeroberfläche zu verwenden. Wenn Sie unbedingt WebGL auswählen müssen (dh für bestimmte Effekte, Tiefenprüfungen usw.), ist Pixi wahrscheinlich einfacher als ThreeJS für 2D-Benutzeroberflächen.

Ich werde das schließen, da es beantwortet zu sein scheint.

Dieser Thread wurde automatisch gesperrt, da nach dem Schließen keine aktuellen Aktivitäten stattgefunden haben. Bitte öffnen Sie eine neue Ausgabe für verwandte Fehler.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

YuryKuvetski picture YuryKuvetski  ·  3Kommentare

SebastienFPRousseau picture SebastienFPRousseau  ·  3Kommentare

softshape picture softshape  ·  3Kommentare

courtneyvigo picture courtneyvigo  ·  3Kommentare

gaccob picture gaccob  ·  3Kommentare