three.js 入门 初识

news2024/11/15 7:42:15

基本步骤:

  1. 初始设置
  2. 创建场景
  3. 创建相机
  4. 创建可见对象
  5. 创建渲染器
  6. 渲染场景

安装

npm install three

引入

import * as THREE from "three";

一、three三要素:场景、相机、渲染

1.场景:

//创建场景
const scene=new THREE.Scene()

2.相机:OrthographicCamera正交投影(不会改变实际物体的大小)和PerspectiveCamera透视投影(和人的观感感觉一样会有近大远小的效果)我们这里是使用的透视投影

//创建相机
const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);
// 设置相机位置
camera.position.set(0, 0, 10);

75  视野:相机的视野有多宽,以度为单位;

window.innerWidth / window.innerHeight  纵横比:场景的宽度与高度的比率;

0.1  近剪裁平面:任何比这更靠近相机的东西都是不可见的;

1000  远剪裁平面:任何比这更远离相机的东西都是不可见的;

3.渲染

// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
//设置渲染器为全屏
renderer.setSize(window.innerWidth, window.innerHeight);
// 将webgl渲染的canvas内容添加到body
document.body.appendChild(renderer.domElement);

以上完成后就是创建一些物体或者是导入模型加载到场景中进行渲染

二、创建可见对象

1.Geometries(几何图形)

举例:长方体(BoxGeometry)

// 创建几何体
const geometry = new THREE.BoxGeometry(1, 1, 1);

球体(SphereGeometry)

const sphereTexture = new THREE.SphereGeometry(1, 20, 20);

平面(PlaneGeometry)

const planeGeometry = new THREE.PlaneGeometry(1, 1, 200, 200);

2.Lights(灯光)

环境光AmbientLight(它的颜色会添加到整个场景和所有对象的当前颜色上

const light = new THREE.AmbientLight(0x404040);
scene.add(light);

点光源PointLight(这种光源放出的光线来自同一点,且辐射方向四面八方,如蜡烛发出的光

方向光DirectionalLight(也称作无限光,从这种光源发出的光线可以看做是平行的,如太阳光

const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
// 设置直线光源的照射位置
directionalLight.position.set(10, 10, 10);
scene.add(directionalLight);

聚光灯SpotLight(这种光源的光线从一个椎体中射出,在被照射的物体上产生聚光的效果,如手电筒发出的光

能形成阴影的光源只有DirectionalLightSpotLight;而相对地,能表现阴影效果的材质只有LambertMaterialPhongMaterial

three.js中渲染阴影的开销比较大,所以默认物体是没有阴影的,需要单独开启。开启阴影的方法:

  • 将渲染器的shadowMapEnabled属性设置为true(告诉渲染器可以渲染阴影)
  • 将物体及光源的castShadow属性设置为true(告诉物体及光源可以透射阴影 物体投射阴影)
  • 将接收该阴影的物体的receiveShadow属性设置为true(告诉物体可以接收其他物体的阴影 物体接收阴影)

3.Controls(控制器)

轨道控制插件OrbitControls.js可以实现场景用鼠标交互,让场景动起来,控制场景的旋转、平移和缩放。

// 导入控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;

配置该插件之后实现的效果:

操控效果
按住鼠标左键并移动摄像机围绕场景中心旋转
转动鼠标滑轮或按住中键并移动放大或缩小
按住鼠标右键并移动在场景中平移
上、下、左、右方向键在场景中平移

4.Loaders(加载器)

5.Textures(纹理)

const textureLoader = new THREE.TextureLoader();
const floorColor = textureLoader.load(require("../assets/img/door/color.jpg"));

6.Materials(材质)

// 材质
const material = new THREE.MeshBasicMaterial({
  map: floorColor
});

MeshBasicMaterial(对光照无感,无光源可以显示,给几何体一种简单的颜色或显示线框)

MeshLambertMaterial(对光照有反应,无光源则不会显示,用于创建暗淡的不发光的物体)MeshPhongMaterial(对光照有反应,无光源不会显示,用于创建金属类米昂凉的物体)

物体之所以能被人眼看见,一种是它自身的材料就能发光,不需要借助外界光源;另一种是自身材料不发光,需要反射环境中的光。对于自身不发光的物体,需要个场景添加光源从而达到可视的效果。

const geometry = new THREE.BoxGeometry(1,1,1); // 创建一个长宽高都为1个单位的立方体
const textureLoader = new THREE.TextureLoader();//初始化纹理
const floorColor = textureLoader.load(require("../assets/img/door/color.jpg"));//导入纹理为一张图片
const material = new THREE.MeshBasicMaterial({color: 0x00ff00,map: floorColor}); // 创建材质,对光照无感
const cube = new THREE.Mesh(geometry, material); // 创建一个立方体网格(mesh),将材质包裹在立方体上
scene.add(cube); // 将立方体网格添加到场景中

camera.position.z = 5; // 指定相机位置

function animate() {
  // 照相机转动时,必须更新该控制器
  controls.update();
  // 结合场景和相机进行渲染,即用摄像机拍下此刻的场景
  renderer.render(scene, camera);
  // 渲染下一帧的时候就调用animate
  requestAnimationFrame(animate);
}
animate();

7.坐标轴辅助器

const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);

红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴.5表示轴的线段长度

8.监听画面变化

// 监听画面变化
window.addEventListener("resize", () => {
  const iwidth = window.innerWidth;
  const iheigt = window.innerHeight;
  //更新摄像头
  camera.aspect = iwidth / iheigt;
  // 更新摄像机投影矩阵
  camera.updateProjectionMatrix();
  // 更新渲染器
  renderer.setSize(iwidth, iheigt);
  // 设置渲染器像素比 防止在HiDPI显示器模糊(视网膜显示器)
  renderer.setPixelRatio(window.devicePixelRatio);
});

三、dat.gui控件(可以对渲染出来的物体进行变化操作)

1.安装并引入gui

npm install --save dat.gui 
import * as dat from "dat.gui";

2.实例代码

const gui = new dat.GUI();
gui
  .add(cube.position, "x")
  .min(0)
  .max(5)
  .step(0.05)
  .name("移动x坐标")
  .onChange((value) => {
    console.log("值被修改了:", value);
  });

// 修改物体的颜色
const params = {
  color: "#fff",
  fn: () => {
    gsap.to(cube.position, {
      x: 5,
      ease: "power1.out",
      duration: 5,
      repeat: -1,
      yoyo: true,
    });
  },
};
gui.addColor(params, "color").onChange((value) => {
  cube.material.color.set(value);
});

// 设置是否显示
gui.add(cube, "visible").name("是否显示");

// 设置按钮点击触发某个事件
var folder = gui.addFolder("设置立方体");
folder.add(cube.material, "wireframe");
folder.add(params, "fn").name("立方体运动");

3.效果

image.png

四、环境贴图

// 设置cube纹理加载器
const cubeTextureLoader = new THREE.CubeTextureLoader();
const envMapTexture = cubeTextureLoader.load([
  require("../assets/img/environmentMaps/1/px.jpg"),
  require("../assets/img/environmentMaps/1/nx.jpg"),
  require("../assets/img/environmentMaps/1/py.jpg"),
  require("../assets/img/environmentMaps/1/ny.jpg"),
  require("../assets/img/environmentMaps/1/pz.jpg"),
  require("../assets/img/environmentMaps/1/nz.jpg"),
]);// p-正方向,n-负方向

// 创建球体
const sphereTexture = new THREE.SphereGeometry(1, 20, 20);
// 材质
const material = new THREE.MeshStandardMaterial({
  metalness: 0.7,
  roughness: 0,
});

// 关联几何体和材质
const spher = new THREE.Mesh(sphereTexture, material);

// 添加几何体到场景
scene.add(spher);

// 给场景添加背景
scene.background = envMapTexture;
// 给场景所有的物体添加默认的环境贴图
scene.environment = envMapTexture;

五、HRD加载

// 导入hdr加载器
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader'
// 加载hdr环境图
const rgbeLoader = new RGBELoader();
rgbeLoader.loadAsync(require("../assets/img/hdr/012.hdr")).then((texture) => {
  texture.mapping = THREE.EquirectangularReflectionMapping; // 经纬线映射贴图
  scene.background = texture;
  scene.environment = texture;
})

六、加载3D模型

import * as THREE from 'three'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import robot from '../../public/robotglb.glb'
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
)
camera.position.set(0, 0, 10)
scene.add(camera)

const light = new THREE.AmbientLight(0xffffff)
scene.add(light)


//初始化模型加载器
const loader = new GLTFLoader()
//解压模型
const dracoLoader = new DRACOLoader()
//引入文件
dracoLoader.setDecoderPath('/draco/')
loader.setDRACOLoader(dracoLoader)
loader.load(
  robot,//模型
  gltf => {
    console.log(gltf, 'gltf')
    scene.add(gltf.scene)
  },
  xhr => {
    console.log(xhr)
  },
  err => {
    console.log(err)
  }
)



let mesh = new THREE.Mesh()
mesh.scale.set(6,6,6)
const renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)
const controls = new OrbitControls(camera, renderer.domElement)



function animate () {
  controls.update()
  renderer.render(scene, camera)
  requestAnimationFrame(animate)
}
animate()

注意:

这里的3d模型一定要放在public文件夹下不能放在src中 会报错 

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

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

相关文章

python中not的用法

前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 话不多说,直接开搞,如果有什么疑惑/资料需要的可以点击文章末尾名片领取源码 python中的not具体表示是什么: 在python中not是逻辑判断词,用于布尔型True和False, not True为F…

【Unity插件】实现多人在线游戏——Mirror插件的使用介绍

文章目录 前言导入Mirror插件 简单介绍一、RPC调用二、错误注意 基本使用一、创建场景的网络管理器二、创建一个玩家三、添加玩家初始生成位置四、玩家控制五、同步摄像机六、同步不同角色的名字和颜色修改七、同步动画八、同步子弹方法一方法二 九、聊天功能十、场景同步切换十…

torch.where()两种用法

参考官方文档。 官方文档中只给了第一种用法。根据条件condition,从input,other中选择元素f返回。如果满足条件,则返回input元素。若不满足,返回other元素。 还有一种用法是通过where返回张量中满足条件condition的坐标,以二维张…

【Unity每日一记】资源加载相关和检测相关

👨‍💻个人主页:元宇宙-秩沅 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 秩沅 原创 👨‍💻 收录于专栏:uni…

中兴协力NB-IoT部署实验(含复杂项目)

这个实验要求每个人都完成一遍,并且不同学生的部分操作内容也不同,个别班级最后也被要求基于此完成复杂项目,黑字部分是必要操作,紫字部分是辅助完成操作或复杂项目的讲解 进入实验室,选择模拟器(同一台模…

pytorch的自动微分、计算图 | 代码解析

在深度学习和机器学习中,自动微分是一个关键的概念,用于计算函数相对于其输入变量的导数(梯度)从而利用各类优化算法如梯度下降降低损失函数。PyTorch中的张量(tensor)提供了自动微分功能,它使得…

游戏视频录制软件对比,哪款最适合你的需求?

随着电子竞技和游戏直播行业的迅速崛起,越来越多的玩家渴望记录并分享自己在游戏中的精彩瞬间。游戏视频录制软件正是满足这一需求的关键工具。本文将针对三款优秀的游戏视频录制软件进行对比分析,以便为读者提供选购建议。 游戏视频录制软件1&#xff1…

Y4455芯片开发的433遥控流水灯方案

越来越多的家庭通过无线遥控来控制家中的照明系统,本文将介绍一种基于Y4455芯片的433MHz无线遥控流水灯方案,创造出美丽的照明场景。 一、宇凡微Y4455芯片简介 宇凡微Y4455芯片是一款低功耗、高性能的315MHz和433MHz短距离无线通讯发射芯片。它支持ASK…

Linux exec函数族

exec并不是生成新的进程还是在原进程执行 我们通常先创建一个子进程,在子进程里面使用exec,因为调用exec成功后,原进程的资源都被取代,除了一些进程ID等,所以在子进程里面调用exec,对原进程无影响。 前六个…

forest--声明式HTTP客户端框架-spring-b oot项目整合

Forest 是一个开源的 Java HTTP 客户端框架,它能够将 HTTP 的所有请求信息(包括 URL、Header 以及 Body 等信息)绑定到您自定义的 Interface 方法上,能够通过调用本地接口方法的方式发送 HTTP 请求。 官方链接: &…

实战演练 | Navicat 常用功能之转储与运行 SQL 文件

数据库管理工作中,"转储 SQL 文件"和"运行 SQL 文件"是两个极为常见操作。一般来说,用户使用数据库管理工具或命令行工具来完成。Navicat 管理开发工具中的“转储 SQL 文件”和“运行 SQL 文件”功能具有直观易用的界面、多种文件格…

北斗高精度定位,破解共享单车停车乱象

如今,共享单车已经成为了许多人出行的首选方式,方便了市民们的“最后一公里”,给大家的生活带来了很多便利。然而,乱停乱放的单车也给城市治理带来了难题。在这种情况下,相关企业尝试将北斗导航定位芯片装载到共享单车…

企业如何拓展市场,获取客源并进行降本增效?

对于企业来说,在降低成本和提高效率的同时拓展市场和获取客户是一项复杂的挑战。以下是实现这一目标的一些策略和方法: 1.市场研究和细分:进行彻底的市场研究,以确定您的产品或服务最有前途的细分市场。将您的精力集中在最有利可…

【PickerView案例09-上午内容复习 Objective-C预言】

一、好,我们把前面两个案例:点餐系统、城市选择界面、复习一下,然后继续讲第三个案例:国旗选择界面 1.我们就直接照着这个Demo去说了啊, 先来看一下这个,点餐系统: 首先,我们说,点餐系统,整个界面儿呢,分几部分:三部分 1)顶部呢:一个View 2)中间呢:一个Pic…

EndNote21 | 安装及库的创建

EndNote21 | 安装及库的创建 一、EndNote21安装二、EndNote21库的创建 一、EndNote21安装 软件安装界面,双击“EndNote 21.exe”程序; 图1 安装软件界面点击next,选择30天试用,点击next; 图2 安装过程点击next&…

数据结构——图(图的存储及基本操作)

文章目录 前言一、邻接矩阵法(顺序存储)1.无向图存储邻接矩阵算法2.有向图存储邻接矩阵算法 二、邻接表法(图的链式存储结构)总结 前言 邻接矩阵法(图的顺序存储结构) 1.1 无向图邻接矩阵算法 1.2 有向图邻接矩阵算法邻接表法(图的一种链式存储结构) 一…

软文推广在企业中运用的优势有哪些?

随着互联网的发展,越来越多的企业在推广方式上已经逐渐脱离于传统媒体,软文推广已经成为了企业宣传的主要方式。也有不少企业来找盒子进行推广,接下来媒介盒子就来告诉大家,企业进行软文推广的优势有哪些? 成本低 传统…

neon常用指令(updating)

函数参考手册: https://developer.arm.com/architectures/instruction-sets/simd-isas/neon/intrinsics 并在左侧选择neon\ Neon 128bit寄存器,所以可支持并行运算 加快运算速度 减少循环 CPU运算比加载数据快,速度瓶颈在加载数据这里。 指令集命名…

为什么你觉得Odoo二次开发难?如何切入?

先说结论,学习Odoo开发,我建议从Odoo的开发者模式切入。事实上在Odoo官网很多问题的解决方案就是基于开发者模式的。 前天有位学了《Odoo开发者模式必知必会》课程的网友跟我说,他之前也花钱买了其他的Odoo开发、前端开发课程,但…

无涯教程-JavaScript - XOR函数

描述 XOR函数返回所有参数的逻辑异或。如果所提供条件的奇数判断为TRUE,则XOR函数返回TRUE,否则返回FALSE。 语法 XOR (logical1, [logical2],…)争论 Argument描述Required/Optionallogical1logical1 is required and subsequent logical values are optional.1 to 254 co…