三.js 正确混合 css3d 和 webgl [英] three.js properly blending css3d and webgl

查看:14
本文介绍了三.js 正确混合 css3d 和 webgl的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试结合 webgl 和 css3d 场景,以便两个场景中的对象正确融合在一起.我正在遵循 here:

I am trying to combine webgl and css3d scenes so that the objects in the two scenes properly blend together. I am following the pattern described here:

并通过修改three.js示例css3d_sandbox.html创建了一个简单的示例.

and have created a simple example by modifying the three.js example css3d_sandbox.html.

在我的版本中,我向 webGl 场景添加了一个立方体,并希望它能够与现有平面正确融合,无论该立方体是在这些对象的前面还是后面.

In my version I have added a cube to the webGl scene and expect it to properly blend with the existing planes whether the cube is in front of or behind those objects.

我注意到两个异常.第一个是,一旦添加了立方体,平面就会在您四处平移时消失在意想不到的位置,就好像远平面和近平面的值没有得到正确遵守,或者对象被错误地确定为位于其他物体的后面.

I notice two anomalies. The first is that once the cube is added the planes disappear in unexpected positions as you pan around as if the far and near plane values are not being honored correctly or the objects are being incorrectly determined to be behind something else.

第二个问题是 css3d 对象在针对 Three.js r67 运行时根本不渲染,但在针对 r61 运行时会渲染.我尝试用 r61 替换 r67 版本的 CSS3DRenderer.js,但仍然没有看到任何 css3d 对象.

The second issue is that the css3d objects do not render at all when running against three.js r67, but they do render when running against r61. I tried replacing the r67 version of CSS3DRenderer.js with r61, but still do not see any css3d objects.

在 r67 中,当将 webGl dom 添加为 css3d dom 的子项的行被注释掉时,css3d 对象确实会出现.

In r67 when the line to add the webGl dom as a child of the css3d dom is commented out, the css3d objects do appear.

如果您就如何解决这些问题提出任何建议,我将不胜感激.示例代码如下,可以通过放入任何版本的 Three.js 示例文件夹(例如 r61 或 r67)来运行.

I would appreciate any suggestions on how to resolve these issues. Sample code is below and may be run by dropping into any version of the three.js examples folder (e.g. r61 or r67).

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <style>
            body {
                background-color: #ffffff;
                margin: 0;
                overflow: hidden;
            }
            #info {
                position: absolute;
                top: 0px;
                width: 100%;
                color: #000000;
                padding: 5px;
                font-family: Monospace;
                font-size: 13px;
                text-align: center;
                z-index: 1;
            }

            a {
                color: #000000;
            }

        </style>
    </head>
    <body>
        <div id="info"><a href="http://threejs.org" target="_blank">three.js</a> - css3d sandbox</div>

        <script src="../build/three.min.js"></script>

        <script src="js/controls/TrackballControls.js"></script>

        <!--<script src="js/renderers/CSS3DRenderer-r61.js"></script>-->
        <script src="js/renderers/CSS3DRenderer.js"></script>

        <script>

            var camera, sceneGl, rendererGl;

            var sceneCss, rendererCss;

            var controls;

            init();
            animate();

            function init() {

                camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
                camera.position.set( 200, 200, 200 );

                controls = new THREE.TrackballControls( camera );

                sceneGl = new THREE.Scene();
                sceneCss = new THREE.Scene();

                var material = new THREE.MeshBasicMaterial( { color: 0x000000, opacity : 0.0 } );
                material.blending  = THREE.NoBlending;

                //
                var xpos = [50, -10, 30, 70, 110];
                var ypos = [60, -40, 0, 40, 80];
                var zpos = [-30, -50, 0, 50, 100];

                for ( var i = 0; i < 5; i ++ ) {

                    var element = document.createElement( 'div' );
                    element.style.width = '100px';
                    element.style.height = '100px';
                    element.style.opacity = 1.0;
                    element.style.background = new THREE.Color( Math.random() * 0xffffff ).getStyle();

                    var object = new THREE.CSS3DObject( element );
                    object.position.x = xpos[i];
                    object.position.y = ypos[i];
                    object.position.z = zpos[i];
                    object.rotation.x = Math.PI/(i + 5);
                    object.rotation.y = Math.PI/(21 - 2 * i);
                    object.rotation.z = Math.PI/(3 * i + 25);
                    object.scale.x = i/12 + 0.5;
                    object.scale.y =  1/ (12 - i) + 0.5;
                    sceneCss.add( object );


                    var geometry = new THREE.PlaneGeometry( 100, 100 );
                    var mesh = new THREE.Mesh( geometry, material );
                    mesh.position.copy( object.position );
                    mesh.rotation.copy( object.rotation );
                    mesh.scale.copy( object.scale );
                    sceneGl.add( mesh );

                }


                //
                var boxGeom = new THREE.CubeGeometry( 60, 60, 60 );

                var cubeMaterial = new THREE.MeshBasicMaterial( 
                    { color: 0x05009A, shading : THREE.FlatShading, side: THREE.FrontSide } );

                var cube = new THREE.Mesh( boxGeom, cubeMaterial );
                cube.position.copy(  new THREE.Vector3(100, 75, 50) );
                cube.rotation.copy( Math.PI/ 6 );

                sceneGl.add( cube );


                rendererCss = new THREE.CSS3DRenderer();
                rendererCss.setSize( window.innerWidth, window.innerHeight );
                rendererCss.domElement.style.position = 'absolute';
                rendererCss.domElement.style.top = 0;

                rendererGl = new THREE.WebGLRenderer();
                rendererGl.setClearColor( 0xf0f0f0 );

                rendererGl.setSize( window.innerWidth, window.innerHeight );

                rendererGl.domElement.style.position    = 'absolute';
                rendererGl.domElement.style.zIndex = 1;
                rendererGl.domElement.style.top = 0;
                rendererCss.domElement.appendChild( rendererGl.domElement );

                document.body.appendChild( rendererCss.domElement );

            }

            function animate() {

                requestAnimationFrame( animate );

                controls.update();

                rendererGl.render( sceneGl, camera );
                rendererCss.render( sceneCss, camera );

            }

        </script>
    </body>
</html>

这是带有代码的 fiddle.

推荐答案

评论中的链接很有帮助.正如该解决方案所述,将 alpha 设置为 true 可以解决使用 r67 渲染 css3d 对象的问题.使webGl背景透明,解决了平移时css3d对象消失的问题.

The link in the comment was helpful. As that solution mentions, setting alpha to true solves the issue of getting the css3d objects to render using r67. Making the webGl background transparent solves the problem of the css3d objects disappearing when panning around.

然而,链接中提到的解决方案将 webgl 和 css3d dom 添加为文档的子元素.这种方法在我的情况下不起作用.我发现仍然有必要将 webgl dom 作为 css3d dom 的子项,以便立方体在这些对象的前面和后面时与平面正确混合.

The solution mentioned in the link however adds both the webgl and css3d dom as child elements of the document. This approach did not work in my case. I find it necessary to still have the webgl dom as a child of the css3d dom for the cube to blend correctly with the planes when it is both in front of and behind those objects.

以下工作代码:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <style>
            body {
                background-color: #ffffff;
                margin: 0;
                overflow: hidden;
            }

        </style>
    </head>
    <body>

        <script src="../build/three.min.js"></script>

        <script src="js/controls/TrackballControls.js"></script>

        <script src="js/renderers/CSS3DRenderer.js"></script>

        <script>

        var camera, sceneGl, rendererGl;
var sceneCss, rendererCss;
var controls;

init();
animate();

function init() {

    camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
    camera.position.set(200, 200, 200);

    controls = new THREE.TrackballControls(camera);

    sceneGl = new THREE.Scene();
    sceneCss = new THREE.Scene();

    var material = new THREE.MeshBasicMaterial({
        color: 0x000000,
        opacity: 0.0,
        side: THREE.DoubleSide
    });

    var xpos = [50, -10, 30, 70, 110];
    var ypos = [60, -40, 0, 40, 80];
    var zpos = [-30, -50, 0, 50, 100];

    for (var i = 0; i < 5; i++) {

        var element = document.createElement('div');
        element.style.width = '100px';
        element.style.height = '100px';
        element.style.opacity = 1.0;
        element.style.background = new THREE.Color(Math.random() * 0xff0000).getStyle();

        var object = new THREE.CSS3DObject(element);
        object.position.x = xpos[i];
        object.position.y = ypos[i];
        object.position.z = zpos[i];
        object.rotation.x = Math.PI / (i + 5);
        object.rotation.y = Math.PI / (21 - 2 * i);
        object.rotation.z = Math.PI / (3 * i + 25);
        object.scale.x = i / 12 + 0.5;
        object.scale.y = 1 / (12 - i) + 0.5;
        sceneCss.add(object);


        var geometry = new THREE.PlaneGeometry(100, 100);
        var mesh = new THREE.Mesh(geometry, material);
        mesh.position.copy(object.position);
        mesh.rotation.copy(object.rotation);
        mesh.scale.copy(object.scale);
        sceneGl.add(mesh);

    }


    var boxGeom = new THREE.CubeGeometry(60, 60, 60);

    var cubeMaterial = new THREE.MeshBasicMaterial({
        color: 0x05009A,
        shading: THREE.FlatShading,
        side: THREE.DoubleSide
    });

    var cube = new THREE.Mesh(boxGeom, cubeMaterial);
    cube.position.copy(new THREE.Vector3(100, 75, 50));
    cube.rotation.copy(Math.PI / 6);

    sceneGl.add(cube);


    rendererCss = new THREE.CSS3DRenderer();
    rendererCss.setSize(window.innerWidth, window.innerHeight);
    rendererCss.domElement.style.position = 'absolute';
    rendererCss.domElement.style.top = 0;

    rendererGl = new THREE.WebGLRenderer({alpha:true});
    rendererGl.setClearColor(0x00ff00, 0.0);

    rendererGl.setSize(window.innerWidth, window.innerHeight);

    rendererGl.domElement.style.position = 'absolute';
    rendererGl.domElement.style.zIndex = 1;
    rendererGl.domElement.style.top = 0;
    rendererCss.domElement.appendChild(rendererGl.domElement);

    document.body.appendChild(rendererCss.domElement);

}

function animate() {

    requestAnimationFrame(animate);

    controls.update();

    rendererGl.render(sceneGl, camera);
    rendererCss.render(sceneCss, camera);

}
        </script>
    </body>
</html>

这篇关于三.js 正确混合 css3d 和 webgl的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆