Three.js--》模型材质与纹理的使用

news/2024/11/27 2:10:48/

目录

初识材质与纹理

修改模型材质颜色

模型添加纹理

纹理常用属性使用

纹理显示算法

设置粗糙度

纹理加载进度情况

设置环境贴图


初识材质与纹理

three.js中的材质就是几何体表面的材料。所有材质均继承自Material。ThreeJS的材质分为:基础材质、深度材质、法向量材质、琥珀材质、冯氏材质、标准材质、着色器材质、基础线材质以及虚线材质。

材质就像物体的皮肤,决定了几何体的外表。例如,材质可以定义一个几何体看起来像金属还是木板,是否透明,什么颜色等,然后添加到Mesh中才可以添加到场景中进行渲染。本章,将会带领大家熟悉Three.js中API提供的所有材质,你也会学会运用这些材质,制作精美的三维物体。

纹理的基类是 Texture,一般我们都使用这个类,通过给其属性 Image 传入一个图片从而构造出一个纹理。纹理是材质的属性,材质和几何体 Gemotry 构成 Mesh ,然后被添加到 Scene 中进行渲染。纹理决定了物体的表面该是什么样子,而材质则决定了物体具备什么样的“气质”。

修改模型材质颜色

比如我设置了一个几何体,后面如果想修改其颜色的话可以通过以下几种方式进行:

模型添加纹理

给几何体添加纹理十分简单,只需准备一张纹理图,然后参考官方文档给出的案例即可:

纹理常用属性使用

纹理的属性有很多,具体的可参看 官方文档 ,如下。接下来着重讲解几个重要的属性:

纹理偏移设置

纹理旋转设置

// 设置纹理旋转 45deg
doorColorTexture.center.set(0.5,0.5) // 设置旋转原点
doorColorTexture.rotation = Math.PI / 4

纹理重复设置

// 设置纹理重复
doorColorTexture.repeat.set(2,3)
// 设置纹理重复模式
doorColorTexture.wrapS = THREE.RepeatWrapping  // 水平无限重复
doorColorTexture.wrapT = THREE.MirroredRepeatWrapping // 垂直镜像重复

纹理显示算法

通过以下官方提供给我们的API函数,实现纹理显示的算法:

// texture纹理显示设置
doorColorTexture.minFilter = THREE.NearestFilter
doorColorTexture.magFilter = THREE.NearestFilter

// texture纹理显示设置
doorColorTexture.minFilter = THREE.LinearFilter
doorColorTexture.magFilter = THREE.LinearFilter

设置粗糙度

我们也可以给几何体设置粗糙度,让其表面变得光滑从而反射的光更明显,如下:

当然我们可以采用一些贴图网站提供给我们的素材,对某一几何体进行相关细节特征的编写,在这就不再过多赘述,后期项目中会逐一讲解,素材网站 ;素材网站 。

纹理加载进度情况

当我们的项目图像资源过大时,我们可以可视化一个加载进度的显示,通过如下方式进行:

创建一个加载管理器:

// 设置加载管理器
const loadingManager = new THREE.loadingManager()

将load后三者提供的参数放置在里面

// 设置三种情况
const event = {}
event.onLoad = () =>{ console.log('图片加载成功');
}
event.onProgress = (url,num,total) =>{ console.log('图片加载完成:',url);console.log('图片加载进度:',num);console.log('图片总数:',total);console.log('加载进度的百分比:',((num/total)*100).toFixed(2)+"%")
}
event.onError = (e) =>{ console.log('图片加载出现错误');console.log(e);
}// 设置加载管理器
const loadingManager = new THREE.LoadingManager(event.onLoad,event.onProgress,event.onError
)// 导入纹理
const textureLoader = new THREE.TextureLoader(loadingManager)
const doorColorTexture = textureLoader.load(img)

当然我们可以将进度显示在界面上,如下:

var div = document.createElement("div")
div.style.width = "200px"
div.style.height = "200px"
div.style.position = "fixed"
div.style.right = 0
div.style.top = 0
div.style.color = "#fff"
document.body.appendChild(div)

因为我写的这个案例就一张图片,所以加载速度很快,等后期做项目素材数量多的话,这种就有明显的效果了,如下:

设置环境贴图

环境贴图就类似于将一个几何体的全身都贴上图片,让其彷佛置身在当前的空间当中,当然这里的图片你可以采用真实的类似商业街道或者乡野田园等等。

注意:使用图片的分辨率尺寸一定要保持一致,不然是不会加载出来的。

// 设置cube纹理加载器
const cubeTextureLoader = new THREE.CubeTextureLoader()
const envMapTexture = cubeTextureLoader.load([img1,img2,img3,img4,img5,img6])// 创建球物体
const sphereGeometry = new THREE.SphereGeometry(1,20,20)
// 球模型渲染几何体
const material = new THREE.MeshStandardMaterial({metalness:0.7, // 设置金属材质roughness:0.1, // 设置光滑度envMap:envMapTexture
})
const mesh = new THREE.Mesh(sphereGeometry,material)
scene.add(mesh)

当然我们也可以给环境添加背景,这样让整个样式更加的真实,如下:

// 给场景添加背景
scene.background = envMapTexture

当然你也可以不用给材料设置envMap属性,也可以进行如下设置给当前所有的页面添加相同背景

当然我们也不一定非要需要6张图片去实现,一张全景图也能实现3d可视化效果,这种方式就是类似于一张世界地图呈现在你面前,而当它不是以平面图片给你展示而是以一个球体给你展示的时候,你也能感受到3d的效果,全景图的实现类似就是这样:

import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader'
// 添加hdr环境图
const rgbeLoader = new RGBELoader()
rgbeLoader.loadAsync("/src/public/2.hdr").then((texture)=>{texture.mapping = THREE.EquirectangularReflectionMappingscene.background = texturescene.environment = texture
})

ok,材质与纹理的使用就讲到这,具体可以参考官网,给出本文的代码笔记:

import * as THREE from 'three';
// 导入轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
// import img from '../public/木质纹理.jpg'
// import img1 from '../public/1.jpg'
// import img2 from '../public/2.jpg'
// import img3 from '../public/3.jpg'
// import img4 from '../public/4.jpg'
// import img5 from '../public/5.jpg'
// import img6 from '../public/6.jpg'
// import img7 from "../public/1.hdr"
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader'
// 添加hdr环境图
const rgbeLoader = new RGBELoader()
rgbeLoader.loadAsync("/src/public/2.hdr").then((texture)=>{texture.mapping = THREE.EquirectangularReflectionMappingscene.background = texturescene.environment = texture
})// 1.创建场景
const scene = new THREE.Scene();
// 2.创建相机
const camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000)
// 设置x、y、z轴坐标,即设置相机位置
camera.position.set(0,0,10)
// 将相机添加到场景之中
scene.add(camera)
// 3.添加物体,创建几何体
// const geometry = new THREE.BoxGeometry(3,3,3)// var div = document.createElement("div")
// div.style.width = "200px"
// div.style.height = "200px"
// div.style.position = "fixed"
// div.style.right = 0
// div.style.top = 0
// div.style.color = "#fff"
// document.body.appendChild(div)// // 设置三种情况
// const event = {}
// event.onLoad = () =>{ 
//   console.log('图片加载成功');
// }
// event.onProgress = (url,num,total) =>{ 
//   console.log('图片加载完成:',url);
//   console.log('图片加载进度:',num);
//   console.log('图片总数:',total);
//   let value = ((num/total)*100).toFixed(2)+"%"
//   div.innerHTML = value
//   console.log('加载进度的百分比:',((num/total)*100).toFixed(2)+"%")
// }
// event.onError = (e) =>{ 
//   console.log('图片加载出现错误');
//   console.log(e);
// }// // 设置加载管理器
// const loadingManager = new THREE.LoadingManager(
//   event.onLoad,
//   event.onProgress,
//   event.onError
// )// // 导入纹理
// const textureLoader = new THREE.TextureLoader(loadingManager)
// const doorColorTexture = textureLoader.load(img)// // 设置纹理偏移
// doorColorTexture.offset.x = 0.5
// doorColorTexture.offset.y = 0.5
// doorColorTexture.offset.set(0.5,0,5)
// // 设置纹理旋转 45deg
// doorColorTexture.center.set(0.5,0.5) // 设置旋转原点
// doorColorTexture.rotation = Math.PI / 4
// // 设置纹理重复
// doorColorTexture.repeat.set(2,3)
// // 设置纹理重复模式
// doorColorTexture.wrapS = THREE.RepeatWrapping  // 水平无限重复
// doorColorTexture.wrapT = THREE.MirroredRepeatWrapping // 垂直镜像重复// texture纹理显示设置
// doorColorTexture.minFilter = THREE.NearestFilter
// doorColorTexture.magFilter = THREE.NearestFilter
// doorColorTexture.minFilter = THREE.LinearFilter
// doorColorTexture.magFilter = THREE.LinearFilter// 设置cube纹理加载器
// const cubeTextureLoader = new THREE.CubeTextureLoader()
// const envMapTexture = cubeTextureLoader.load([img1,img2,img3,img4,img5,img6])// 创建球物体
const sphereGeometry = new THREE.SphereGeometry(1,20,20)
// 球模型渲染几何体
const material = new THREE.MeshStandardMaterial({metalness:0.7, // 设置金属材质roughness:0.1, // 设置光滑度// envMap:envMapTexture
})
const mesh = new THREE.Mesh(sphereGeometry,material)
scene.add(mesh)
// // 给场景添加背景
// scene.background = envMapTexture
// 给场景所有的物体添加默认的环境贴图
// scene.environment = envMapTexture// // 网格模型渲染几何体
// const material = new THREE.MeshStandardMaterial({
//   color:'#fffff00',
// })
// const mesh = new THREE.Mesh(geometry,material)
// scene.add(mesh)// 4.初始化渲染器
const renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth,window.innerHeight)
document.body.appendChild(renderer.domElement)// // 添加一个平行光
// const directionalLight = new THREE.DirectionalLight(0xffffff,1)
// // 设置光源方向
// directionalLight.position.set(8,10,5)
// // 方向光指向对象网格模型Mesh,即照射的对象,可以不设置,默认的位置是0,0,0
// directionalLight.target = mesh
// scene.add(directionalLight)// 添加一个环境光
const ambient = new THREE.AmbientLight(0xffffff,0.9)
scene.add(ambient)// // 创建一个点光源
// const pointLight = new THREE.PointLight(0xffffff,1.0)
// // 设置点光源位置
// pointLight.position.set(0,5,0)
// scene.add(pointLight)
// // 可视化点光源
// const pointLightHelper = new THREE.PointLightHelper( pointLight, 0.1 );
// scene.add(pointLightHelper)// // 添加坐标轴辅助器
// const axesHelper = new THREE.AxesHelper(5) // 数值代表线的长度
// scene.add(axesHelper) // 添加到场景之中// 创建轨道控制器
const controls =  new OrbitControls(camera,renderer.domElement)
// 设置控制器阻尼,让控制器更有真实效果,但必须在动画循环里调用 .update()
controls.enableDamping = trueexport function render(){// 每次循环渲染时调用stats更新方法,来刷新时间controls.update()renderer.render(scene,camera) // 周期性执行相机的渲染功能,更新canvas画布上的内容requestAnimationFrame(render) // 接下来渲染下一帧的时候就会调用render函数
}
// 先开始就渲染一下
render()

http://www.ppmy.cn/news/61881.html

相关文章

深入理解 Linux 内核(二)

系列文章目录 Linux 内核设计与实现 深入理解 Linux 内核(一) 深入理解 Linux 内核(二) Linux 设备驱动程序 Linux设备驱动开发详解 文章目录 系列文章目录六、定时测量1、时钟和定时器电路2、Linux 计时体系结构(1&am…

Python每日一练:最长递增的区间长度(一行代码花样解法)

文章目录 前言一、题目二、一行超人三、分析一下思路 总结 前言 很显然,Python的受众远远大于C,其实笔者本人对Python的理解也是远强于C的,C纯粹是为了假装笔者是个职业选手才随便玩玩的,借着十多年前学的C的功底,强行…

树脂塞孔有哪些优缺点及应用?

树脂塞孔的概述 树脂塞孔就是利用导电或者非导电树脂,通过印刷,利用一切可能的方式,在机械通孔、机械盲埋孔等各种类型的孔内进行填充,实现塞孔的目的。 树脂塞孔的目的 1 树脂填充各种盲埋孔之后,利于层压的真空下…

Android 13 变更及适配攻略

准备工作 首先将我们项目中的 targetSdkVersion和compileSdkVersion 升至 33。 影响Android 13上所有应用 1.通知受限 对新安装的应用的影响: 如果用户在搭载 Android 13 或更高版本的设备上安装您的应用,应用的通知默认处于关闭状态。在您请求新的…

多通道振弦传感器无线采集仪通过短信和FTP文件修改参数

多通道振弦传感器无线采集仪通过短信和FTP文件修改参数 通过短信修改参数 向设备发送参数修改指令,设备在下次采发过程中若收到包含有合法指令的短信时会解析并执行短信内的指令,参数修改完成后会以短信形式回发应答信息。短信指令的格式如下&#xff1a…

各种ID生成策略对比

1. id⾃增的劣势 问题:当数据量庞⼤时,在数据库分库分表后,数据库⾃增id不能满⾜唯⼀id来标识数据;因为每个表都按⾃⼰节奏⾃增,会造成id冲突,⽆法满⾜需求。 所以分布式id就有了一定规则 - 全局唯一&…

三角函数最小正周期

由于 2 π 是正弦函数 y sin ⁡ x , x ∈ R 的周期, 由于2\pi是正弦函数y\sin x,x\in R的周期, 由于2π是正弦函数ysinx,x∈R的周期, 下面只需证明任一小于 2 π 的正数都不是那个函数的周期。 下面只需证明任一小于2\pi的正数都不是那个函数…

USB2.0(一):基础

一、总线标准 USB1.1:支持12Mbps全速率(FullSpeed)和1.5Mbps低速率( HalfSpeed)USB2.0:支持480Mbps高速率(High Speed),兼容1.1USB3.0:支持5Gbps超高速率&am…