Three.js--》实现3d小岛模型搭建

news2025/1/19 20:37:03

目录

项目搭建

初始化three.js基础代码

设置环境背景

设置水面样式

添加天空小岛


今天简单实现一个three.js的小Demo,加强自己对three知识的掌握与学习,只有在项目中才能灵活将所学知识运用起来,话不多说直接开始。

项目搭建

本案例还是借助框架书写three项目,借用vite构建工具搭建react项目,vite这个构建工具如果有不了解的朋友,可以参考我之前对其讲解的文章:vite脚手架的搭建与使用 。搭建完成之后,用编辑器打开该项目,在终端执行 npm i 安装一下依赖,安装完成之后终端在安装 npm i three 即可。

因为react在每次页面发生变化时会出现执行整段代码,这样的话就会产生不必要的资源拥塞,所以我将three.js代码单独抽离成一个js文件。具体如下:

import { render } from "./three/水天一色小岛.js"
import './App.css'
const App = () => {
  return (
    <div>
      {render()}
    </div>
  )
}
export default App

当然也是有比较设置一下css样式,重置一下浏览器原本的css样式,如下:

*{
  margin: 0;
  padding: 0;
}
body{
  background-color: #1e1a20;
}
::-webkit-scrollbar {
  display: none;
}

初始化three.js基础代码

three.js开启必须用到的基础代码如下:

导入three库

import * as THREE from 'three'

初始化场景

const scene = new THREE.Scene()

初始化相机

const camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,2000)
camera.position.set(10,50,120) // 设置相机位置
camera.aspect = window.innerWidth / window.innerHeight // 更新摄像头宽高比例
camera.updateProjectionMatrix() // 更新摄像头矩阵
scene.add(camera)

初始化渲染器

const renderer = new THREE.WebGLRenderer({
  antialias:true, // 设置抗锯齿

})
renderer.outputEncoding = THREE.sRGBEncoding // 告诉渲染器在输出颜色时采用sRGB空间的标准渲染格式
renderer.setSize(window.innerWidth,window.innerHeight) // 设置渲染器的宽高
document.body.appendChild(renderer.domElement) // 将渲染器添加到页面中

监听屏幕大小的改变,修改渲染器的宽高和相机的比例

window.addEventListener("resize",()=>{
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()
  renderer.setSize(window.innerWidth,window.innerHeight)
})

导入控制器

import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"
// 实例化控制器
const controls = new OrbitControls(camera,renderer.domElement)

设置渲染函数

export function render(){
  renderer.render(scene,camera) // 渲染场景
  requestAnimationFrame(render) // 引擎自动更新渲染器
}
render()

ok,设置完这些基础代码之后,我们可以添加一个物体进行检验一下,就添加个平面吧,如下:

// 添加平面
const planeGeometry = new THREE.PlaneGeometry(100,100)
const planeMaterial = new THREE.MeshBasicMaterial({
  color:0xffffff
})
const plane = new THREE.Mesh(planeGeometry,planeMaterial)
scene.add(plane)

ok,可见代码写的没有错误,接下来开始具体的Demo实操。

设置环境背景

在网上随便找一张全景图片,然后进行球体的纹理贴图,代码如下:

// 创建一个巨大的天空球体
const skyGeometry = new THREE.SphereGeometry(1000,60,60)
const skyMaterial = new THREE.MeshBasicMaterial({
  map: new THREE.TextureLoader().load('./src/public/starry-sky2.jpg')
})
const sky = new THREE.Mesh(skyGeometry,skyMaterial)
scene.add(sky)

一开始我们是置身在球体外部的,具体效果如下:

如果想我们一开始就置身在球体内部可以进行如下操作:

设置视频纹理:除了设置图片纹理外,我们也可以设置一下视频纹理,如下:

// 设置视频纹理
const video = document.createElement("video")
video.src = "./src/public/sky.mp4" // 视频路径
video.loop = true // 循环播放
window,addEventListener("click",(e)=>{
  // 判断视频是否处于播放状态
  if(video.paused){
    video.play()
    skyMaterial.map = new THREE.VideoTexture(video)
    skyMaterial.map.needsUpdate = true
  }
})

设置水面样式

这里借助three库中Water来实现水面波纹的效果,如下:

// 导入水面
import { Water } from "three/examples/jsm/objects/Water2"
// 创建平面
const waterGeometry = new THREE.CircleGeometry(300,64)
const water = new Water(waterGeometry,{
  textureWidth: 1024,
  textureHeight: 1024,
  color:0x0080ff,
  scale: 1,
})
water.rotation.x = -Math.PI / 2
scene.add(water)

这里有个坑,如果想实现这种波纹效果的话,需要自行提供波纹的纹理贴图,并提供特定的路径,如果路径不对的话是否爆出如下错误的,如下:

添加天空小岛

导入gltf载入库

import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"
import { DRACOLoader } from 'three/examples/jsm/loaders/dracoloader'

添加小岛模型

const loader = new GLTFLoader() // 实例化gltf载入库
const dracoLoader = new DRACOLoader() // 实例化draco载入库
dracoLoader.setDecoderPath("/draco/") // 添加draco载入库
loader.setDRACOLoader(dracoLoader) // 添加draco载入库

loader.load("./model/island2.glb",(gltf)=>{
  scene.add(gltf.scene)
})

这里需要设置一下环境纹理来显示具体样式

import { DRACOLoader } from 'three/examples/jsm/loaders/dracoloader'
import { RGBELoader } from 'three/examples/jsm/loaders/rgbeloader'
// 载入环境纹理
const hdrLoader = new RGBELoader()
hdrLoader.loadAsync("./src/public/050.hdr").then((texture)=>{
  texture.mapping = THREE.EquirectangularReflectionMapping
  scene.background = texture
  scene.environment = texture
})

// 添加环境光
const light = new THREE.DirectionalLight(0xffffff,1)
light.position.set(-100,100,10)
scene.add(light)

最后实现的效果如下:

ok,今天的three.js小案例就讲到这,给出本文的代码笔记: (获取素材也可以私信博主)

/* eslint-disable no-unused-vars */
import * as THREE from 'three'
// 导入控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"
// 导入水面
import { Water } from "three/examples/jsm/objects/Water2"
// 导入gltf载入库
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"
import { DRACOLoader } from 'three/examples/jsm/loaders/dracoloader'
import { RGBELoader } from 'three/examples/jsm/loaders/rgbeloader'

// 初始化场景
const scene = new THREE.Scene()
// 初始化相机
const camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,2000)
camera.position.set(10,50,120) // 设置相机位置
camera.aspect = window.innerWidth / window.innerHeight // 更新摄像头宽高比例
camera.updateProjectionMatrix() // 更新摄像头矩阵
scene.add(camera)
// 初始化渲染器
const renderer = new THREE.WebGLRenderer({
  antialias:true, // 设置抗锯齿
  logarithmicDepthBuffer: true // 对数深度缓冲区
})
renderer.outputEncoding = THREE.sRGBEncoding // 告诉渲染器在输出颜色时采用sRGB空间的标准渲染格式
renderer.setSize(window.innerWidth,window.innerHeight) // 设置渲染器的宽高
document.body.appendChild(renderer.domElement) // 将渲染器添加到页面中

// 监听屏幕大小的改变,修改渲染器的宽高和相机的比例
window.addEventListener("resize",()=>{
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()
  renderer.setSize(window.innerWidth,window.innerHeight)
})

// 实例化控制器
const controls = new OrbitControls(camera,renderer.domElement)

// 设置渲染函数
export function render(){
  renderer.render(scene,camera) // 渲染场景
  requestAnimationFrame(render) // 引擎自动更新渲染器
}
render()

// 创建一个巨大的天空球体
let texture = new THREE.TextureLoader().load('./src/public/starry-sky2.jpg')
const skyGeometry = new THREE.SphereGeometry(1000,30,30)
const skyMaterial = new THREE.MeshBasicMaterial({
  map: texture
})
skyGeometry.scale(1,1,-1)
const sky = new THREE.Mesh(skyGeometry,skyMaterial)
scene.add(sky)

// 设置视频纹理
const video = document.createElement("video")
video.src = "./src/public/sky.mp4" // 视频路径
video.loop = true // 循环播放
window,addEventListener("click",(e)=>{
  // 判断视频是否处于播放状态
  if(video.paused){
    video.play()
    let texture = new THREE.VideoTexture(video)
    skyMaterial.map = texture
    skyMaterial.map.needsUpdate = true
    scene.background = texture
    scene.environment = texture
  }
})

// 载入环境纹理
const hdrLoader = new RGBELoader()
hdrLoader.loadAsync("./src/public/050.hdr").then((texture)=>{
  texture.mapping = THREE.EquirectangularReflectionMapping
  scene.background = texture
  scene.environment = texture
})

// 添加环境光
const light = new THREE.DirectionalLight(0xffffff,1)
light.position.set(-100,100,10)
scene.add(light)

// 创建平面
const waterGeometry = new THREE.CircleGeometry(300,64)
const water = new Water(waterGeometry,{
  textureWidth: 1024,
  textureHeight: 1024,
  color:0xeeeeff,
  scale: 1,
})
water.position.y = 3
water.rotation.x = -Math.PI / 2
scene.add(water)

// 添加小岛模型
const loader = new GLTFLoader() // 实例化gltf载入库
const dracoLoader = new DRACOLoader() // 实例化draco载入库
dracoLoader.setDecoderPath("/draco/") // 添加draco载入库
loader.setDRACOLoader(dracoLoader) // 添加draco载入库

loader.load("./model/island2.glb",(gltf)=>{
  scene.add(gltf.scene)
})

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

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

相关文章

AR和VR技术的进展和应用:如何为移动应用开发添加更多趣味和体验?

章节一&#xff1a;引言 作为一名移动应用开发者&#xff0c;我一直致力于为用户提供创新和令人兴奋的体验。随着技术的不断发展&#xff0c;AR和VR技术成为了实现这一目标的有力工具。无论是增强现实还是虚拟现实&#xff0c;它们都能够将虚拟世界与现实世界相结合&#xff0…

可移动磁盘“未格式化”提示?教程帮你重获数据!

可移动磁盘在使用的过程中会出现各种奇怪的错误&#xff0c;比如小编今天碰到的一个&#xff0c;打开分区提示未格式化&#xff01;可移动磁盘“未格式化”提示&#xff1f;教程帮你重获数据&#xff01; 可移动磁盘“未格式化”提示&#xff1f;教程帮你重获数据&#xff01; …

【新星计划·2023】常用的5种VLAN的划分方式,你知道几种?

在说VLAN划分方式之前&#xff0c;先来说一说什么是VLAN&#xff1f;为什么需要划分VLAN&#xff1f; 一、什么是VLAN VLAN(Virtual Local Area Network)即虚拟局域网&#xff0c;是将一个物理的LAN在逻辑上划分成多个广播域的通信技术。每个VLAN是一个广播域&#xff0c;VLA…

我还是劝你别去外包,干了4年,废了.....

先说一下自己的情况&#xff0c;大专生&#xff0c;18年通过校招进入湖南某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…

AVUE样式、刷新、字典、清空搜索条件等操作

1、操作栏、表格样式的控制 2、下拉框字典的设置 3、日期格式的设置 const dateFormat function(row, value) { if (!value) return ; let format YYYY-mm-dd; let date new Date(value); const dataItem { Y: date.getFullYear().toString(), m: (date.ge…

使用midjourney搞出一套三国人物画像!

当下已进入如火如荼的全民AI时代&#xff0c;最近体验了下midjourney&#xff0c;使用它的以图生图功能生成出来一套三国人物画像&#xff0c;和大家分享下使用心得。 使用midjourney的准备工作 下载工具 使用midjourney生产图片依赖的工具和流程&#xff0c;大致如下&#x…

Parasoft和TASKING联手提供卓越的汽车软件开发和自动化测试

​​Parasoft与TASKING宣布建立合作 2023年4月26日&#xff0c;全球嵌入式软件测试解决方案领导者Parasoft宣布与汽车嵌入式软件开发工具行业领导者TASKING建立合作伙伴关系。Parasoft和TASKING的合作为汽车行业提供了一套完整的软件全生命周期解决方案&#xff0c;通过CI/CD工…

Shell基础学习---2、运算符、条件判断、流程控制

1 、运算符 1、基本语法 “$((运算式))”或‘“$[运算式]” 2、案例实操 2 、条件判断 1、基本语法 &#xff08;1&#xff09;test condition &#xff08;2&#xff09;[ condition ] &#xff08;注意condition前后要有空格&#xff09; 注意&#xff1a;条件非空即为tr…

批量域名综合信息查询-域名批量注册查询软件

域名综合信息查询 域名是一个网站的重要组成部分&#xff0c;它直接影响着网站的流量和排名。对于网站管理者来说&#xff0c;了解域名的综合信息是非常重要的。为了便于管理者查询和了解域名的综合信息&#xff0c;147SEO提供了免费的域名综合信息查询服务。下面&#xff0c;…

案例9:Java公益物资分配系统设计与实现开题报告

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

k8s系列-eureka部署集群

1.基本信息 2.容器信息 容器镜像名称: xxxx:30002/dmp/eureka:2022.10.08.14.39.17 环境变量 参数名称 参数值 eureka.instance.hostname ${HOSTNAME}.dmp-eureka-cloud eureka.instance.prefer-ip-address false eureka.client.service-url.defaultZone http://dmp-eureka…

CLLC谐振变换器的基波分析

CLLC谐振变换器_基波分析 目录 CLLC谐振变换器_基波分析 目录电路图FHA分析基于FHA的电路增益特性分析 电路图 FHA分析 输入电压FHA分析 谐振输入假设为理想方波 V i ( t ) 4 V i n π ∑ n 1 , 3 , 5... ∞ 1 n s i n ( 2 π n f s t ) V_{i}(t)\frac{4Vin}{\pi}\sum_…

拓尔微芯片TMI33421在家电上的应用、特点及概述

TMI33421是拓尔微最新推出的一款30V, 2A 同步降压DC-DC转换器&#xff0c;在效率和可靠性方面表现俱佳。 高效率&#xff1a;最高可达95% TMI33421是一颗同步降压转换器&#xff0c;将2颗MOS管集成在芯片内部&#xff0c;实现更小的功率损耗&#xff0c;在2A的正常工作电流下&…

第03讲:SpringCloudStream实现分布式事务

需求分析 本案例是通过一个发送短信验证码的功能来实验MQ发送消息时实现分布式事务&#xff0c;思路分析如下 消息生产者生产发送验证码的半消息 生产者执行本地事务&#xff08;将验证码保存到数据库&#xff09;&#xff0c;并记录事务的ID&#xff0c;如果整个过程不出现异…

[点云学习] 一、点云相关知识了解

1.何谓点云&#xff1f; 点云是一种表示三维空间中对象的数据结构&#xff0c;它由许多离散的点组成。每个点都有自己的位置坐标和可能的其他属性&#xff0c;如颜色、法向量和强度等。点云通常由激光扫描仪、相机或其他传感器捕获&#xff0c;用于创建三维模型、地图或进行遥感…

three.js学习 11 - 1.threejs常用几何体 2.几何体材质自定义 3.材质的旋转与堆叠效果

1.threejs常用几何体 ①.缓冲几何体&#xff08;立方体&#xff09; 官网API地址&#xff1a;https://www.three3d.cn/docs/index.html?qgeometry#api/zh/geometries/BoxGeometry ②.圆缓冲几何体 官网地址&#xff1a;https://www.three3d.cn/docs/index.html?qgeometry#a…

内存一致性(Memory Consistency)模型简介

这里写自定义目录标题 1. 前言2 为什么需要内存一致性(Memory Consistency)模型3. 什么是内存一致性(Memory Consistency)模型4. 各种内存一致性(Memory Consistency)模型4.1 顺序一致性(SC: Sequential Consistency)模型4.2 完全存储定序(TSO: Total Store Order)模型4.3 部分…

外贸人如何精准开发客户?Facebook开发客户全攻略

现在做跨境的都了解的一个社媒平台就是Facebook了&#xff0c;因为很多人都会拿Facebook来开发客户&#xff0c;忙里偷闲&#xff0c;今天东哥就来聊聊用Facebook开发客户的一些心得。 用Facebook开发客户的心得 1、利用关键词搜索 使用行业相关的关键词、产品特定的关键词、相…

菁染料-N-羟基琥珀酰亚胺酯Cyanine7-NHS ester活性脂1432019-64-1

CY7-NHS ester是一种荧光染料&#xff0c;具有橙红色荧光。它的化学式为C41H48ClN3O4&#xff0c;分子量为733.64。CY7-NHS的荧光特性适合生物学应用&#xff0c;它的激发波长为750nm&#xff0c;发射波长为773nm&#xff0c;可用于近红外成像。这种标记物可以用于活细胞成像、…

案例10:Java外卖平台设计与实现开题报告

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…