ThreeJS 炫酷特效旋转多面体Web页 Demo 01《ThreeJS 炫酷特效制作》

news2024/11/25 8:21:28

本案例为一个 threejs 的特效网页,大小球体进行包裹,外球体为透明材质,但是进行了线框渲染,使其能够通过外球踢查看其内球体。
注:案例参考源于互联网,在此做代码解释,侵删
本案例除 ThreeJS 外不适用任何第三方框架,放心食用
懒的同学可以直接下载代码,打赏作者一根精神食粮:https://download.csdn.net/download/A757291228/15728369

请添加图片描述
这是 inscode 的代码,不过渲染有点问题,不过也可以看到大致效果:

一、ThreeJS 三要素

在编写 ThreeJS 前,需要明白 ThreeJS 的三个要素,若对建模、游戏有过了解的同学在学习 ThreeJS 时对知识点理解会更容易接受。

在 ThreeJS 中有三个很关键的对象,分别是 摄像头、场景以及渲染器:

  • 其中 场景 是通过 ThreeJS “搭建”呈现特效的一个“舞台”,创建好一个场景后,即可往这个场景中添加对应的多种物体,例如多边形、粒子、球体等;
  • 创建好场景后我们需要在场景中添加摄像头用于呈现场景中的视觉效果,摄像头在 ThreeJS 中担任 “视觉采集”
    角色,可以通过控制摄像头采集范围(大小)从而采集场景中视觉呈现;
  • 那么完成以上两步后,还需要对场景进行渲染,只有渲染过后才能进行视觉效果的呈现。

可以想象场景为一个场地,摄像头为一个摄像头,渲染器就是渲染器,然后拍成了一段视频或照片。

二、代码中创建三要素

2.1 创建 html

首先创建一个 html 文件,并且引入 CSS 与 JS 文件:

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>1_bit ThreeJS 炫酷旋转多面体Web页 Demo</title>
	<link rel="stylesheet" href="./style.css">
</head>

<body>
	<div id="canvas"></div>
	<script src='three.min.js'></script>
	<script src="./1bitDemo.js"></script>
</body>

</html>

在此需要注意,在 body 元素中添加了一个 div 并且 id 为 canvas,该 div 是为了之后在 js 代码中对应这个 div 添加渲染好的元素;除此之外还引入了 three.min.js 依赖,另外一个 js 名为 1bitDemo.js 是我们等下须编写的 js 文件代码。

2.2 css 编写

编写完 html 代码后,创建一个 style.css 文件用于给 html 添加一些基本样式,html 设置背景色,并且给与一个线性渐变,方向向下,随后给与 margin 为0,使其页面边缘贴合,代码过于简单在此不再赘述,css 如下:

html {
  width: 100%;
  height: 100%;
  background: linear-gradient(to bottom, #11e8bb 0%, #8200c9 100%);
  overflow: hidden;
}

body {
  margin: 0;
  padding: 0;
}

此时页面如下:
在这里插入图片描述

2.3 创建三要素

接着做完准备工作后,创建一个 js 文件,在此我的 js 文件名为 1bitDemo.js ,在其中我们将创建 场景、渲染器、摄像头。

由于我们为了一打开页面就进行渲染,所以在此需要创建一个 onload 事件:

window.onload = function () {
	
}

接着创建对应的对象存储三要素(渲染器、场景、摄像头):

var renderer, scene, camera;

渲染器

我们在此先创建渲染器,通过调用 THREE 对象的 WebGLRenderer 对摄像头进行创建,WebGLRenderer 方法接收传入一个渲染器的配置项对象,例如代码为:

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

此时传入的配置项:

  • antialias 表示抗锯齿打开,使几何体边缘平滑;
  • alpha 表示渲染器渲染时的画面有透明通道,若不打开将不会存在透明通道,例如 png 图片与 jpg 区别;

接着配置渲染器的渲染大小:

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

以上代码中 setSize 方法用于设置渲染器渲染大小,通过 window.innerWidthwindow.innerHeight 传入渲染宽高。

此时就可以通过 js 获取到 canvas 元素,从而添加渲染器到 canvas 窗口即可:

document.getElementById('canvas').appendChild(renderer.domElement);

以上代码中 renderer.domElement 是得到渲染器渲染出的 canvas。

场景

场景创建很简单,通过 THREEScene 方法即可创建:

scene = new THREE.Scene();

摄像头

接着创建摄像头,透视摄像头创建使用 PerspectiveCamera 方法,代码如下:

camera = new THREE.PerspectiveCamera(100, window.innerWidth / window.innerHeight, 1, 1000);

PerspectiveCamera 方法接收 4 个参数,分别为:

  • 相机可视垂直视野角度(玩过FPS的应该知道有一个视野角度)
  • 相机可视长宽比
  • 相机近端距离
  • 相机远端距离

其中:

  • 相机近端距离为 相机到场景中最近可视物体的距离
  • 相机远端距离为 相机到场景中最远的可视物体的距离

若可视物体小于了 相机近端距离 和 大于了 相机远端距离 都会不可见。

接着我们此时可以移动一下摄像机的 z 轴,代码为:

camera.position.z = 500;

以下为 three 中的坐标系参考图:

在这里插入图片描述

此时 z 轴就是摄像机,或者说人的视窗所距离中心点的位置,若不移动这个距离,在创建几何体时将会无法很好的看见几何体,因为默认位置为这个坐标系的中心点。

最后将这个摄像机添加到场景中即完成三要素创建:

scene.add(camera);

三、几何体创建

3.1 创建二十面缓冲几何体

此时我们创建 2 个二十面的几何体,直接通过 IcosahedronGeometry 方法即可创建,代码为:

var geom = new THREE.IcosahedronGeometry(7, 1);
var geom2 = new THREE.IcosahedronGeometry(15, 1);

以上代码中 IcosahedronGeometry 接受两个参数,分别为:

  • radius 二十面体的半径,默认为1;
  • detail 设置面角,默认为0,值超过1则是球体,超过0小于1则会增加顶点使其转变成非二十面几何体;

3.2 创建二十面体的显示样式

在 three 中要为 二十面体创建显示的样式需要创建材质(Material),在此我们要创建一种可以用来模拟物体表面反射光线的亮度和光滑度的材质,需要通过 MeshPhongMaterial 进行创建,随后在 MeshPhongMaterial 方法中传入对应的配置项即可:

var mat = new THREE.MeshPhongMaterial({
	color: 0xffffff,
	shading: THREE.FlatShading
});
var mat2 = new THREE.MeshPhongMaterial({
	color: 0xffffff,
	wireframe: true,
	side: THREE.DoubleSide
});

以上代码中的配置项对象值:

  • color 表示颜色;
  • shading 表示网格的渲染方式(之后要使用的网格),在此使用
    FlatShading,表示使用平面着色来渲染网格,渲染的网格将会扁平化;
  • wireframetrue 表示渲染的网格将会呈现线框形式
  • side 设置为 THREE.DoubleSide
    表示双面渲染,即渲染的时候物体双面都会进行渲染,而不是只有一面(性能考虑若想设置只渲染一面设置为 THREE.FrontSide

3.3 创建 Mesh 用于组装 3D 对象

Mesh 在 ThreeJS 的 3D 对象中是必要的,通过 创建 Mesh 组合 3D 对象,创建 Mesh 需要指定对应的几何体以及材质,如以下代码:

var planet = new THREE.Mesh(geom, mat);

其中 geom 为之前所创建的几何体,mat 为之前所创建的材质。

随后我们需要对这个几何体 planet 进行缩放大小显示,在此放大 16 倍:

planet.scale.x = planet.scale.y = planet.scale.z = 16;

接下来我们需要创建一个 Object3D 用于存放这个几何体,通过 Object3D 我们可以方便的对 完整的几何体进行 缩放、移动等。

var center = new THREE.Object3D();
center.add(planet);
scene.add(center);

以上代码中创建了一个 cente rObject3D 对象,把创建好的几何体 planet 添加到 center 中,再把 center 添加到 scene 场景中即可。

渲染

此时若想查看页面是什么样,可以在末尾直接通过渲染器调用 render 方法进行渲染即可,render 方法需要传入场景和摄像头对象,此时代码为:

renderer.render(scene, camera)

但此时渲染出来的画面是黑色的:

在这里插入图片描述

原因是场景中没有添加光源,所以暗淡无光,接下来我们创建光源,但在此之前,我们刚刚创建了两个 MeshPhongMaterial 材质和 IcosahedronGeometry 二十面体对象,我们在此只实现了一个对象的 mesh,我们此时再完成另一个 IcosahedronGeometry mesh 的创建,并且创建 Object3D 对象进行存放:

var planet2 = new THREE.Mesh(geom2, mat2);
planet2.scale.x = planet2.scale.y = planet2.scale.z = 10;
outside = new THREE.Object3D();
outside.add(planet2);
scene.add(outside);

3.4 创建光源

在此我们创建环境光,创建环境光通过方法 AmbientLight,AmbientLight 方法传入环境光颜色即可:

var ambientLight = new THREE.AmbientLight(0x999999);
scene.add(ambientLight);

此时刷新界面如下:

在这里插入图片描述
此时我们还需要创建其他的太阳光。太阳光通过 DirectionalLight 进行创建,是一种平行光,并不会随距离而衰减。DirectionalLight 接受两个参数,一个是光照颜色一个是光照强度,光照强度默认为 1:

var lights1 = new THREE.DirectionalLight(0xffffff, 1);
lights1.position.set(1, 0, 0);
var lights2 = new THREE.DirectionalLight(0x11E8BB, 1);
lights2.position.set(0.75, 1, 0.5);
var lights3 = new THREE.DirectionalLight(0x8200C9, 1);
lights3.position.set(-0.75, -1, 0.5);
scene.add(lights1);
scene.add(lights2);
scene.add(lights3);

刷新界面重新渲染此时界面如下:
在这里插入图片描述

3.5 创建环境物体

接着开始创建环境物体,首先依照惯例创建一个 3D 容器,并且将这个容器添加到场景中:

particle = new THREE.Object3D();
scene.add(particle);

接着创建一个四面体(第一个参数已经就是半径,第二个参数与二十面体一致):

var geometry = new THREE.TetrahedronGeometry(2, 0);

随后创建材质(与之前一致不再赘述):

var material = new THREE.MeshPhongMaterial({
	color: 0xffffff,
	shading: THREE.FlatShading
});

由于环境物体较多,在此直接使用for 循环进行循环创建:

for (var i = 0; i < 1000; i++) {
	var mesh = new THREE.Mesh(geometry, material);
	mesh.position.set(Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5).normalize();
	mesh.position.multiplyScalar(90 + (Math.random() * 700));
	mesh.rotation.set(Math.random() * 2, Math.random() * 2, Math.random() * 2);//旋转

	particle.add(mesh);
}

以上代码中首先创建了一个 mesh,随后 通过 mesh.position.set 设置其 x y z 的坐标,接着通过 multiplyScalar 方法对坐标进行放大,此时放大后将会使整体创建的 mesh 位置进行扩大,远离中心点,这样就可以使这些创建的物体发散到其他位置,最后在通过 mesh.rotation.set 设置他们的旋转角度,使创建的物体旋转方向发生改变,否则都是一个面反光并不是很好看,太单一了,最后添加到 particle 即可完成。

此时页面效果如下:
在这里插入图片描述

为啥看起来球那么小?其实大家可以调整视角大小以及远端距离可以拉近与物体的距离,在此我把摄像头视觉方位调成70:

camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);

此时呈现效果确实变大了:
在这里插入图片描述
最后就是完成动画,使其旋转。

3.6 animation 动画

做过 unity 的同学应该很清楚,只需要每帧更改其位置即可,那么此时我们创建一个 animate 方法,设置其 Object3D 对象的 rotation 即可:

function animate() {
	requestAnimationFrame(animate);

	particle.rotation.x += 0.0010;
	particle.rotation.y -= 0.0040;
	inside.rotation.x -= 0.0020;
	inside.rotation.y -= 0.0030;
	outside.rotation.x -= 0.0010;
	outside.rotation.y += 0.0020;
	renderer.clear();

	renderer.render(scene, camera)
};

以上方法中 requestAnimationFrame 为一个循环函数,传入对应的函数名即可重复执行,在此处我们只需要把 这个 animate 函数放到 onload 事件最后一行代码即可,并且删除 onload 中的 renderer 的 render 方法,因为在此处已经写有。

以上代码中的 renderer.clear(); 为清理渲染器的缓存,准备下一次渲染,一般在场景重绘前调用即可,当然 clear 可以指定清理不同的缓冲区,同学们可以之后在了解一下。

以上 animate 方法已经写好了,但是注意 renderer, scene, camera, inside, outside, particle 这些变量需要设置为全局变量,否则调用不到。

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

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

相关文章

Kafka原理

生产者原理解析 生产者工作流程图&#xff1a; 一个生产者客户端由两个线程协调运行&#xff0c;这两个线程分别为主线程和 Sender 线程 。 在主线程中由kafkaProducer创建消息&#xff0c;然后通过可能的拦截器、序列化器和分区器的作用之后缓存到消息累加器&#xff08;Rec…

uniApp 页面通讯统一解决方案

文章目录 往期回顾统一解决方案uni.on和eventChannel之间的选择如何设置触发器最终范例距离 往期回顾 uniapp 踩坑记录 uni.$on为什么不能修改data里面的数据 uniApp页面通讯大汇总&#xff0c;如何页面之间传值 统一解决方案 uni.on和eventChannel之间的选择 uni.on和eve…

61082-041502PLF(0.80mm)40 位置 连接器 插座,G846A050210T1HR 集管和线壳 WTB 1.00 PITCH

61082-041502PLF&#xff08;0.80mm&#xff09;FCI紧凑型Bergstak连接器提供广泛的堆叠高度和电路尺寸&#xff0c;以支持广泛的夹层&#xff0c;板堆叠通信&#xff0c;数据和工业应用。 连接器类型&#xff1a;插座&#xff0c;外罩触点 针位数&#xff1a;40 间距&#xff…

浅谈互联网搜索之召回

一、背景 在搜索系统中&#xff0c;一般会把整个搜索系统划分为召回和排序两大子系统。本文会从宏观上介绍召回系统&#xff0c;并着重介绍语义召回。谨以此文&#xff0c;希望对从事和将要从事搜索行业的工作者带来一些启发与思考。 二、搜索系统召回方法 不同于推荐系统&…

6月6号软件资讯更新合集......

Yao 0.10.3 正式发布&#xff0c;拥抱 AIGC 时代&#xff01; ChatGPT 解锁了新的人机交互方式&#xff0c;人类可以与电脑直接交流了&#xff01;AIGC 时代已经到来&#xff0c;万千应用正在升级或重构&#xff0c;Yao 提供了一个开箱即用的解决方案&#xff0c;可以快速开发…

迷茫了3年:做完这个测试项目,我终于决定辞职!

2023年早已过半&#xff0c;来个迟到的年中总结&#xff0c;说实话&#xff0c;2023&#xff0c;很迷茫&#xff0c;然后过的非常不如意&#xff0c;倒不是上一年的职业目标没达到&#xff0c;而是接下来的路根本不知道如何走。在没解决这个问题之前&#xff0c;或者说没搞清楚…

Web3.0概念

学习web3您需要先掌握 JavaScript node React 后续 我们将学习一门新的语言 叫 Solidity 他是一种只能合约语言开发 我们利用web3将不再依赖后端 而是连接只能合约开发 首先 我们先不用急着写代码 还是要概念为先 首先 我们来对比 WEB1.0到3.0的概念 首先 web1.0 更多处于信…

AI实战营第二期——第一次作业:基于RTMPose的耳朵穴位关键点检测

题目&#xff1a;基于RTMPose的耳朵穴位关键点检测 背景 根据中医的“倒置胎儿”学说&#xff0c;耳朵的穴位反映了人体全身脏器的健康&#xff0c;耳穴按摩可以缓解失眠多梦、内分泌失调等疾病。耳朵面积较小&#xff0c;但穴位密集&#xff0c;涉及耳舟、耳轮、三角窝、耳甲…

Unity - 从RG中解压法线贴图

文章目录 环境目的问题解决References 环境 Unity : 2020.3.37f1 Pipeline : BRP 目的 备忘便于索引 问题 之前使用 GPA 还原一些效果的时候&#xff0c;发现 法线贴图的 Y 通道数值不对&#xff0c;感觉被 翻转了 比方说&#xff0c;下面是 GPA 中的法线 这个法线是 DX …

Ubuntu20.04安装EVO工具教程

EVO工具全名为“Python package for the evaluation of odometry and SLAM”&#xff0c;使用Python写的轨迹评估工具&#xff0c;目前在SLAM领域论文中的“使用率”逐渐上升&#xff0c;可以说已经成为了作为SLAMer一定要会用的工具。最近需要使用evo工具评测SLAM算法性能并可…

Dell服务器安装Ubuntu系统

1、下载镜像&#xff0c;做启动盘 镜像链接 http://old-releases.ubuntu.com/releases/20.04.2/ubuntu-20.04.2-live-server-amd64.iso 版本可以根据自己要求选择。 做启动盘 我用的是ultraiso 记得先格式化&#xff0c;再写入。 2、 设置BIOS启动 按F11&#xff0c;进入BIOS…

光线追踪是怎么影响渲染速度的,什么显卡可以支持?

在 3D 世界中&#xff0c;慢慢地人们倾向于让它尽可能逼真。他们可以应用许多技术和技巧&#xff0c;但有一种技术可以为您提供很多帮助&#xff0c;称为光线追踪。然而&#xff0c;众所周知&#xff0c;它是非常计算密集型的。在本文中&#xff0c;让我们进一步探讨它&#xf…

Java JUC并发编程

前言 1、JUC是指有关 java.util.concurrent包以及其子包&#xff0c;这些包都是有关线程操作的包 2、HTTPS服务请求中&#xff0c;WEB服务只负责创建主线程来接收外部的HTTPS请求&#xff0c;如果不做任何处理&#xff0c;默认业务逻辑是通过主线程来做的&#xff0c;如果业务…

Linux文件基础IO

目录 C文件IO相关操作 介绍函数 文件相关系统调用接口 接口介绍 fd文件描述符 重定向 缓冲区 inode 软硬链接 动静态库 库的制作 制作静态库 制作动态库 使用库 使用静态库 使用动态库 C文件IO相关操作 介绍函数 打开文件 参数介绍&#xff1a; const char*…

MySQL的explain字段解释

MySQL的explain字段解释 ,type类型含义:1.id 2.select_type 3.table 4.type(重要) 5.possible_keys 6.possible_keys 7. key 8.key_len 9. ref 10. rows(重要) 11. filtered 12. Extra(重要) 如下: Explain命令是查看查询优化器是如何决定执行查询的主要方法。这个功…

Firewalld防火墙详解

文章目录 Firewalld防火墙什么是防火墙Firewalld防火墙的概念Firewalld防火墙运行模式Firewalld防火墙的命令Firewalld防火墙的高级规则 Firewalld防火墙 什么是防火墙 防火墙&#xff1a;防范一些网络攻击。有软件防火墙、硬件防火墙之分。 硬件防火墙和软件防火墙的主要区…

【软件开发】MyBatis 理论篇

MyBatis 理论篇 1.MyBatis 是什么&#xff1f; MyBatis 是一个半 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;它内部封装了 JDBC&#xff0c;开发时只需要关注 SQL 语句本身&#xff0c;不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。…

初识网络之协议定制

目录 一、数据在网络传输中遇到的部分问题 1. 序列化与反序列化 2. 如何保证接收端读取一个完整的报文 二、实现一个简单的网络计算器 1. 客户端处理 1.1 请求结构体和返回结构体 1.2 解析输入的字符串 1.3 序列化 1.4 添加标识符和字符串长度 1.5 接收服务端返回的数…

浏览器的回流与重绘与事件循环

浏览器的回流与重绘和事件循环 浏览器回流浏览器重绘事件循环 浏览器回流 什么是浏览器回流&#xff1f; 回流是通过JS代码让布局或者几何属性改变&#xff0c;使部分页面或者整个页面更新的过程 浏览器重绘 剩下的是浏览器重绘&#xff1a;比如改变div的visibility, color、…

如何使用Foxmail 7.2.25版本登录Microsoft 365 国内版(即世纪互联版)邮箱

近期微软在全球取消了在Exchange Online 的基本身份验证&#xff0c;取消了之后只有适配微软新式验证的客户端才支持登录&#xff0c;以往的直接配置IMAP/POP服务器地址和邮箱账号密码来登录的方式已经行不通了。 详情可以点击此链接了解&#xff1a;弃用 Exchange Online 中的…