2024年了,是该学学Three.js了

前言

 📫 大家好,我是南木元元,热衷分享有趣实用的文章,希望大家多多支持,一起进步!

 🍅 个人主页:南木元元


目录

Three.js介绍

Three.js应用场景

搭建开发环境

初始化项目

创建文件

配置命令

启动服务

Three.js的一些重要概念

第一个3D场景

渲染器

3D场景的实现

1.创建三维场景

2.创建透视相机

3.创建渲染器

4.添加物体

5.定位相机

结语 


Three.js介绍

讲到Three.js,就需要先说一下OpenGL和WebGL,OpenGL是一个跨平台的3D/2D的绘图标准,WebGL是一种3D绘图协议,它允许把JavaScript和OpenGL 结合在一起运用,但使用WebGL原生的API来写3D程序非常的复杂,对于前端开发者来说学习成本非常高。

Three.js是WebGL的JavaScript 3D库,其对WebGL提供的接口进行了非常好的封装,简化了很多细节,大大降低了学习成本,让开发者能更快速的进行3D场景效果的开发。

简单来说,Three.js就是能够实现3D效果的JS库。

官网:Three.js – JavaScript 3D Library

WebGL、OpenGL、Three.js三者的关系:

  • WebGL:OpenGL + JavaScript
  • Three.js:一个基于WebGL封装的库

Three.js应用场景

three.js应用广泛,在小游戏、产品展示、物联网、智慧城市、机械、建筑、GIS等各个领域基本上都有three.js的身影。 

微信小游戏

智慧城市

智慧小区

数字孪生

全景看房

机械领域

GIS

搭建开发环境

本文使用vite来搭建three.js的开发环境,当然你也可以使用webpack等其他打包工具。

初始化项目

创建vite-three目录并执行npm init -y,初始化 package.json。

npm init -y

安装vite:

npm i vite -D

安装three.js:

npm i three

此时的项目目录如下:

创建文件

创建src目录,src下新建main.js文件,根目录创建index.html,作为vite的入口文件。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>vite-three</title>
    <style>
        body {
            margin: 0;
        }
    </style>
</head>
<body>
    <!-- 使用模块化方式引入文件 -->
    <script src="./src/main.js" type="module"></script>
</body>
</html>

上述引入js时加上了type="module",代表使用模块化的方式引入,因为main.js中会使用到import模块化语法。main.js文件如下:

import * as THREE from "three";
console.log(THREE);

配置命令

在package.json中配置如下命令:

"scripts": {
    "dev": "vite --open",
    "build": "vite build",
    "preview": "vite preview"
}

启动服务

终端输入npm run dev,启动开发服务:

npm run dev

在浏览器控制台看到如下信息,就代表Three.js已经成功引入。

Three.js的一些重要概念

在Three.js中,我们需要先理解一些比较重要的概念:

  • 场景:场景就是一个三维的世界,在这个世界中可以放置各种各样的物体。
  • 相机:三维空间的观察者,通过相机来查看场景。
  • 物体:被观察的对象,不同的物体形状、大小、材质、纹理不同。
  • 光源:物体表面的明暗效果会受光照影响,为了更好的模拟三维效果,需要一些光照和阴影。

这里需要重点说下相机。

相机分为两种:透视相机(PerspectiveCamera)和正交相机(OrthographicCamera)。

Three.js最常使用的是透视相机,它模拟了人眼观察世界的规律:物体近大远小。

// 透视相机参数
const fov = 45; 
const aspect = window.innerWidth / window.innerHeight;
const near = 1; 
const far = 1000; 
// 创建一个透视相机
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);

透视相机有四个构造参数:

  1. fov(视野):相机的视野有多宽,以度为单位。
  2. aspect(纵横比):场景的宽度与高度的比率。
  3. near(近剪裁平面):任何比这更靠近相机的东西都是不可见的。
  4. far(远剪裁平面):任何比这更远离相机的东西都是不可见的。

这四个参数构成一个有边界的空间区域,被称为视锥体,只有视锥体之内的物体,才会渲染出来,视锥体范围之外的物体不会显示。

第一个3D场景

创建一个场景,需要3个对象:场景(scene)、相机(camera)、渲染器(renderer),这样就能通过摄像机渲染出场景。

渲染器

场景和相机我们都已经介绍过了,那什么是渲染器呢?

渲染器(Renderer):从相机的角度去渲染场景,负责将场景绘制到<canvas>元素中。

three.js的整个工作机制如下图所示: 

将可见对象如网格(mesh)添加到场景(scene)中,然后将需要渲染的数据传递给渲染器(renderer),渲染器负责将场景在 <canvas> 画布上绘制出来。了解了这些,接下来我们就来绘制three.js的第一个3D场景。

3D场景的实现

1.创建三维场景

首先,创建场景,作为我们能看到的一切的载体。

const scene = new THREE.Scene();

2.创建透视相机

创建透视相机,设置相机参数。

// 透视相机参数
const fov = 45; 
const aspect = window.innerWidth / window.innerHeight;
const near = 1; 
const far = 1000; 
// 创建一个透视相机
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);

3.创建渲染器

创建渲染器,并执行render渲染操作。

// 创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 渲染
renderer.render(scene, camera);

4.添加物体

three.js中,使用Mesh网格表示一个物体,网格包含几何体(Geometry)和材质(Material)。

创建一个立方体,添加到场景中。 

// 创建立方体(几何+材质)
const geometry = new THREE.BoxGeometry(100, 100, 100);
const material = new THREE.MeshNormalMaterial();
const mesh = new THREE.Mesh(geometry, material);
// 添加到场景
scene.add(mesh);

上述代码,创建了长宽高均为100个单位的立方体,使用法向量材质MeshNormalMaterial,然后基于几何形状和材质创建立方体,最后添加到场景中。

5.定位相机

完成上述步骤后,你却会发现此时的屏幕上是一片黑暗,什么也看不到。

这是因为我们创建的相机和物体最初都位于场景的中心(0, 0, 0),并且相机也默认看向(0, 0, 0)这个点,所以透视相机不会渲染内容。我们只需移动一下相机位置就可以了。

// 定位相机
camera.position.set(200, 300, 200); //设置相机位置
camera.lookAt(0, 0, 0); //设置相机方向

效果:

完整代码:

import * as THREE from "three";

// 创建场景
const scene = new THREE.Scene();
// 创建透视相机
const fov = 45;
const aspect = window.innerWidth / window.innerHeight;
const near = 1;
const far = 1000;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
// 定位相机
camera.position.set(200, 300, 200); 
camera.lookAt(0, 0, 0); 

// 创建立方体(几何+材质)
const geometry = new THREE.BoxGeometry(100, 100, 100);
const material = new THREE.MeshNormalMaterial();
const mesh = new THREE.Mesh(geometry, material);
// 添加到场景
scene.add(mesh);

// 创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 渲染
renderer.render(scene, camera);

结语 

🔥如果此文对你有帮助的话,欢迎💗关注、👍点赞、⭐收藏✍️评论支持一下博主~    

  • 123
    点赞
  • 117
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 174
    评论
import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; class RegexTest { public static void main(String[] args) { checkMail(); StringReplace(); ipSort(); getNumber(); } /* * 需求: 对邮件地址进行校验,判断给出的mail是否是合法的邮箱地址 */ public static void checkMail() { String mail = "abc12@sina.com"; String mailRegex = "[a-zA-Z0-9]+@[a-zA-Z0-9]+(\\.[a-zA-Z]+)+"; Pattern pattern = Pattern.compile(mailRegex); Matcher matcher = pattern.matcher(mail); if (matcher.matches()) { System.out.println(mail + " is a valid email address."); } else { System.out.println(mail + " is not a valid email address."); } } /* * 需求: 将下列字符串转成:我要编程 */ public static void StringReplace() { String str = "我我...我我..我...我要..要要..学学学学...学学..编...编程程"; String replaceStr = str.replaceAll("[^我要编程]", ""); System.out.println(replaceStr); } /* * 192.68.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30 将ip地址进行地址段的顺序排序 * 还按照字符串自然顺序,只要让它们每一段都是3位即可 1,按照每一段需要的最多的0进行补齐 那么每一段就会至少保证有3位 2,将每一段只保留3位 这样,所有的ip地址都是每一段3位 */ public static void ipSort() { String ip = "192.68.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30"; TreeSet<String> set = new TreeSet<String>(); String[] ips = ip.split(" "); for (String s : ips) { String[] nums = s.split("\\."); StringBuilder sb = new StringBuilder(); for (String num : nums) { sb.append(String.format("%03d", Integer.parseInt(num))); } set.add(sb.toString()); } for (String s : set) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < s.length(); i += 3) { sb.append(Integer.parseInt(s.substring(i, i + 3))).append("."); } sb.deleteCharAt(sb.length() - 1); System.out.println(sb.toString()); } } /* * 提取数字 */ public static void getNumber() { String string = "12334我的QQ是: 456456 我的电话是:0532214我的邮箱是:123:aaa@aaa.com"; String regex = "\\d+"; Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(string); while (matcher.find()) { System.out.println(matcher.group()); } } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 174
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南木元元

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值