Three.js初学(3)

Three.js初学(3)

  • 动画渲染循环
    • 1. 请求动画帧
    • 2. 旋转动画
  • Canvas画布布局和全屏
  • 常见几何体
  • 渲染器设置
  • GUI.js库
    • 1. 库的引入
    • 2. 如何使用
      • 初步调试
      • 进阶调试
      • 界面分组

动画渲染循环

1. 请求动画帧

requestAnimationFrame实现周期性循环执行
requestAnimationFrame默认每秒钟执行60次,但不一定能做到,要看代码的性能,对于部分高刷新率的电脑硬件设备,也是有可能超过60次的。

let i = 0;
function render() {i+=1;console.log('执行次数'+i);requestAnimationFrame(render);//请求再次执行函数render
}
render();

2. 旋转动画

动画说白了就是一张张照片,连起来依次展示,这样就形成一个动画效果,只要帧率高,人的眼睛就感觉不到卡顿,是连续的视频效果。以下案例代码会将几何体沿着y轴旋转。rotateY会影响几何体旋转的速度,你也写成rotateX/Z

// 渲染函数
function render() {renderer.render(scene, camera); //执行渲染操作mesh.rotateY(0.01);//每次绕y轴旋转0.01弧度requestAnimationFrame(render);//请求再次执行渲染函数render,渲染下一帧
}
render();

设置了渲染循环,相机控件OrbitControls就不用再通过事件change执行renderer.render(scene, camera);,毕竟渲染循环一直在执行。

Canvas画布布局和全屏

threejs渲染输出的结果就是一个Cavnas画布,canvas画布也是HTML的元素之一,这意味着three.js渲染结果的布局和普通web前端习惯是一样的。

全屏布局

const width = window.innerWidth; //窗口文档显示区的宽度作为画布宽度
const height = window.innerHeight; //窗口文档显示区的高度作为画布高度
document.body.appendChild(renderer.domElement);

同时要注意全局的css样式设置

<style>body{overflow: hidden;margin: 0px;}
</style>

常见几何体

在这里插入图片描述
three.js的材质默认正面可见,反面不可见,对于矩形平面PlaneGeometry、圆形平面如果你想看到两面,可以设置side: THREE.DoubleSide

new THREE.MeshBasicMaterial({side: THREE.DoubleSide, //两面可见
});

在这里插入图片描述

渲染器设置

渲染器锯齿属性

可以使得渲染的几何体质量更好更清晰一点。

const renderer = new THREE.WebGLRenderer({antialias:true,
});

设置设备像素比

如果你在渲染的过程中需要画布显示不清晰或者模糊的问题

// 获取你屏幕对应的设备像素比.devicePixelRatio告诉threejs,以免渲染模糊问题
renderer.setPixelRatio(window.devicePixelRatio);

设置背景颜色

renderer.setClearColor(0x444444, 1); //设置背景颜色

效果如下图所示:

在这里插入图片描述

GUI.js库

它是一个前端库,对HTML、CSS和JavaScript进行了封装,可以借助dat.gui.js快速创建控制三维场景的UI交互界面。

1. 库的引入

github地址:https://github.com/dataarts/dat.gui

npm地址:https://www.npmjs.com/package/dat.gui

当然threejs官方案例扩展库中也提供了gui.js

// 引入dat.gui.js的一个类GUI
import { GUI } from 'three/addons/libs/lil-gui.module.min.js';

2. 如何使用

初步调试

创建GUI对象

创建完成之后运行,就会发现右上角多了一个交互界面。

// 实例化一个gui对象
const gui = new GUI();

改变GUI界面默认的style属性

//改变交互界面style属性
gui.domElement.style.right = '0px';
gui.domElement.style.width = '300px';

.add()方法

执行gui.add()方法可以快速创建一个UI交互界面,可以用来改变一个JavaScript对象属性的属性值。
格式:.add(控制对象,对象具体属性,其他参数)

//创建一个对象,对象属性的值可以被GUI库创建的交互界面改变
const obj = {x: 30,y: 60,z: 30,
};
// gui界面上增加交互界面,改变obj对应属性
gui.add(obj, 'x', 0, 100); 
gui.add(obj, 'y', 0, 100);
gui.add(obj, 'z', 0, 100);

后面的两个参数,代表着这个拖动条的区间范围数值。但这个时候拖动只有数值变化,几何体位置依然不变,如果想要变化,就将obj对象换成mesh.position或者可以使用onchange方法。

gui.add(mesh.position, 'x', 0, 100);
gui.add(obj, 'x', 0, 100).onChange(function(value){mesh.position.x = value;// 你可以写任何你想跟着obj.x同步变化的代码
});

光照强度的调试

在调试场景渲染效果的时候,比如光照的强度,人大脑的CPU是没有能力通过光照参数算出来模型渲染效果的,一般来说你先大概给一个经验值,然后通过gui在这个大概值的基础上下浮动可视化调试。

// 光照强度属性.intensity
console.log('ambient.intensity',ambient.intensity);
// 通过GUI改变mesh.position对象的xyz属性
gui.add(ambient, 'intensity', 0, 2.0);

ambient是我们之前所设置的环境光,详情可看我的 另一篇博客

进阶调试

.name()方法

在创建的交互界面之后,会默认显示所改变属性的名字,为了通过交互界面更好理解你改变的某个对象属性,可以通过.name()方法改变gui生成交互界面显示的内容。

gui.add(ambient, 'intensity', 0, 100.0).name('环境光强度');
gui.add(pointLight, 'intensity', 0, 10.0).name('点光源强度');
gui.add(directionalLight, 'intensity', 0, 50.0).name('平行光强度');

步长.step()方法

可以设置交互界面每次改变属性值间隔是多少。

gui.add(mesh.position, 'x', 0, 100).name('X轴').step(1.0);
gui.add(mesh.position, 'y', 0, 100).name('Y轴').step(1.0);
gui.add(mesh.position, 'z', 0, 100).name('Z轴').step(1.0);

.addColor()颜色值改变

生成几何体颜色值改变的交互界面。

const obj = {color:0xff0000,
};
// .addColor()生成颜色值改变的交互界面
gui.addColor(obj, 'color').onChange(function(value){mesh.material.color.set(value);
});

.add()方法进阶

之前我们所提到的.add()方法,后面的参数不仅仅可以是数字,还可以是数组,布尔值甚至是对象。

  • 数组
const obj = {scale: 0,
};
// 参数3数据类型:数组(下拉菜单)
gui.add(obj, 'scale', [-100, 0, 100]).name('y坐标').onChange(function (value) {mesh.position.y = value;
});
  • 布尔值
const obj = {bool: false,
};
gui.add(obj, 'bool').name('旋转动画');// 渲染循环
function render() {// 当gui界面设置obj.bool为true,mesh执行旋转动画if (obj.bool) mesh.rotateY(0.01);renderer.render(scene, camera);requestAnimationFrame(render);
}
render();
  • 对象
const obj = {scale: 0,
};
// 参数3数据类型:对象(下拉菜单)
gui.add(obj, 'scale', {left: -100,center: 0,right: 100// 左: -100,//可以用中文// 中: 0,// 右: 100
}).name('位置选择').onChange(function (value) {mesh.position.x = value;
});

界面分组

当GUI交互界面需要控制的属性比较多的时候,为了避免混合,可以适当分组管理,这样更清晰。

通过gui对象的.addFolder()方法可以创建一个子菜单,当你通过GUI控制的属性比较多的时候,可以使用.addFolder()进行分组。

const pos = gui.addFolder("位置");
pos.add(mesh.position, 'x', 0, 100).name('X轴').step(1.0);
pos.add(mesh.position, 'y', 0, 100).name('Y轴').step(1.0);
pos.add(mesh.position, 'z', 0, 100).name('Z轴').step(1.0);const lightFolder = gui.addFolder('光源');
lightFolder.add(ambient, 'intensity', 0, 100.0).name('环境光强度').step(1.0);
lightFolder.add(pointLight, 'intensity', 0, 10.0).name('点光源强度').step(1.0);
lightFolder.add(directionalLight, 'intensity', 0, 50.0).name('平行光强度').step(1.0);

子菜单都可以用代码控制交互界面关闭或开展状态。

gui.close();//关闭菜单
gui.open(); //打开菜单

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/697189.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode | 整数反转 C语言

Problem: 7. 整数反转 文章目录 思路解题方法Code结果 思路 运算部分 while(x > 0) {y x % 10;y * 10;x / 10; } y / 10;对于大于32位的数要用long int类型的变量保存用pow算-2的31次方和2的31次方-1。 解题方法 由思路得 Code int reverse(long int x){long int y …

web前端安全性——iframe安全问题

1、概念 iframe安全问题可称作界面劫持&#xff0c;像点击劫持、拖放劫持、触屏劫持。就是我们的点击&#xff0c;拖放&#xff0c;触屏操作被劫持了&#xff0c;而去操作了其它的透明隐藏的界面。 **原理是利用透明层iframe,使用了CSS中的opacity或z-index等属性&#xff0c;…

快速构建 Debezium MySQL Example 数据库

博主历时三年精心创作的《大数据平台架构与原型实现&#xff1a;数据中台建设实战》一书现已由知名IT图书品牌电子工业出版社博文视点出版发行&#xff0c;点击《重磅推荐&#xff1a;建大数据平台太难了&#xff01;给我发个工程原型吧&#xff01;》了解图书详情&#xff0c;…

突破编程_C++_面试(指针(1))

面试题 1 &#xff1a;什么是空指针&#xff1f; 在 C 中&#xff0c;空指针是一个特殊的指针值&#xff0c;它不指向任何有效的内存地址。空指针通常用于表示指针不指向任何对象或函数。在C11及以后的版本中&#xff0c; nullptr 是表示空指针的推荐方式。 nullptr 是一个指针…

AI绘画与修图:重塑数字艺术的新纪元

文章目录 一、AI绘画与修图的原理二、AI绘画的应用三、AI修图的优势四、面临的挑战五、未来发展趋势《AI绘画与修图实战&#xff1a;PhotoshopFirefly从入门到精通 轻松玩转AI绘画与修图实战》亮点内容简介作者简介 随着人工智能技术的飞速发展&#xff0c;AI绘画与修图已经成为…

如何理解和区分训练集、测试集和验证集

如何理解和区分训练集、测试集和验证集 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】 &#x1f4a1; 创作高质量博文&#xff0c;分享更多关于深度学习、PyTor…

靡语IT:Vue精讲(一)

Vue简介 发端于2013年的个人项目&#xff0c;已然成为全世界三大前端框架之一&#xff0c;在中国大陆更是前端首选。 它的设计思想、编码技巧也被众多的框架借鉴、模仿。 纪略 2013年&#xff0c;在Google工作的尤雨溪&#xff0c;受到Angular的启发&#xff0c;从中提取自…

soc(十七) SOC市场分类

桌面服务器集中式服务器架构和基于ARM微服务器架构的存储差别在哪&#xff1f; http://www.dostor.com/p/54167.html 手机飞行器汽车家庭监控安防路由器

【前端素材】推荐优质后台管理系统Protable平台模板(附源码)

一、需求分析 后台管理系统是一种用于管理和监控网站、应用程序或系统的在线工具。它通常是通过网页界面进行访问和操作&#xff0c;用于管理网站内容、用户权限、数据分析等。当我们从多个层次来详细分析后台管理系统时&#xff0c;可以将其功能和定义进一步细分&#xff0c;…

华为配置CAPWAP双栈覆盖业务示例

配置CAPWAP双栈覆盖业务示例 组网图形 图1 配置CAPWAP双栈覆盖业务示例组网图 业务需求组网需求数据规划配置思路配置注意事项操作步骤配置文件 业务需求 企业用户接入WLAN网络&#xff0c;以满足移动办公的最基本需求。且在覆盖区域内移动发生漫游时&#xff0c;不影响用户的业…

解决 PLC QModbusTcpClient 通信自动断开

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; 例如&#xff1a;项目场景&#xff1a;QModbusTcpClient 通信 问题描述 提示&#xff1a;这里描述项目中遇到的问题&#xff1a; QModbusTcpClient 连接后&#xff0c;稍微停一段时间&#xff0c;就…

LeetCode10. Regular Expression Matching——完全背包

文章目录 一、题目二、题解 一、题目 Given an input string s and a pattern p, implement regular expression matching with support for ‘.’ and ‘*’ where: ‘.’ Matches any single character.​​​​ ‘*’ Matches zero or more of the preceding element. The…

【selenium】三大切换 iframe 弹窗alert 句柄window 和 鼠标操作

目录 一、iframe 1、切换方式&#xff1a; 1、第一种情况&#xff1a; 2、第二种情况&#xff1a; 方式1: 先找到iframe&#xff0c;定位iframe元素&#xff08;可以通过元素定位的各种方式&#xff1a;xpath&#xff0c;css等等&#xff09;&#xff0c;用对象接收&…

MyBatis Plus中的动态表名实践

随着数据库应用的不断发展&#xff0c;面对复杂多变的业务需求&#xff0c;动态表名的处理变得愈发重要。在 MyBatis Plus&#xff08;以下简称 MP&#xff09;这一优秀的基于 MyBatis 的增强工具的支持下&#xff0c;我们可以更便捷地应对动态表名的挑战。本文将深入研究如何在…

美创新一代数据安全管理平台宣传片「龍」重登场

美创新一代数据安全管理平台&#xff08;DSM Cloud&#xff09;产品宣传片 国产化、混合多云环境催生愈加复杂的数据安全防护、管理及可持续运营挑战。 美创新一代数据安全管理平台&#xff08;DSM Cloud&#xff09;&#xff0c;围绕韧性数据安全体系&#xff0c;聚焦全域数据…

[HTML]Web前端开发技术27(HTML5、CSS3、JavaScript )JavaScript基础——喵喵画网页

希望你开心&#xff0c;希望你健康&#xff0c;希望你幸福&#xff0c;希望你点赞&#xff01; 最后的最后&#xff0c;关注喵&#xff0c;关注喵&#xff0c;关注喵&#xff0c;佬佬会看到更多有趣的博客哦&#xff01;&#xff01;&#xff01; 喵喵喵&#xff0c;你对我真的…

activeMq将mqtt发布订阅转成消息队列

1、activemq.xml置文件新增如下内容 2、mqttx测试发送&#xff1a; 主题&#xff08;配置的模糊匹配&#xff0c;为了并发&#xff09;&#xff1a;VirtualTopic/device/sendData/12312 3、mqtt接收的结果 4、程序处理 package comimport cn.hutool.core.date.DateUtil; imp…

ReactNative进阶(二十三)error: no type or protocol named ‘RCTBridgeModule’问题修复

文章目录 一、前言三、拓展阅读 一、前言 Jenkins组包RN技术栈实现的iOS应用时&#xff0c;遇到以下错误提示信息&#xff1a; error: no type or protocol named ‘RCTBridgeModule’ interface RCTEventDispatcher : NSObject <RCTBridgeModule>error: cannot find i…

【AIGC】基于深度学习的图像生成与增强技术

摘要&#xff1a; 本论文探讨基于深度学习的图像生成与增强技术在图像处理和计算机视觉领域的应用。我们综合分析了主流的深度学习模型&#xff0c;特别是生成对抗网络&#xff08;GAN&#xff09;和变分自编码器&#xff08;VAE&#xff09;等&#xff0c;并就它们在实际应用中…

嵌入式linux开发 (三十四) 内存管理2.0(6) 各种段(.code .rodata .data .bss .stack .heap)的含义

我们知道, 逻辑程序在连接的时候在elf 文件中会有 .code .rodata .data 然后在内存中才会有 .code .rodata .data那么为什么链接器在链接生成的elf文件中会有这些段呢?这涉及到链接器的历史问题