Pixi.js: Объединение холста Pixi.js и холста three.js

Созданный на 21 янв. 2015  ·  12Комментарии  ·  Источник: pixijs/pixi.js

Привет, ребята !

Прежде всего, спасибо за Pixi.js, это отличный инструмент, мне он нравится! идеальная противоположность three.js для 2D-мира.

Я работаю над проектом, в котором хотел бы иметь такую ​​конфигурацию:

  • 2D-интерфейс, полностью написанный на WebGL с помощью Pixi.js
  • Этот 2D-интерфейс будет инкапсулирован в источнике 3D-мира, написанного на Three.js.
  • Затем этот трехмерный мир будет визуализирован стереоскопической камерой VR в Three.js.

Как бы вы приступили к инкапсуляции холста Pixi.js внутри холста Three.js?

Спасибо за ваше время !

Ура

Эммануэль

🤔 Question

Самый полезный комментарий

Я РЕДАКТИРУЮ сообщение, поскольку я решил мою проблему, я публикую рабочий код на случай, если кто-то столкнется с той же проблемой и понадобится пример.

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

Все 12 Комментарий

Если three.js поддерживает холст в качестве текстуры, вы можете визуализировать pixi на внеэкранном холсте и использовать его в качестве текстуры в своей сцене three.js.

Пятно! именно так мы это делаем!

В среду, 21 января 2015 г., в 16:45, Чад Энглер [email protected]
написал:

Если three.js поддерживает холст в качестве текстуры, вы можете визуализировать pixi в
закадровый холст и используйте его как текстуру в своей сцене three.js.

-
Ответьте на это письмо напрямую или просмотрите его на GitHub
https://github.com/GoodBoyDigital/pixi.js/issues/1366#issuecomment -70872648
.

Мэт Гровс

_Технический партнер_

Телефон: 07708 114496 :: www.goodboydigital.com
Первый этаж, блок 9B, Queens Yard, White Post Lane, Лондон, E9 5EN
Goodboy ©. Все права защищены.

Вау ... Большое спасибо, ребята! :)

Это то, что я называю быстрой обратной связью!

Я просто думаю о маленькой детали.

Мне нужно иметь возможность рисовать панель 2D UI (Pixi.js), которая будет отображаться в Top of a 3D World (Three.js).
Но важно, чтобы эта 2D-панель пользовательского интерфейса имела следующие свойства.

  • Прозрачность с коэффициентом непрозрачности от 0 до 100%
  • Эффект размытия 3D-мира на заднем плане

Если я использую приемы рендеринга своего холста и применяю его как текстуру. Боюсь, что размытие фона будет невозможно?

Я прилагаю изображение, чтобы проиллюстрировать это.
transparency

Есть ли размытие на стороне Three.js? Просто сделайте объект pixi прозрачным, а затем смешайте текстуру с вашей 3D-сценой, как хотите.

В очередной раз благодарим за помощь ! Теперь, когда вы это сказали ... это определенно самый логичный путь! :)

Ура

E

Я РЕДАКТИРУЮ сообщение, поскольку я решил мою проблему, я публикую рабочий код на случай, если кто-то столкнется с той же проблемой и понадобится пример.

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

Мы делаем что-то подобное в проекте. Это становится немного сложно, поскольку оба движка (pixi и ThreeJS) отслеживают состояние GL, чтобы минимизировать избыточные вызовы. Это означает, что они плохо взаимодействуют друг с другом, поэтому вам нужно сбросить их флаги перед запуском рендереров.

В новых версиях ThreeJS вы можете использовать renderer.resetGLState() .

В PIXI все немного сложнее. Такие вещи было бы полезно иметь в качестве метода в WebGLRenderer. Это необходимо перед

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

Это позволяет отображать пользовательский интерфейс поверх 3D-сцены без переключения буфера кадра.

Достичь размытия под вашим пользовательским интерфейсом значительно сложнее. Вам необходимо:

  • визуализировать 3D-сцену в буфер кадра
  • включить тест ножниц и визуализировать области размытия с помощью многопроходного шейдера размытия (Ping-ponging FBOs и т. д.)
  • затем визуализируйте 2D UI поверх

Спасибо за очень точный и задокументированный отзыв, Мэтт! :)

Поскольку я новичок в программировании на WebGL, это очень полезно.
Сначала я не решался использовать библиотеку Mix 2, особенно то, что взломанный Three.js может в некоторой степени заменить pixi тем, что мне нужно.

Но превосходные примеры, само внимание разработчиков к 2D, действительно убедили меня использовать pixi для вызовов gl2d.

Поскольку вы, похоже, тоже выбрали подход Mix, я думаю, это подтверждает, что Pixi определенно является более эффективным выбором для рисования 2D-элементов с помощью WebGL.

Ура

E

Поскольку вы, похоже, тоже выбрали подход Mix, я думаю, это подтверждает, что Pixi определенно является более эффективным выбором для рисования 2D-элементов с помощью WebGL.

Что же, может быть. В большинстве случаев дополнительная производительность является спорным (как часто вам нужно 3000 кнопки анимации сразу?), И такие вещи, как надежный рендеринга текста, ввод текста и событий прокрутки может быть невероятно сложной в WebGL.

Самый простой способ - просто использовать DOM / CSS для пользовательского интерфейса. Если вам абсолютно необходимо выбрать WebGL (например, для определенных эффектов, тестирования глубины и т.д.), то Pixi, вероятно, будет проще, чем ThreeJS для 2D-интерфейса.

Собираюсь закрыть это, поскольку кажется, что ответ.

Этот поток был автоматически заблокирован, поскольку после его закрытия в последнее время не было никаких действий. Пожалуйста, откройте новую проблему для связанных ошибок.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги