Three.js 纹理贴图 – 环境贴图 – 纹理贴图 – 透明贴图 – 高光贴图

45,589次阅读
没有评论

共计 9143 个字符,预计需要花费 23 分钟才能阅读完成。

文章目录

  • Three.js 纹理贴图
    • 纹理贴图 map 属性
      • 纹理贴图的映射方式 texture.Mapping
      • 纹理贴图的色彩空间 texture.colorSpace
        • 中途更新纹理的色彩空间 texture.needsUpdate
      • 纹理加载器 THREE.TextureLoader
        • 监听单个材质
        • 监听多个材质 – LoadingManager 类
      • 颜色贴图与材质的颜色
      • 纹理对象 Texture 阵列 – texture.wrapS、texture.wrapT 与 texture.repeat
      • 案例:矩形 Mesh+ 背景透明 png 贴图
      • 案例:uv 动画 – 纹理对象的偏移属性 offset
        • 纹理贴图阵列 + UV 动画
    • 环境贴图
      • 添加环境贴图 mesh 材质的 envMap 属性
        • 案例:使用一个全景图作为环境贴图
      • 使用立方体纹理加载器 CubeTextureLoader 加载环境贴图
    • 透明贴图 mesh 的 alphaMap 属性 / 高光贴图 mesh 的 specularMap 属性 / 光照贴图 mesh 的 lightMap 属性 / 环境遮挡贴图 mesh 的 aoMap 属性

Three.js 纹理贴图

  • 纹理贴图加载器 TextureLoader.load()方法加载一张图片,返回一个纹理对象Texture
  • 立方体纹理加载器 CubeTextureLoader.load()方法加载 6 张图片,返回一个立方体纹理对象 CubeTexture 立方体纹理对象 CubeTexture 的父类是纹理对象 Texture

网格材质 Mesh 的贴图属性

属性 描述 其他
map:Texture 材质的颜色贴图 使用范围:除 MeshPhysicalMaterial
envMap : Texture 环境贴图
alphaMap: 透明贴图
alpha 贴图是一张灰度纹理,用于控制整个表面的透明度。
需要开启材质的透明度属性
specularMap : Texture 高光贴图用于控制对象表面的高光反射强度和位置,通常使用灰度图像来表示不同的反射强度值。 可以通过 reflectivity 属性设置反射强度

纹理贴图 map 属性

纹理贴图的映射方式 texture.Mapping

属性默认值:texture.Mapping = THREE.UVMapping
属性含义:如何将纹理题图应用到几何体表面

  • mapping 是一种将纹理贴到几何体表面上的技术
  • cube mapping 则是一种将纹理贴到立方体表面上的技术。
属性值 描述 使用
THREE.UVMapping UV 贴图 将二维纹理映射到三维物体表面的过程。在 Three.js 中,每个几何体都有一个 UV 坐标系,和几何体表面上的三角形网格一一对应。UV 坐标系中的每个点都映射到纹理图像上的一个像素,用来确定几何体表面的纹理贴图。 U,V 坐标用来应用映射,要求是单个纹理。
一般与网格材质的 map 属性配合使用。
THREE.CubeReflectionMapping 立方体反射映射 该映射模式将环境贴图作为一个立方体贴图,将六个面分别映射到对应的立方体面上,以模拟立方体环境映射和反射效果。 cubeTexture.mapping 的默认值
THREE.CubeRefractionMapping 立方体折射映射 使用一个立方体贴图来表示环境光的折射,可以用来模拟环境光和镜面反射等效果 该映射模式与 THREE.CubeReflectionMapping 类似,但是它模拟的是折射效果,环境贴图中的物体看作透明的,经过物体的折射后反射到表面上。
THREE.EquirectangularReflectionMapping 圆柱反射映射 将环境贴图作为一个全景图片,将图片映射到球体或半球体上,以模拟球形环境映射和反射效果。 类似 cube mapping,只不过不是用立方体贴图,而是使用单个贴图?

可以配合材质的 envMap 属性使用

THREE.EquirectangularRefractionMapping 圆柱折射映射 该映射模式与 THREE.EquirectangularReflectionMapping 类似,但是模拟的是折射效果,即将环境贴图中的物体看作透明的,经过物体的折射后反射到表面上。 可以配合材质的 envMap 属性使用

纹理贴图的色彩空间 texture.colorSpace

在着色器中色值的提取与色彩的计算操作一般都是在线性空间。在 webGL 中,贴图或者颜色以 sRGB 传入时,必须转换为线性空间。计算完输出后再将线性空间转为 sRGB 空间。

属性值 描述
默认值:THREE.NoColorSpace 无色彩空间
THREE.SRGBColorSpace=“srgb”sRGB 模式 在感知光的强度方向均匀分布的灰度条
物理上的线性颜色空间,当计算机需要对 sRGB 像素运行图像处理算法时,一般会采用线性颜色空间计算。
THREE.LinearSRGBColorSpace =“srgb-linear”线性模式 按照发射光的轻度均匀分布的灰度条
sRGB 是当今一般电子设备及互联网图像上的标准颜色空间。较适应人眼的感光。

Three.js 纹理贴图 - 环境贴图 - 纹理贴图 - 透明贴图 - 高光贴图
可以理解为: 在物理上 18% 亮度时人眼感知到的是 50% 亮度

中途更新纹理的色彩空间 texture.needsUpdate

如果在中途修改色彩空间,需要设置 texture.needsUpdate=true 才可以生效。

案例
比如采用 gui 交互控制器,修改色彩空间。如果中途修改色彩空间,不会生效,需要设置更新纹理才能生效。

gui.add(texture, 'colorSpace', {
  sRGB: THREE.SRGBColorSpace,
  liner: THREE.LinearSRGBColorSpace 
}).onChange( => {
  texture.needsUpdate  = true 
})

Three.js 纹理贴图 - 环境贴图 - 纹理贴图 - 透明贴图 - 高光贴图

纹理加载器 THREE.TextureLoader

纹理加载器:new THREE.TextureLoader(manager : LoadingManager)
参数:加载器使用的 loadingManager,默认值为THREE.DefaultLoadingManager
继承链:Loader → TextureLoader
返回值:返回创建的纹理加载器TextureLoader.

纹理对象的属性和方法

属性名和方法名 描述
texture.offset:Vector2 贴图单次重复中的起始偏移量(偏移贴图在 Mesh 上位置),分别表示 U 和 V。

加载纹理 - 得到纹理对象
textureLoader.load (url : String, onLoad : (texture)=>{}, onProgress : Function, onError : Function) : Texture
返回值:新的纹理对象 texture,该纹理对象可以用于材质创建
注意点:异步加载,第三个参数在后续版本好像被遗弃了可以用 undefined 暂时占位

监听单个材质
import tile from "./assets/tile.jpg";


const loader = new THREE.TextureLoader();


loader.load(
    
    tile,

    
    function ( texture ) {
        
        const material = new THREE.MeshBasicMaterial( {
            map: texture
         } );
    },
 
    
    undefined,

    
    function ( err ) {
        console.error( '材质加载失败' );
    }
)
监听多个材质 – LoadingManager 类

语法:LoadingManager(onLoad:Function,onProgress:Function,, onError:Function,)
说明:处理并跟踪已加载和待处理的数据。
参数
onLoad: 所有加载器加载完成后,将调用此函数。
onProgress: 当每个项目完成后,将调用此函数。
onError: 当一个加载器遇到错误时,将调用此函数。


const loadingManager = new THREE.LoadingManager(
  function() {
    console.log('图片加载完成')
  },
  function(url, loaded, total) {
    console.log(`图片加载中,本次加载的材质${url},第 ${loaded}/${total} 个材质`)
  },
  function(err) {
    console.log('图片加载失败', err)
  }
)


const textureLoader = new THREE.TextureLoader(loadingManager)


const imgTexture1 = textureLoader.load('../assets/images/140.jpg')
const imgTexture2 = textureLoader.load('../assets/images/141.jpg')

执行输出

图片加载中,本次加载的材质../assets/images/140.jpg,第 1/2 个材质
图片加载中,本次加载的材质../assets/images/141.jpg,第 2/2 个材质
图片加载完成

颜色贴图与材质的颜色

在 vur 中的引入方式
方式 1. 先 import 引入然后作为参数传递给 load
方式 2. 将图片存储在 public 公共文件夹下


import map from "./assets/map.jpg";
const texLoader = new THREE.TextureLoader();
const texture = texLoader.load(map)


import panda from "/panda.png";
const material = new THREE.MeshLambertMaterial({
  map:texLoader.load( panda),
});

const material = new THREE.MeshLambertMaterial({
  map:texLoader.load('../public/panda.png'),
});


const texture = texLoader.load('./assets/map.jpg')

public 里的文件不会处理,直接复制到打包文件。文件中的绝对地址也不会解析所以可以将图片放到 public 中。.开头的地址会被理解为相对地址,webpack 会解析地址加载图片,这里不知道是不是 load 的参数没有被理解为相对地址去解析,所以才会报错?

vue 中引入图片失败的原因及解决办法

材质的颜色贴图属性 .map 设置后,模型会从纹理贴图上采集像素值,这时候一般来说不需要再设置材质颜色.color

颜色贴图 mapcolor属性颜色值会混合。如果没有特殊需要,设置了颜色贴图 .map 就不用设置·color

纹理对象 Texture 阵列 – texture.wrapS、texture.wrapT 与 texture.repeat

阵列就是不断的重复,如果使用一个规则的图形,load 只需要加载一小部分,然后通过阵列完全显示,加快贴图加载的速度。

属性名 描述 参考值
texture.wrapS:number 定义了纹理贴图在水平方向上将如何 包裹,在 UV 映射中对应于 U 可选纹理常量中的包裹模式三个选项,默认是 THREE.ClampToEdgeWrapping
texture.wrapT :number 纹理贴图在垂直方向上将如何包裹,在 UV 映射中对应于 V
texture.repeat:Vector2 决定纹理在表面的重复次数,两个方向分别表示 U 和 V

包裹模式的可选值

包裹模式 描述
THREE.RepeatWrapping 纹理将简单地重复到无穷大
THREE.ClampToEdgeWrapping 纹理中的最后一个像素将延伸到网格的边缘
THREE.MirroredRepeatWrapping 在每次重复时将进行镜像
import tile from "./assets/tile.jpg";

const geometry = new THREE.PlaneGeometry(300, 250);


const texLoader = new THREE.TextureLoader();
const texture = texLoader.load(tile)


texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;

texture.repeat.set(8,8);
const material = new THREE.MeshLambertMaterial({
  map:texture,
});

Three.js 纹理贴图 - 环境贴图 - 纹理贴图 - 透明贴图 - 高光贴图

案例:矩形 Mesh+ 背景透明 png 贴图

想要 png 贴图完全透明的部分不显示,需要将材质的 transparent 属性打开。


import direction from "./assets/direction .jpg";
const geometry = new THREE.PlaneGeometry(60, 60); 
const textureLoader = new THREE.TextureLoader();
const material = new THREE.MeshBasicMaterial({
    map: textureLoader.load(direction ),        
    transparent: true, 
});
const mesh = new THREE.Mesh(geometry, material);
mesh.rotateX(-Math.PI / 2);

案例:uv 动画 – 纹理对象的偏移属性 offset

偏移之后的左边部分被截掉,右边的剩余部分为图片最后 1px 无限重复


function render() {
    texture.offset.x +=0.001;
    renderer.render(scene, camera);
    requestAnimationFrame(render);
}
render();

Three.js 纹理贴图 - 环境贴图 - 纹理贴图 - 透明贴图 - 高光贴图

纹理贴图阵列 + UV 动画

开启阵列之后,左边偏移消失的地方会拼接到右边偏移之后多出来的地方(首尾相连)

import * as THREE from "three";
import panda from "/panda.png";

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
  45,
  window.innerWidth / window.innerHeight, 
  1,
  8000
);
camera.position.set(300,300,300)

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);

const geometry = new THREE.PlaneGeometry(200, 200);
const loader = new THREE.TextureLoader();
const texture = loader.load(panda)

texture.wrapS = THREE.RepeatWrapping;

texture.repeat.x=2;
const material = new THREE.MeshBasicMaterial( {
  map: texture
} );
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

const ambient = new THREE.AmbientLight(0xffffff,3)
scene.add(ambient);

document.body.appendChild(renderer.domElement);

function render() {
    texture.offset.x +=0.1;
    renderer.render(scene, camera);
    requestAnimationFrame(render);
}
render();

Three.js 纹理贴图 - 环境贴图 - 纹理贴图 - 透明贴图 - 高光贴图

环境贴图

环境贴图是一类用于 模拟环境反射光照 的一种 3D 技术

为什么叫天空盒
OpenGL 中天空盒的思想就是绘制一个大的立方体,然后将观察者放在立方体的中心,当相机移动时,这个立方体也跟着相机一起移动,这样相机就永远不会运动到场景的边缘。

Three.js 纹理贴图 - 环境贴图 - 纹理贴图 - 透明贴图 - 高光贴图

添加环境贴图 mesh 材质的 envMap 属性

给模型设置环境贴图后,可以将光反射的环境部分映射到模型上(类似镜子将人反射在镜子上面)。

使用下图作为环境贴图
Three.js 纹理贴图 - 环境贴图 - 纹理贴图 - 透明贴图 - 高光贴图
这里一定要将设置 envMap.mapping,不然模型就是一片黑色,这里设置成THREE.EquirectangularReflectionMappingTHREE.EquirectangularRefractionMapping都可以。


const geometry = new THREE.PlaneGeometry(200, 200);
const loader = new THREE.TextureLoader();
const texture = loader.load("/assets/door.png") 
const material = new THREE.MeshBasicMaterial({
  map: texture,
});
loader.load("/assets/test.jpg",(envMap)=>{
  envMap.mapping = THREE.EquirectangularReflectionMapping;
  material.envMap = envMap;
})

const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

Three.js 纹理贴图 - 环境贴图 - 纹理贴图 - 透明贴图 - 高光贴图

案例:使用一个全景图作为环境贴图
loader.load("/assets/test.jpg",(envMap)=>{
  envMap.mapping = THREE.EquirectangularReflectionMapping;
  scene.background = envMap; 
  scene.environment = envMap;
  material.envMap = envMap; 
})

注意:scene.backgroundscene.environment 需要一起设置。scene.background控制场景的背景,scene.environment纹理贴图将会被设为场景中所有物理材质的环境贴图。该属性不能够覆盖已存在的、已分配给 MeshStandardMaterial.envMap 的贴图。
Three.js 纹理贴图 - 环境贴图 - 纹理贴图 - 透明贴图 - 高光贴图

如果色调不喜欢,可以修改渲染器的色调映射 webGLRenderer.toneMapping: Constant 和映射色调的曝光程度webGLRenderer.toneMappingExposure : Number,可以访问案例体会一下不同值的区别


THREE.NoToneMapping
THREE.LinearToneMapping
THREE.ReinhardToneMapping
THREE.CineonToneMapping
THREE.ACESFilmicToneMapping

使用立方体纹理加载器 CubeTextureLoader 加载环境贴图

语法:new CubeTextureLoader(manager : LoadingManager)
参数:加载器使用的 loadingManager,默认值为THREE.DefaultLoadingManager
继承链:Loader → CubeTextureLoader
返回值:返回创建的立方体纹理加载器 CubeTextureLoader.
描述:立方体纹理加载器 CubeTextureLoader.load()方法加载 6 张图片,返回一个立方体纹理对象CubeTexture

loader.setPath 设置基础路径





const loader = new THREE.TextureLoader();
const texture = loader.load("/assets/door1.png")
const alphaMap = loader.load("/assets/mask.png")
const urls = [
  '/assets/tile.jpg', x 轴正方向  p:正 positive  n:负 negative
  '/assets/tile.jpg', x 轴负方向  p:正 positive  n:负 negative
  '/assets/tile.jpg', y 轴正方向
  '/assets/tile.jpg', y 轴负方向
  '/assets/tile.jpg', z 轴正方向
  '/assets/tile.jpg', z 轴负方向
]
let textureCube = new THREE.CubeTextureLoader().load(urls);
scene.background = textureCube;
const material = new THREE.MeshBasicMaterial({
  map: texture,
  envMap:textureCube,
});

透明贴图 mesh 的 alphaMap 属性 / 高光贴图 mesh 的 specularMap 属性 / 光照贴图 mesh 的 lightMap 属性 / 环境遮挡贴图 mesh 的 aoMap 属性

  • 透明贴图:alpha 贴图是一张灰度纹理,用于控制整个表面的透明度。
  • 高光贴图:用于控制对象表面的高光反射强度和位置,通常使用灰度图像来表示不同的反射强度值。
  • 光照贴图:用于控制对象表面的光照强度和位置,通常使用灰度图像来表示不同的光照强度值。光照贴图可以让对象表面看起来更加真实,增强细节和立体感。
  • 环境光遮蔽贴图(AO 贴图):用于控制对象表面在环境光下的遮蔽程度,通常使用灰度图像来表示不同的遮蔽程度值。
贴图类型 黑色 白色 灰色
透明贴图 alphaMap 不透明区域 完全透明 不同程度的半透明
高光贴图 specularMap 不反射区域 最大反射强度区域 不同程度反射强度区域
光照贴图 lightMap 无光照 五颜六色的光
环境遮蔽贴图 aoMap 完全被遮蔽 没有遮蔽 不同程度的遮蔽

案例代码
代码只显示某一贴图,测试时可以修改为不同贴图的设置属性,使用下图测试效果。Three.js 纹理贴图 - 环境贴图 - 纹理贴图 - 透明贴图 - 高光贴图

const texture = loader.load("/assets/door.png")
const alphaMap = loader.load("/assets/transparent.png")
let planeMaterial = new THREE.MeshBasicMaterial({
  color: 0xffffff,
  map: texture,
  transparent: true, 
  
  alphaMap: alphaMap,
  reflectivity: 0.5,  
});

在这里插入图片描述

原文地址: Three.js 纹理贴图 – 环境贴图 – 纹理贴图 – 透明贴图 – 高光贴图

    正文完
     0
    Yojack
    版权声明:本篇文章由 Yojack 于2024-09-28发表,共计9143字。
    转载说明:
    1 本网站名称:优杰开发笔记
    2 本站永久网址:https://yojack.cn
    3 本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行删除处理。
    4 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
    5 本站所有内容均可转载及分享, 但请注明出处
    6 我们始终尊重原创作者的版权,所有文章在发布时,均尽可能注明出处与作者。
    7 站长邮箱:laylwenl@gmail.com
    评论(没有评论)