让css3d渲染平面充当3JS的底板?

时间:2018-05-30 10:45:07

标签: javascript three.js

我的要求是让css3d渲染平面充当地板。并且三维立方体应位于飞机顶部。下面我附上了我试过的代码。平面和立方体共享相同的场景和相机。但渲染是不同的。但我无法将三维立方体放置在平面上方,平面和立方体的旋转也不同。

    <!DOCTYPE html>
      <html lang="en">
      <head>
      <title>3JS CODE</title>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
      <style>
        body {
            font-family: Monospace;
            background-color: #f0f0f0;
            margin: 0px;
            overflow: hidden;
        }
      </style>
      </head>
      <body>

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

    <script src="js/controls/TrackballControls.js"></script>
    <script src="js/renderers/CSS3DRenderer.js"></script>
    <script src="js/libs/stats.min.js"></script>
    <script>

        var HtmlElement = function ( id, x, y, z, rx ) {
            var div = document.createElement( 'div' );
            div.innerHTML = "Hello";
            div.id = id; //'googleMap';
            div.style.width = '1200px';
            div.style.height = '950px';
            div.style.backgroundColor = 'blue';

            var object = new THREE.CSS3DObject( div );
            object.position.set( x, y, z );
            object.rotation.x = rx;
            return object;
        };

    </script>

    <script>

        var container, stats;
        var camera, controls, mapScene, group, renderer1,renderer2;
        var objects = [];

        init();
        animate();

        function init() {

            container = document.createElement( 'div' );
            document.body.appendChild( container );

            camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 5000 );
            camera.position.z = 1000;
            camera.position.set(0.18348775328760136, -334.5971567493426, 800.8398185862801);



            controls = new THREE.TrackballControls( camera );
            controls.rotateSpeed = 3.0;
            controls.zoomSpeed = 2.2;
            controls.panSpeed = 2.8;
            controls.noZoom = false;
            controls.noPan = false;
            controls.staticMoving = true;
            controls.dynamicDampingFactor = 1.3;


            mapScene = new THREE.Scene();

            // scene.background = new THREE.Color( 0xf0f0f0 );

            group = new THREE.Group();

            var mapObject = new HtmlElement( 'googleMap', 0, 0, 240, 270 );
            group.add( mapObject );


            ///////////////
            var geometry = new THREE.BoxGeometry( 200, 200, 200 );
            for ( var i = 0; i < geometry.faces.length; i += 2 ) {
                    var hex = Math.random() * 0xffffff;
                    geometry.faces[ i ].color.setHex( hex );
                    geometry.faces[ i + 1 ].color.setHex( hex );
            }
            var material = new THREE.MeshBasicMaterial( { vertexColors: THREE.FaceColors, overdraw: 0.5 } );
            cube = new THREE.Mesh( geometry, material );
            cube.position.x = 0;
            cube.position.y = -300;
            cube.position.z = 500;

            group.add( cube );


            mapScene.add( group );

            // renderer
            renderer1 = new THREE.CSS3DRenderer();
            renderer1.setSize( window.innerWidth, window.innerHeight );

            renderer1.domElement.style.position = 'absolute';
            renderer1.domElement.style.top = 0;

            container.appendChild( renderer1.domElement );

            renderer2 = new THREE.WebGLRenderer( { antialias: true } );
            renderer2.setSize( window.innerWidth, window.innerHeight );
            container.appendChild( renderer2.domElement );


            stats = new Stats();
            container.appendChild( stats.dom );

            window.addEventListener( 'resize', onWindowResize, false );

            render();
            // initMap();

        }

        function onWindowResize() {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer1.setSize( window.innerWidth, window.innerHeight );
            renderer2.setSize( window.innerWidth, window.innerHeight );
        }

        function animate() {
            requestAnimationFrame( animate );
            render();
            stats.update();
        }

        function render() {         
            controls.update();
            renderer1.render( mapScene, camera );
            renderer2.render( mapScene, camera );
        }

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

这是输出
here's the output

1 个答案:

答案 0 :(得分:2)

the docs不关心THREE.CSS3DObject的深度缓冲区。它对深度缓冲甚至深度测试都没有任何线索。 CSS对象的顺序可以由WebGLRenderingContext定义 你试图混合两种完全不同的技术,这些技术不会以这种方式相互作用。

但你仍然可以使它发挥作用。

为此,您必须将z-index元素的z-index定义为低于CSS3DRenderer元素的z-index,以便WebGLRenderer绘制“在...之前” CSS3DRenderer。必须为WebGLRenderer

启用进一步的透明度
renderer1 = new THREE.CSS3DRenderer();
renderer1.setSize( window.innerWidth, window.innerHeight );
renderer1.domElement.style.position = 'absolute';
renderer1.domElement.style.zIndex = 0;
renderer1.domElement.style.top = 0;
container.appendChild( renderer1.domElement );

renderer2 = new THREE.WebGLRenderer( { antialias: true, alpha:true } );
renderer2.setSize( window.innerWidth, window.innerHeight );
renderer2.domElement.style.position = 'absolute';
renderer2.domElement.style.zIndex = 1;
renderer2.domElement.style.top = 0;
container.appendChild( renderer2.domElement );

然后您必须确保WebGLRenderer负责CSS3DObject。从技术上讲,这是不可能做到的。但你可以欺骗系统。 您可以渲染一个完全透明的平面,其大小相等,位置与CSS3DObject中的WebGLRenderer相同:

var HtmlElement = function ( id, x, y, z, w, h ) {
    var div = document.createElement( 'div' );
    div.innerHTML = "Hello";
    div.id = id; //'googleMap';
    div.style.width = w + 'px';
    div.style.height = h + 'px';
    div.style.backgroundColor = 'blue';

    var object = new THREE.CSS3DObject( div );
    object.position.set( x, y, z );
    return object;
};

var WebGlObject = function ( x, y, z, w, h ) {
    var material = new THREE.MeshBasicMaterial({
        color: 0x0000000,
        opacity: 0.0,
        side: THREE.DoubleSide
    });
    var geometry = new THREE.PlaneGeometry(w, h);
    var mesh = new THREE.Mesh(geometry, material);
    mesh.position.x = x;
    mesh.position.y = y;
    mesh.position.z = z;
    return mesh;
};

var mapObject = HtmlElement('googleMap', 0, 0, 0, 800, 800);
var planeMesh = WebGlObject(             0, 0, 0, 800, 800);

请参阅示例,该示例基于您的问题代码:

var HtmlElement = function ( id, x, y, z, w, h ) {
    var div = document.createElement( 'div' );
    //div.innerHTML = "Hello";
    div.id = id; //'googleMap';
    div.style.width = w + 'px';
    div.style.height = h + 'px';
    div.style.backgroundColor = 'lightblue';
    div.style.color = "red";
    div.style.fontSize="200px";
    div.style.textAlign="center";
    
    var iframe = document.createElement("iframe");
    iframe.setAttribute("src", "https://www.google.com/maps/embed");
    iframe.style.width = w + "px";
    iframe.style.height = h + "px";
     div.appendChild(iframe);

    var object = new THREE.CSS3DObject( div );
    object.position.set( x, y, z );
    return object;
};

var WebGlObject = function ( x, y, z, w, h ) {
    var material = new THREE.MeshBasicMaterial({
      color: 0x0000000,
      opacity: 0.0,
      side: THREE.DoubleSide
    });
    var geometry = new THREE.PlaneGeometry(w, h);
    var mesh = new THREE.Mesh(geometry, material);
    mesh.position.x = x;
    mesh.position.y = y;
    mesh.position.z = z;
    return mesh;
};

var container, stats;
var camera, controls, mapScene, group, renderer1,renderer2;
var objects = [];

init();
animate();

function init() {

    container = document.createElement( 'div' );
    document.body.appendChild( container );

    camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 5000 );
    camera.position.set(-600, 300, 700);

    controls = new THREE.TrackballControls( camera );
    controls.rotateSpeed = 3.0;
    controls.zoomSpeed = 2.2;
    controls.panSpeed = 2.8;
    controls.noZoom = false;
    controls.noPan = false;
    controls.staticMoving = true;
    controls.dynamicDampingFactor = 1.3;


    mapScene = new THREE.Scene();

    // scene.background = new THREE.Color( 0xf0f0f0 );

    group = new THREE.Group();
    group.renderOrder=1;

    var mapObject = HtmlElement( 'googleMap', 0, 0, 0, 800, 800 );
    var planeMesh = WebGlObject(0, 0, 0, 800, 800);
    group.add( mapObject );

    var geometry = new THREE.BoxGeometry( 200, 200, 200 );
    for ( var i = 0; i < geometry.faces.length; i += 2 ) {
            var hex = Math.random() * 0xffffff;
            geometry.faces[ i ].color.setHex( hex );
            geometry.faces[ i + 1 ].color.setHex( hex );
    }
    var material = new THREE.MeshBasicMaterial( { vertexColors: THREE.FaceColors, overdraw: 0.5 } );
    cube = new THREE.Mesh( geometry, material );
    cube.position.x = 0;
    cube.position.y = 0;
    cube.position.z = 102;

    group.add( cube );
    group.add( planeMesh );
    mapScene.add( group );

    // renderer
    renderer1 = new THREE.CSS3DRenderer();
    renderer1.setSize( window.innerWidth, window.innerHeight );
    renderer1.domElement.style.position = 'absolute';
    renderer1.domElement.style.zIndex = 0;
    renderer1.domElement.style.top = 0;
    container.appendChild( renderer1.domElement );

    renderer2 = new THREE.WebGLRenderer( { antialias: true, alpha:true } );
    renderer2.setSize( window.innerWidth, window.innerHeight );
    renderer2.domElement.style.position = 'absolute';
    renderer2.domElement.style.zIndex = 1;
    renderer2.domElement.style.top = 0;
    container.appendChild( renderer2.domElement );

    window.addEventListener( 'resize', onWindowResize, false );

    render();
}

function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer1.setSize( window.innerWidth, window.innerHeight );
    renderer2.setSize( window.innerWidth, window.innerHeight );
}

function animate() {
    requestAnimationFrame( animate );
    render();
    stats.update();
}

function render() {         
    controls.update();
    renderer2.render( mapScene, camera );
    renderer1.render( mapScene, camera );
}
<script src="https://threejs.org/build/three.min.js"></script>
<!--script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/89/three.min.js"></script-->
<script src="https://threejs.org/examples/js/controls/TrackballControls.js"></script>
<script src="https://threejs.org/examples/js/renderers/CSS3DRenderer.js"></script>