学习threejs,使用createMultiMaterialObject创建多材质对象

news/2025/2/25 6:03:04

👨‍⚕️ 主页: gis分享者
👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅!
👨‍⚕️ 收录于专栏:threejs gis工程师


文章目录


一、🍀前言

本文详细介绍如何基于threejs在三维场景中使用createMultiMaterialObject创建多材质对象,亲测可用。希望能帮助到您。一起学习,加油!加油!

1.1 ☘️THREE.SceneUtils 场景操控类

THREE.SceneUtils一个用于操控场景的实用类。

方法:
.createMeshesFromInstancedMesh ( instancedMesh : InstancedMesh ) : Group
instancedMesh – 实例化网格。

为给定的实例化网格的每个实例,创建一个包含新网格的新物体组(Object Group)。

.createMeshesFromMultiMaterialMesh ( mesh : Mesh ) : Group
mesh – 具有多种材质的网格。

将给定的多材质网格转换为 Group 的实例,为每种材质保留一个单独的网格。

.createMultiMaterialObject ( geometry : BufferGeometry, materials : Array ) : Group
geometry – 材料集的几何形状。materials – 为物体准备的材料。

创建一个新组,囊括了在材质中定义的每种材质的新网格。请注意,这和为一个网格定义多种材质的材质数组不同。

该方法对于同时需要材质和线框绘制的物体非常有用。

.sortInstancedMesh ( mesh : InstancedMesh, compareFn : Function ) : undefined
mesh – InstancedMesh 将在其中对实例进行排序。

compareFn – 定义排序顺序的比较器函数。

根据用户定义的回调,对 InstancedMesh 中的实例进行排序。回调将提供两个参数,indexA 和 indexB,并且必须返回一个数值。有关排序回调及其返回值的更多信息,请参见 Array.prototype.sort。

由于性能成本高,three.js 不会自动对 InstancedMesh 实例进行排序。手动排序可能有助于改善 alpha 混合材质的显示(从后到前),并减少不透明材质的透支(从前到后)。

MaterialObjectfont_39">1.2 ☘️.createMultiMaterialObject

本例使用createMultiMaterialObject创建多材质对象。实现立方体网格对象既有颜色基础材质,又有MeshDepthMaterial深度材质效果。

MaterialObjectfont_41">二、🍀使用createMultiMaterialObject创建多材质对象

1. ☘️实现思路

  • 1、初始化renderer渲染器,设置renderer的颜色。
  • 2、初始化Scene三维场景scene。
  • 3、初始化camera相机,定义相机位置 camera.position.set,设置相机方向camera.lookAt,设置相机的near、far近远端面。
  • 4、加载几何模型:定义addCube方法,方法内创建随机大小的立方体几何对象cubeGeometry。创建MeshDepthMateria网格深度材质cubeMaterial和MeshBasicMaterial基础材质colorMaterial。传入参数cubeGeometry、cubeMaterial和colorMaterial调用createMultiMaterialObject方法创建多材质对象cube,设置cube第一个网格对象的大小、cube的投影和随机位置,场景scene中添加cube。循环10次调用addCube方法生成多材质对象。定义render方法,实现所有立方体对象的旋转动画。具体代码参考下面代码样例。
  • 5、加入gui控件,控制添加、移除立方体以及立方体颜色、旋转速度等信息。加入stats监控器,监控帧数信息。

2. ☘️代码样例

<!DOCTYPE html>

<html>

<head>
    <title>学习threejs,使用createMultiMaterialObject创建多材质对象</title>
    <script type="text/javascript" src="../libs/three.js"></script>
    <script type="text/javascript" src="../libs/stats.js"></script>
    <script type="text/javascript" src="../libs/dat.gui.js"></script>
    <style>
        body {
            /* set margin to 0 and overflow to hidden, to go fullscreen */
            margin: 0;
            overflow: hidden;
        }
    </style>
</head>
<body>

<div id="Stats-output">
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>

<!-- Js 代码块 -->
<script type="text/javascript">

    // 初始化
    function init() {

        var stats = initStats();

        // 创建三维场景
        var scene = new THREE.Scene();

        // 创建相机
        var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 10, 130);

        // 创建渲染器,设置大小
        var renderer = new THREE.WebGLRenderer();

        renderer.sortObjects = false;

        renderer.setClearColor(new THREE.Color(0x00000, 1.0));
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.shadowMapEnabled = true;

        // 设置相机位置、远近和方向
        camera.position.x = -50;
        camera.position.y = 40;
        camera.position.z = 50;
        camera.near = 7;
        camera.far = 139;
        camera.lookAt(scene.position);

        // 渲染器绑定html页面要素
        document.getElementById("WebGL-output").appendChild(renderer.domElement);
        
        var step = 0;

        var controls = new function () {
            this.cameraNear = camera.near;
            this.cameraFar = camera.far;
            this.rotationSpeed = 0.02;
            this.numberOfObjects = scene.children.length;
            this.color = 0x00ff00;


            this.removeCube = function () {
                var allChildren = scene.children;
                var lastObject = allChildren[allChildren.length - 1];
                if (lastObject instanceof THREE.Mesh) {
                    scene.remove(lastObject);
                    this.numberOfObjects = scene.children.length;
                }
            };

            this.addCube = function () {

                var cubeSize = Math.ceil(3 + (Math.random() * 3));
                var cubeGeometry = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize);

                //var cubeMaterial = new THREE.MeshLambertMaterial({color:  Math.random() * 0xffffff });
                var cubeMaterial = new THREE.MeshDepthMaterial();
                var colorMaterial = new THREE.MeshBasicMaterial({
                    color: controls.color,
                    transparent: true,
                    blending: THREE.MultiplyBlending
                });
                var cube = new THREE.SceneUtils.createMultiMaterialObject(cubeGeometry, [colorMaterial, cubeMaterial]);
                cube.children[1].scale.set(0.99, 0.99, 0.99);
                cube.castShadow = true;

                // 立方体随机位置
                cube.position.x = -60 + Math.round((Math.random() * 100));
                cube.position.y = Math.round((Math.random() * 10));
                cube.position.z = -100 + Math.round((Math.random() * 150));

                // 场景中添加立方体
                scene.add(cube);
                this.numberOfObjects = scene.children.length;
            };

            this.outputObjects = function () {
                console.log(scene.children);
            }
        };

        var gui = new dat.GUI();
        gui.addColor(controls, 'color');
        gui.add(controls, 'rotationSpeed', 0, 0.5);
        gui.add(controls, 'addCube');
        gui.add(controls, 'removeCube');
        gui.add(controls, 'cameraNear', 0, 50).onChange(function (e) {
            camera.near = e;
        });
        gui.add(controls, 'cameraFar', 50, 200).onChange(function (e) {
            camera.far = e;
        });

        var i = 0;
        while (i < 10) {
            controls.addCube();
            i++;
        }

        render();

        function render() {
            stats.update();

            // 立方体旋转动画
            scene.traverse(function (e) {
                if (e instanceof THREE.Mesh) {

                    e.rotation.x += controls.rotationSpeed;
                    e.rotation.y += controls.rotationSpeed;
                    e.rotation.z += controls.rotationSpeed;
                }
            });

            requestAnimationFrame(render);
            renderer.render(scene, camera);
        }

        function initStats() {

            var stats = new Stats();

            stats.setMode(0);

            stats.domElement.style.position = 'absolute';
            stats.domElement.style.left = '0px';
            stats.domElement.style.top = '0px';

            document.getElementById("Stats-output").appendChild(stats.domElement);

            return stats;
        }
    }
    window.onload = init;
</script>
</body>
</html>

效果如下:
在这里插入图片描述


http://www.niftyadmin.cn/n/5865077.html

相关文章

apache-tomcat-6.0.10版本工具资源分享

Apache Tomcat 6.0免安装版本是一款轻量级的Java应用服务器&#xff0c;特别适合于开发和部署Java Servlets和JavaServer Pages&#xff08;JSP&#xff09;应用程序。它以其开源、免费和高效的特点&#xff0c;深受开发者们的喜爱。免安装版本&#xff0c;也称为绿色版&#x…

Python爬虫系列教程之第十五篇:爬取电商网站商品信息与数据分析

大家好&#xff0c;欢迎继续关注本系列爬虫教程&#xff01; 在前面的文章中&#xff0c;我们已经学习了如何构建爬虫、如何应对反爬机制以及如何将数据存储到数据库或文件中。随着业务场景的不断扩展&#xff0c;电商网站的数据采集和分析已成为实际项目中非常重要的一环。 本…

Linux:自定义协议+序列反序列化

我们程序员写的一个个解决我们实际问题, 满足我们日常需求的网络程序, 都是在应用层. 一&#xff0c;再次理解协议 思考1: 我们究竟是如何将数据发送出去的&#xff1f; --------> &#xff08;1&#xff09;我们都知道TCP是双加工的&#xff0c;所以在内核中存在着发送…

每天一个Flutter开发小项目 (3) : 高效Flutter学习与产出 - 构建简易天气应用

引言 欢迎回到 每天一个Flutter开发小项目 系列博客!在前两篇博客中,我们分别构建了计数器应用和待办事项列表应用,相信您已经对Flutter开发有了一定的基础认识。今天,我们将更进一步,探讨如何更高效地学习Flutter,并构建一个更有意思的小项目——简易天气应用。 高效学…

RawShaderMaterial 与 ShaderMaterial

目录 自动添加的 Uniforms 和 Attributes ShaderMaterial RawShaderMaterial GLSL 预处理 ShaderMaterial RawShaderMaterial 使用场景 ShaderMaterial RawShaderMaterial 代码示例对比 使用 ShaderMaterial 使用 RawShaderMaterial 常见问题与注意事项 总结 在 Th…

每日一题之铠甲合体

问题描述 暗影大帝又开始搞事情了&#xff01;这次他派出了 MM 个战斗力爆表的暗影护法&#xff0c;准备一举摧毁 ERP 研究院&#xff01;MM 个暗影护法的战斗力可分别用 B1,⋯,BMB1​,⋯,BM​ 表示。 ERP 研究院紧急召唤了 NN 位铠甲勇士前来迎战&#xff01;每位铠甲勇士都…

【Java 优选算法】模拟

欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 模拟算法的思路比较简单,根据题目描述列出流程,找出规律,将流程转化为代码 替换所有的问号 题目链接 解法 直接根据题目给出条件模拟 示例,找出规律 1.先找出字符?,再…

Android开发数据持久化

Android系统中主要提供了三种方式用于简单的实现数据持久化功能&#xff0c; 分别是&#xff1a;文件存储&#xff0c;SharedPreferences存储以及数据库存储。 文件存储&#xff1a;核心技术就是用Context 类中提供openFileInput()和openFileOutput()方法&#xff0c;之后利用…