目录
初识材质与纹理
修改模型材质颜色
模型添加纹理
纹理常用属性使用
纹理显示算法
设置粗糙度
纹理加载进度情况
设置环境贴图
初识材质与纹理
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.EquirectangularReflectionMapping
scene.background = texture
scene.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.EquirectangularReflectionMapping
scene.background = texture
scene.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 = true
export function render(){
// 每次循环渲染时调用stats更新方法,来刷新时间
controls.update()
renderer.render(scene,camera) // 周期性执行相机的渲染功能,更新canvas画布上的内容
requestAnimationFrame(render) // 接下来渲染下一帧的时候就会调用render函数
}
// 先开始就渲染一下
render()