Pixi.js: 结合使用Pixi.js画布和Three.js画布

创建于 2015-01-21  ·  12评论  ·  资料来源: pixijs/pixi.js

嗨,大家好 !

首先,感谢Pixi.js,它是一个很棒的工具,我喜欢! Three.js在2D世界中的完美反击部分。

我正在一个项目中,我想要这样的配置:

  • 使用Pixi.js以完整WebGL编写的2D UI
  • 该2D UI将封装在Three.js编写的3D世界的起源处
  • 然后将在Three.js中使用VR立体相机渲染此3D世界

您将如何继续将Pixi.js Canvas封装在Three.js Canvas中?

谢谢你的时间 !

干杯

伊曼纽尔

🤔 Question

最有用的评论

我编辑帖子是因为ai已经解决了我的问题,我发布了工作代码,以防万一有人遇到相同的问题并需要一个示例。

<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场景中的纹理。

发现! 这就是我们的工作方式!

在2015年1月21日星期三下午4:45,Chad Engler [email protected]
写道:

如果three.js支持将画布作为纹理,则可以将pixi渲染为
屏幕外的画布,并将其用作您Three.js场景中的纹理。

-
直接回复此电子邮件或在GitHub上查看
https://github.com/GoodBoyDigital/pixi.js/issues/1366#issuecomment -70872648

马特·格罗夫斯

_技术合作伙伴_

电话:07708 114496 :: www.goodboydigital.com
E9 5EN伦敦白岗巷皇后区9B单元一楼
好孩子©。 版权所有。

Wahou ...谢谢大家! :)

这就是我所说的快速反馈!

我只是在考虑一个小细节。

我需要能够绘制将在3D世界(Three.js)顶部渲染的2D UI面板(Pixi.js)。
但是,那些2D UI面板具有以下属性很重要。

  • 透明度系数为0-100%的透明度
  • 在背景中模糊3D世界的效果

如果我使用渲染画布的技巧,并将其作为纹理应用。 恐怕将无法实现背景模糊?

我附上一张图片来说明这一点。
transparency

Three.js方面是否模糊? 只需使pixi对象透明,然后根据需要将纹理混合到3D场景中即可。

再次感谢你的帮助 ! 既然您已经说过了……那绝对是最合乎逻辑的道路! :)

干杯

Ë

我编辑帖子是因为ai已经解决了我的问题,我发布了工作代码,以防万一有人遇到相同的问题并需要一个示例。

<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场景的顶部渲染UI,而无需切换任何帧缓冲区。

实现UI下方的模糊要复杂得多。 您需要:

  • 将3D场景渲染到帧缓冲区
  • 启用剪刀测试并使用多遍模糊着色器(ping-poning FBO等)渲染模糊区域
  • 然后在顶部渲染2D UI

感谢您提供的非常准确且有据可查的反馈Matt! :)

因为我是WebGL编程的新手,所以这非常有帮助。
我首先对Mix 2库犹豫不决,特别是被入侵的Three.js可以在某种程度上替代pixi来满足我的需求。

但是出色的范例(2D开发人员的重点)确实说服了我使用pixi进行gl2d调用。

当您看起来也选择了混合方法时,我想它证实了Pixi绝对是使用WebGL绘制2D元素的更有效选择。

干杯

Ë

当您看起来也选择了混合方法时,我想它证实了Pixi绝对是使用WebGL绘制2D元素的更有效选择。

也许会。 在大多数情况下,额外的性能几乎没有意义(您需要多长时间一次设置3000个动画?),而强大的文本呈现,文本输入和滚动事件之类的功能在WebGL中极具挑战性。

最简单的方法就是将DOM / CSS用于UI。 如果您绝对需要选择WebGL(例如,用于某些效果,深度测试等),那么对于2D UI,Pixi可能比ThreeJS容易。

由于似乎已回答,因此将其关闭。

该线程已被自动锁定,因为它关闭后没有任何近期活动。 请为相关错误打开新一期。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

readygosports picture readygosports  ·  3评论

YuryKuvetski picture YuryKuvetski  ·  3评论

zcr1 picture zcr1  ·  3评论

Makio64 picture Makio64  ·  3评论

softshape picture softshape  ·  3评论