Three.js 正确混合 css3d 和 webgl

2023-12-06

我正在尝试组合 webgl 和 css3d 场景,以便两个场景中的对象正确地混合在一起。我遵循所描述的模式here:

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

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

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

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

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

我将不胜感激任何关于如何解决这些问题的建议。示例代码如下,可以通过放入任何版本的 Three.js 示例文件夹(例如 r61 或 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 对象在平移时消失的问题。

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

工作代码如下:

<!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>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Three.js 正确混合 css3d 和 webgl 的相关文章

  • 电子邮件链接在 Android 上不起作用

    我有 HTML 格式的点击电子邮件链接的代码 它在我的电脑上运行良好 但在移动设备上不起作用 我只有 Android 所以我不知道问题是否仅在 Android 上或所有移动设备上 当我按下链接时 浏览器显示 网页无法显示 邮寄至 电子邮件受
  • 是否可以设置输入文本值的样式?

    我想知道是否可以设置输入框值的样式 such http jsfiddle net aCwhY as
  • jQuery 变量在定义时声称它是未定义的

    我试图在同一页面上有两个自动填充文本框 一个用于手机型号 input1 一个用于固件 input2 当两者都填充时 我希望显示一个带有ID input1input2 的div 但是当在input1 中输入值时 它声称phone 的变量未定义
  • 无法在jspdf中加载多个图像

    我正在尝试加载动态生成的多个图像 我想将这些图像转换为 PDF 格式 HTML 代码如下
  • 重新创建 CSS3 过渡三次贝塞尔曲线

    在 CSS3 过渡中 您可以将计时函数指定为 cubic bezier 0 25 0 3 0 8 1 0 在该字符串中 您仅指定曲线上点 P1 和 P2 的 XY 因为 P0 和 P3 始终分别为 0 0 0 0 和 1 0 1 0 根据苹
  • 重新加载更新的 javascript> 代码而不完全重新加载 html 页面

    我正在开发一个单页 Web 应用程序 它具有许多不同的功能和形式 当开发一个深度 我的意思是主页上没有的 功能时 我会经历这个循环 开发代码 编辑类和函数 刷新整个页面 一路点击 直到到达我需要测试的部分 有时加起来大约一分钟 测试新代码
  • html5 canvas 上的错误显示 lineWidth=1

    I have example https developer mozilla org samples canvas tutorial 4 5 canvas linewidth html https developer mozilla org
  • LESS CSS 语法对现代化很有用

    通常我使用现代化 http modernizr com 了解浏览器的功能 同时 我用LESS CSS http lesscss org 使我的CSS更具可读性和可维护性 使用 LESS 嵌套规则的常见样式如下所示 header color
  • div 中的文本字符有限,添加“阅读更多”链接并在单击链接时显示所有字符

    我有一个 div 里面有文本 使用 PHP 和 MySQL 显示 结构如下 div class description p Here is a lot of text p div 我想在 p 标签内的文本超过 100 个字符时显示 阅读更多
  • CSS3变换:悬停时翻译,带有过渡[重复]

    这个问题在这里已经有答案了 这应该很简单 我的 HTML 中有一堆锚点 如下所示 a href Link 1 a a href Link 2 a a href Link 3 a a href Link 4 a a href Link 5 a
  • 为什么网格项目不居中?

    由于某种原因 两个输入范围使网格中的前两项偏离中心 我假设这是因为它们的影子 DOM 样式 事实真的是这样吗 有谁知道为什么范围使项目 A 和 B 偏离中心 这是一个代码笔 https codepen io tOkyO1 pen QOeKL
  • 在按钮之间添加空间?

    嗨 我这里有一个代码 除了一件事之外 一切都很完美 代码中每个按钮之间没有空格 我尝试过 margin 但不幸的是它是一个无序列表 所以我有点困惑 我将添加或替换什么以在两个按钮之间留出空间 帮助
  • R Shinydashboard 自定义 CSS 到 valueBox

    我一直在尝试将 valueBox 的颜色更改为自定义颜色 超出 validColors 中可用的颜色 但一直无法这样做 我知道有一种方法可以使用标签来包含自定义 CSS 但是我无法将它们放在正确的位置 ui lt dashboardPage
  • 使 Material UI Grid 项目的子项拉伸以适合父容器的剩余高度

    1 现状 我有一个包含 4 个网格项的 Material UI 网格容器 每个 Grid 项中都有一个 Typography 组件 其中包含标题和包含一些内容的 Card 如下所示 2 期望的外观 我希望卡片填充网格项目的剩余高度并且不超过
  • 使用 CSS 覆盖透明 div 中的不透明文本

    我试图使透明 div 内的文本没有不透明度 也就是全黑 div style background 3cc p style background 000 This text should be all black p div 只用 CSS 就
  • 没有类的 CSS 选择器

    我正在使用选择器来选择不具有一个类的所有元素 list th not foo some rules 我怎样才能将其应用到多个班级 list th not foo list th not bar some rules 上面的 CSS 当然不会
  • PHP 共享标头而不使用服务器端脚本?

    到目前为止我总是通过 PHP 解决简单的问题 您有一个包含页眉 菜单 页脚和内容字段的网站 每个页面的页眉 菜单和页脚通常是相同的 在没有 PHP 或任何其他服务器端语言的情况下 如何使页眉 菜单和页脚数据仅存在于一个文件中 例如 您不会有
  • 如何使用 JavaScript 获取元素的填充值?

    我有一个textarea在我的 HTML 中 我需要获取整数或浮点形式的填充数值 以像素为单位 我如何使用 JavaScript 获取它 我没有使用 jQuery 所以我正在寻找纯 JavaScript 解决方案 这将返回padding l
  • 不使用控件时,视频元素在 Chrome 中消失

    So I think这是一个浏览器错误 它出现在一个更复杂的设计 网站中 但我已经进行了很好的尝试 简化了我的代码和设计等 并发现了以下内容 嵌入时
  • 弹出窗口的动态高度取决于内容,可能吗?

    是否有可能获得一个宽度始终为 400px 的弹出窗口 但根据弹出窗口中的内容动态高度 我已经看到了这个 但不知道如何将其应用到弹出窗口 调整 iframe 的宽度高度以适应其中的内容 https stackoverflow com ques

随机推荐