threejs视频教程学习(4):贴图、材质、光线 您所在的位置:网站首页 3d材质颜色 threejs视频教程学习(4):贴图、材质、光线

threejs视频教程学习(4):贴图、材质、光线

2022-12-24 06:10| 来源: 网络整理| 查看: 265

获取材质贴图(3d模型)

https://www.poliigon.com/

https://www.textures.com/

https://www.qingmo.com/

https://pixabay.com/zh/

https://ambientcg.com/list

网站里提供了一些纹理图片和简单的模型

map 颜色贴图 基础网格材质(MeshBasicMaterial)

一个以简单着色(平面或线框)方式来绘制几何体的材质。这种材质不受光照的影响。 不受光照影响说明不需要添加光源就可以看见物体

import { onMounted } from 'vue'; import * as THREE from 'three'; // 导入轨道控制器,模块化开发导入的是jsm不是js import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'; onMounted(() => { // 添加一个场景 const scene = new THREE.Scene(); // 创建一个透视相机,摄像机的视野是一个圆锥,顶点就是摄像机的位置 const camera = new THREE.PerspectiveCamera( 75, // 摄像机视锥体垂直视野角度 window.innerWidth / window.innerHeight, // 摄像机视锥体长宽比 0.1, // 摄像机视锥体近端面 1000 // 摄像机视锥体远端面 ); // 设置相机的位置 camera.position.set(0, 0, 10); // x、y、z // 把相机添加到场景中 scene.add(camera); // 创建几何体 const geometry = new THREE.BoxGeometry(2, 2, 2); // 设置材质 const basicMaterial = new THREE.MeshBasicMaterial( { color: '#3f7b9d', } ); // 创建物体 const cube = new THREE.Mesh(geometry, basicMaterial); // 将立方体添加到场景中 scene.add(cube); // 初始化渲染器 const renderer = new THREE.WebGLRenderer(); // 设置渲染的尺寸大小 renderer.setSize(800, 600); // 将wbgl渲染的canvas内容添加到dom元素中 document.getElementById('container')?.appendChild(renderer.domElement); // 创建轨道控制器 const controls = new OrbitControls(camera, renderer.domElement); // 设置控制器阻尼,让物体拥有惯性,必须在动画循环里调用update() controls.enableDamping = true; // 添加坐标轴辅助器 const axesHelper = new THREE.AxesHelper(5); scene.add(axesHelper); // 创建一个渲染函数,当场景发生变化后重新渲染 const render = () => { controls.update(); renderer.render(scene, camera); // 使用浏览器自带的请求动画帧函数不断的进行渲染 requestAnimationFrame(render); }; render(); });

在这里插入图片描述

设置纹理 // 导入纹理 const textureLoader = new THREE.TextureLoader(); const door = textureLoader.load('../../../../public/color.jpg'); // 设置材质 const basicMaterial = new THREE.MeshBasicMaterial( { color: 'yellow', map: door } );

在这里插入图片描述 材质的颜色对纹理的颜色是有影响的。

alphaMap 透明度贴图

alpha贴图是一张灰度纹理,用于控制整个表面的不透明度。(黑色:完全透明;白色:完全不透明)。 默认值为null。

透明度贴图可以用于场景空隙,比如铁栅栏。 在这里插入图片描述

// 导入纹理 const textureLoader = new THREE.TextureLoader(); // 颜色贴图 const door = textureLoader.load('../../../../public/color.jpg'); // 透明贴图 const alpha = textureLoader.load('../../../../public/alpha.jpg'); // 设置材质 const basicMaterial = new THREE.MeshBasicMaterial( { color: 'yellow', map: door, // 颜色贴图 alphaMap: alpha, // 透明贴图 transparent: true // 必须要设置,否则透明贴图不会生效 } );

在这里插入图片描述

环境遮挡贴图

aoMap,个人觉得用于遮挡物体表面的光照,使物体表面出现阴影

// 导入纹理 const textureLoader = new THREE.TextureLoader(); // 颜色贴图 const door = textureLoader.load('../../../../public/color.jpg'); // 透明贴图 const alpha = textureLoader.load('../../../../public/alpha.jpg'); // 环境遮挡贴图 const aoMap = textureLoader.load('../../../../public/ambientOcclusion.jpg'); // 创建几何体 const geometry = new THREE.BoxGeometry(2, 2, 2); // 设置材质 const basicMaterial = new THREE.MeshBasicMaterial( { color: 'yellow', map: door, // 颜色贴图 alphaMap: alpha, // 透明贴图 transparent: true, // 必须要设置,否则透明贴图不会生效 aoMap: aoMap // 环境遮挡贴图 } ); // 创建物体 const cube = new THREE.Mesh(geometry, basicMaterial); // 将立方体添加到场景中 scene.add(cube); // 环境遮挡贴图需要第二组UV才能够生效,获取材质本身的UV geometry.setAttribute('uv2', new THREE.BufferAttribute(geometry.attributes.uv.array, 2));

在这里插入图片描述

物料渲染

标准网格材质(MeshStandardMaterial)。一种基于物理的标准材质,使用Metallic-Roughness工作流程。 基于物理的渲染(PBR)最近已成为许多3D应用程序的标准,例如Unity, Unreal和 3D Studio Max。使用标准网格材质必须要添加光源

环境光

AmbientLight,环境光会均匀的照亮场景中的所有物体。环境光不能用来投射阴影,因为它没有方向。

// 设置材质 const meshMaterial = new THREE.MeshStandardMaterial( { color: 'yellow', map: door, // 颜色贴图 alphaMap: alpha, // 透明贴图 transparent: true, // 必须要设置,否则透明贴图不会生效 aoMap: aoMap // 环境遮挡贴图 } ); // 创建物体 const cube = new THREE.Mesh(geometry, meshMaterial); // 将立方体添加到场景中 scene.add(cube); // 环境遮挡贴图需要第二组UV才能够生效,获取材质本身的UV geometry.setAttribute('uv2', new THREE.BufferAttribute(geometry.attributes.uv.array, 2)); // 添加灯光,环境光, const light = new THREE.AmbientLight(0xffffff,0.6); // 设置环境光的颜色和亮度,亮度最大是1 scene.add(light);

在这里插入图片描述

平行光

DirectionalLight,平行光是沿着特定方向发射的光。这种光的表现像是无限远,从它发出的光线都是平行的。常常用平行光来模拟太阳光 的效果; 平行光可以投射阴影

// 添加灯光,环境光 const light = new THREE.AmbientLight(0xffffff, 0.6); scene.add(light); // 添加平行光 const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5); directionalLight.position.set(10, 0, 0); // 设置平行光是从x轴方向照射 scene.add(directionalLight);

在这里插入图片描述

位移贴图

displacementMap ,位移贴图会影响网格顶点的位置,与仅影响材质的光照和阴影的其他贴图不同,移位的顶点可以投射阴影,阻挡其他对象, 以及充当真实的几何体。根据贴图的颜色来进行凸显,颜色约白位置越高。

贴图材料

在这里插入图片描述

// 位移贴图 const displace = textureLoader.load('../../../../public/height.jpg'); // 创建几何体,增加顶点数 const geometry = new THREE.BoxGeometry(2, 2, 2, 100, 100, 100); // 设置材质 const meshMaterial = new THREE.MeshStandardMaterial( { color: 'yellow', map: door, // 颜色贴图 alphaMap: alpha, // 透明贴图 transparent: true, // 必须要设置,否则透明贴图不会生效 aoMap: aoMap, // 环境遮挡贴图 displacementMap: displace, // 位移贴图 displacementScale: 0.2 // 设置位移贴图对网格的影响 } );

注意点: 1、必须给物体增加分段数,默认物体就是一整块,增加分段数后,就是由多块组合而成,这样位移贴图才能生效,使某些板块突出出来 2、设置displacementScale,设置位移贴图对网格的影响成都 在这里插入图片描述

粗糙度贴图

roughness 材质的粗糙程度。0.0表示平滑的镜面反射,1.0表示完全漫反射。默认值为1.0。如果还提供roughnessMap,则两个值相乘。

roughnessMap 该纹理的绿色通道用于改变材质的粗糙度。黑色代表光滑,白色代表不光滑 在这里插入图片描述

// 设置材质 const meshMaterial = new THREE.MeshStandardMaterial( { color: 'yellow', map: door, // 颜色贴图 alphaMap: alpha, // 透明贴图 transparent: true, // 必须要设置,否则透明贴图不会生效 aoMap: aoMap, // 环境遮挡贴图 displacementMap: displace, // 位移贴图 displacementScale: 0.2, // 设置位移贴图对网格的影响 roughness: 0 // 粗糙度 } );

很明显我们可以看见灯光 在这里插入图片描述

// 导入粗糙度贴图 const roughMap = textureLoader.load('../../../../public/roughness.jpg'); // 创建几何体,增加顶点数 const geometry = new THREE.BoxGeometry(2, 2, 2, 100, 100, 100); // 设置材质 const meshMaterial = new THREE.MeshStandardMaterial( { color: 'yellow', map: door, // 颜色贴图 alphaMap: alpha, // 透明贴图 transparent: true, // 必须要设置,否则透明贴图不会生效 aoMap: aoMap, // 环境遮挡贴图 displacementMap: displace, // 位移贴图 displacementScale: 0.2, // 设置位移贴图对网格的影响 roughness: 1, // 粗糙度 roughnessMap: roughMap // 粗糙度贴图 } ); 金属贴图

metalness 材质与金属的相似度。非金属材质,如木材或石材,使用0.0,金属使用1.0,通常没有中间值。 默认值为0.0。0.0到1.0之间的值可用于生锈金属的外观。如果还提供了metalnessMap,则两个值相乘。 metalnessMap 该纹理的蓝色通道用于改变材质的金属度。

// 设置材质 const meshMaterial = new THREE.MeshStandardMaterial( { color: 'yellow', map: door, // 颜色贴图 alphaMap: alpha, // 透明贴图 transparent: true, // 必须要设置,否则透明贴图不会生效 aoMap: aoMap, // 环境遮挡贴图 displacementMap: displace, // 位移贴图 displacementScale: 0.2, // 设置位移贴图对网格的影响 roughness: 1, // 粗糙度 roughnessMap: roughMap, // 粗糙度贴图 metalness: 1 // 金属度 } );

设置金属度后,门会变成金属材质,没有光照的部分会看不见。 在这里插入图片描述 使用金属贴图,只让金属的部分变成金属材质 在这里插入图片描述

// 金属贴图 const metaMap = textureLoader.load('../../../../public/metalness.jpg'); // 创建几何体,增加顶点数 const geometry = new THREE.BoxGeometry(2, 2, 2, 100, 100, 100); // 设置材质 const meshMaterial = new THREE.MeshStandardMaterial( { color: 'yellow', map: door, // 颜色贴图 alphaMap: alpha, // 透明贴图 transparent: true, // 必须要设置,否则透明贴图不会生效 aoMap: aoMap, // 环境遮挡贴图 displacementMap: displace, // 位移贴图 displacementScale: 0.2, // 设置位移贴图对网格的影响 roughness: 1, // 粗糙度 roughnessMap: roughMap, // 粗糙度贴图 metalness: 0, // 金属度 metalnessMap: metaMap // 金属贴图 } ); 法线贴图

normalMap 用于创建法线贴图的纹理。RGB值会影响每个像素片段的曲面法线,并更改颜色照亮的方式。法线贴图不会改变曲面的实际形状,只会改变光照

法线贴图的图片是有颜色的图 在这里插入图片描述

// 法线贴图 const normalMap = textureLoader.load('../../../../public/normal.jpg'); // 创建几何体,增加顶点数 const geometry = new THREE.BoxGeometry(2, 2, 2, 100, 100, 100); // 设置材质 const meshMaterial = new THREE.MeshStandardMaterial( { color: 'yellow', map: door, // 颜色贴图 alphaMap: alpha, // 透明贴图 transparent: true, // 必须要设置,否则透明贴图不会生效 aoMap: aoMap, // 环境遮挡贴图 displacementMap: displace, // 位移贴图 displacementScale: 0.2, // 设置位移贴图对网格的影响 roughness: 1, // 粗糙度 roughnessMap: roughMap, // 粗糙度贴图 metalness: 0, // 金属度 metalnessMap: metaMap, // 金属贴图 normalMap: normalMap // 法线贴图 } );

在这里插入图片描述 对比之前的图可以看到,光并不是一个完整的圆圈了。 在这里插入图片描述

完整代码

import { onMounted } from 'vue'; import * as THREE from 'three'; // 导入轨道控制器,模块化开发导入的是jsm不是js import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'; onMounted(() => { // 添加一个场景 const scene = new THREE.Scene(); // 创建一个透视相机,摄像机的视野是一个圆锥,顶点就是摄像机的位置 const camera = new THREE.PerspectiveCamera( 75, // 摄像机视锥体垂直视野角度 window.innerWidth / window.innerHeight, // 摄像机视锥体长宽比 0.1, // 摄像机视锥体近端面 1000 // 摄像机视锥体远端面 ); // 设置相机的位置 camera.position.set(0, 0, 10); // x、y、z // 把相机添加到场景中 scene.add(camera); // 导入纹理 const textureLoader = new THREE.TextureLoader(); // 颜色贴图 const door = textureLoader.load('../../../../public/color.jpg', () => { console.log('颜色贴图加载完成'); }); // 透明贴图 const alpha = textureLoader.load('../../../../public/alpha.jpg'); // 环境遮挡贴图 const aoMap = textureLoader.load('../../../../public/ambientOcclusion.jpg'); // 位移贴图 const displace = textureLoader.load('../../../../public/height.jpg'); // 导入粗糙度贴图 const roughMap = textureLoader.load('../../../../public/roughness.jpg'); // 金属贴图 const metaMap = textureLoader.load('../../../../public/metalness.jpg'); // 法线贴图 const normalMap = textureLoader.load('../../../../public/normal.jpg'); // 创建几何体,增加顶点数 const geometry = new THREE.BoxGeometry(2, 2, 2, 100, 100, 100); // 设置材质 const meshMaterial = new THREE.MeshStandardMaterial( { color: 'yellow', map: door, // 颜色贴图 alphaMap: alpha, // 透明贴图 transparent: true, // 必须要设置,否则透明贴图不会生效 aoMap: aoMap, // 环境遮挡贴图 displacementMap: displace, // 位移贴图 displacementScale: 0.2, // 设置位移贴图对网格的影响 roughness: 1, // 粗糙度 roughnessMap: roughMap, // 粗糙度贴图 metalness: 0, // 金属度 metalnessMap: metaMap, // 金属贴图 normalMap: normalMap // 法线贴图 } ); // 创建物体 const cube = new THREE.Mesh(geometry, meshMaterial); // 将立方体添加到场景中 scene.add(cube); // 环境遮挡贴图需要第二组UV才能够生效,获取材质本身的UV geometry.setAttribute('uv2', new THREE.BufferAttribute(geometry.attributes.uv.array, 2)); // 添加灯光,环境光 const light = new THREE.AmbientLight(0xffffff, 0.6); scene.add(light); // 添加平行光 const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5); directionalLight.position.set(10, 0, 0); // 设置平行光是从x轴方向照射 scene.add(directionalLight); // 初始化渲染器 const renderer = new THREE.WebGLRenderer(); // 设置渲染的尺寸大小 renderer.setSize(800, 600); // 将wbgl渲染的canvas内容添加到dom元素中 document.getElementById('container')?.appendChild(renderer.domElement); // 创建轨道控制器 const controls = new OrbitControls(camera, renderer.domElement); // 设置控制器阻尼,让物体拥有惯性,必须在动画循环里调用update() controls.enableDamping = true; // 添加坐标轴辅助器 const axesHelper = new THREE.AxesHelper(5); scene.add(axesHelper); // 创建一个渲染函数,当场景发生变化后重新渲染 const render = () => { controls.update(); renderer.render(scene, camera); // 使用浏览器自带的请求动画帧函数不断的进行渲染 requestAnimationFrame(render); }; render(); }); 纹理加载进度

TextureLoader类提供了load方法,前面我们只是用来加载文件,下面看一下它的回调 TextureLoader提供了几个方法:

单张纹理加载

// 导入纹理 const textureLoader = new THREE.TextureLoader(); // 颜色贴图 const door = textureLoader.load('../../../../public/color.jpg', () => { console.log('颜色贴图加载完成'); }); LoadingManager

其功能是处理并跟踪已加载和待处理的数据。具体内容见官方文档

环境贴图

例如有一个光滑的金属小球,真实情况下,小球表面是可以显示出周围的环境的。这个效果可以通过环境贴图来实现 在这里插入图片描述

envMap 环境贴图,为了能够保证物理渲染准确,您应该添加由PMREMGenerator预处理过的环境贴图,默认为null。

envMapIntensity 通过乘以环境贴图的颜色来缩放环境贴图的效果。

import { onMounted } from 'vue'; import * as THREE from 'three'; // 导入轨道控制器,模块化开发导入的是jsm不是js import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'; onMounted(() => { // 添加一个场景 const scene = new THREE.Scene(); // 创建一个透视相机,摄像机的视野是一个圆锥,顶点就是摄像机的位置 const camera = new THREE.PerspectiveCamera( 75, // 摄像机视锥体垂直视野角度 window.innerWidth / window.innerHeight, // 摄像机视锥体长宽比 0.1, // 摄像机视锥体近端面 1000 // 摄像机视锥体远端面 ); // 设置相机的位置 camera.position.set(0, 0, 10); // x、y、z // 把相机添加到场景中 scene.add(camera); // 环境贴图 const envMap = new THREE.CubeTextureLoader() .setPath('../../../../public/env/') .load([ 'px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg' ]); // 创建球体,半径1,20是分段 const spherGeometry = new THREE.SphereGeometry(1, 20, 20); const spherMaterial = new THREE.MeshStandardMaterial({ metalness: 0.7, // 金属度 roughness: 0.1, // 粗糙度 envMap: envMap // 环境贴图 }); // 创建物体 const cube = new THREE.Mesh(spherGeometry, spherMaterial); // 将立方体添加到场景中 scene.add(cube); // 添加灯光,环境光 const light = new THREE.AmbientLight(0xffffff, 0.6); scene.add(light); // 添加平行光 const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5); directionalLight.position.set(10, 0, 0); // 设置平行光是从x轴方向照射 scene.add(directionalLight); // 初始化渲染器 const renderer = new THREE.WebGLRenderer(); // 设置渲染的尺寸大小 renderer.setSize(800, 600); // 将wbgl渲染的canvas内容添加到dom元素中 document.getElementById('container')?.appendChild(renderer.domElement); // 创建轨道控制器 const controls = new OrbitControls(camera, renderer.domElement); // 设置控制器阻尼,让物体拥有惯性,必须在动画循环里调用update() controls.enableDamping = true; // 添加坐标轴辅助器 const axesHelper = new THREE.AxesHelper(5); scene.add(axesHelper); // 创建一个渲染函数,当场景发生变化后重新渲染 const render = () => { controls.update(); renderer.render(scene, camera); // 使用浏览器自带的请求动画帧函数不断的进行渲染 requestAnimationFrame(render); }; render(); });

1、环境贴图的加载必须按照顺序来,分别是px(正方向的x轴贴图)、nx(负方向的x轴贴图)、py(正方形的y轴贴图)、ny(负方向的y轴贴图)、pz(正方形的z轴贴图)、nz(负方向的轴贴图) 2、必须要给物体设置金属度和光滑度,只设置环境贴图是无用的

在这里插入图片描述

设置场景的背景 // 给场景设置背景 scene.background = envMap; // 给场景内的所有问题添加默认的环境贴图,如果场景内的物体有环境贴图则使用自身的,没有则使用默认的 scene.environment = envMap;

在这里插入图片描述

HDR环境图的设置

对应HDR指令的文件需要使用DataTextureLoader加载器,用于加载二进制文件格式的(rgbe, hdr, …)的抽象类。 内部使用FileLoader来加载文件, 和创建一个新的 DataTexture.

import {RGBELoader} from 'three/examples/jsm/loaders/RGBELoader' const rgbeloader = new RGBELoader(); rgbeloader.loadAsync('../../../../public/002.hdr') .then((texture) => { // 设置纹理映射类型 texture.mapping = THREE.EquirectangularReflectionMapping; scene.background = texture; });

在这里插入图片描述

灯光与阴影

常用光

平行光(DirectionalLight)、点光源(PointLight)、聚光灯(SpotLight)可以产生阴影。 平行光:平行光是沿着特定方向发射的光。 点光源:从一个点向各个方向发射的光源。 聚光灯:光线从一个点沿一个方向射出,随着光线照射的变远,光线圆锥体的尺寸也逐渐增大。比如手电筒

环境光(AmbientLight)、平面光(RectAreaLight)不可以产生阴影 环境光:环境光会均匀的照亮场景中的所有物体。环境光不能用来投射阴影,因为它没有方向。 平面光:平面光光源从一个矩形平面上均匀地发射光线。这种光源可以用来模拟像明亮的窗户或者条状灯光光源。

常用材质 基础网格材质(MeshBasicMaterial)不受光照的影响 ,标准网格材质(MeshStandardMaterial)受光照的影响。其他材质像我这种入门者应该也用不到就不介绍了。

灯光阴影

1、材质要满足对光照有反应 2、设置渲染器开启阴影的计算 3、设置光照投射阴影 4、设置物体投射阴影 5、设置物体接收阴影 6、要注意光照的角度

import { onMounted } from 'vue'; import * as THREE from 'three'; // 导入轨道控制器,模块化开发导入的是jsm不是js import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'; onMounted(() => { // 添加一个场景 const scene = new THREE.Scene(); // 创建一个透视相机,摄像机的视野是一个圆锥,顶点就是摄像机的位置 const camera = new THREE.PerspectiveCamera( 75, // 摄像机视锥体垂直视野角度 window.innerWidth / window.innerHeight, // 摄像机视锥体长宽比 0.1, // 摄像机视锥体近端面 1000 // 摄像机视锥体远端面 ); // 设置相机的位置 camera.position.set(0, 0, 10); // x、y、z // 把相机添加到场景中 scene.add(camera); // 创建球体,半径1,20是分段 const spherGeometry = new THREE.SphereGeometry(1, 20, 20); const material = new THREE.MeshStandardMaterial(); const cube = new THREE.Mesh(spherGeometry, material); // 球体 cube.castShadow = true; // 设置球体可以投射阴影 // 将立方体添加到场景中 scene.add(cube); // 创建平面并添加到场景中 const planeGeometry = new THREE.PlaneGeometry(10, 10, 10, 10); // 平面物体 const plane = new THREE.Mesh(planeGeometry, material); // 平面 plane.position.set(0, -1, 0); plane.rotation.x = -Math.PI / 2; // 设置平面可以接收来自球的阴影 plane.receiveShadow = true; scene.add(plane); // 添加灯光,环境光 const light = new THREE.AmbientLight(0xffffff, 0.6); scene.add(light); // 添加平行光 const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5); directionalLight.position.set(15, 10, 0); // 设置平行光是从x轴方向照射 directionalLight.castShadow = true; // 设置光照产生阴影 scene.add(directionalLight); // 初始化渲染器 const renderer = new THREE.WebGLRenderer(); // 设置渲染的尺寸大小 renderer.setSize(800, 600); // 开启场景阴影渲染 renderer.shadowMap.enabled = true; // 将wbgl渲染的canvas内容添加到dom元素中 document.getElementById('container')?.appendChild(renderer.domElement); // 创建轨道控制器 const controls = new OrbitControls(camera, renderer.domElement); // 设置控制器阻尼,让物体拥有惯性,必须在动画循环里调用update() controls.enableDamping = true; // 添加坐标轴辅助器 const axesHelper = new THREE.AxesHelper(5); scene.add(axesHelper); // 创建一个渲染函数,当场景发生变化后重新渲染 const render = () => { controls.update(); renderer.render(scene, camera); // 使用浏览器自带的请求动画帧函数不断的进行渲染 requestAnimationFrame(render); }; render(); });

在这里插入图片描述



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有