UV 法向量实验室:Threejs 纹理与光照炼金术

UV

UV 坐标是二维坐标,用于描述三维模型上的纹理坐标。UV 坐标通常用于将纹理映射到三维模型的表面,从而实现纹理贴图的效果。

在 Three.js 中,每个模型都有一个 geometry 属性,该属性包含模型的顶点坐标、法向量、纹理坐标等信息。纹理坐标通常存储在 geometry.attributes.uv 属性中,该属性是一个 THREE. BufferAttribute 对象,其中包含了每个顶点的 UV 坐标。

如图,左边的贴图杂乱无章,右边的贴图是按照模型顶点的 UV 坐标进行映射的。

js 复制代码
//第一个平面,贴图可以正常显示
const planeGeometry = new THREE.PlaneGeometry(2, 2);
const planeMaterial = new THREE.MeshBasicMaterial({ map: texture });
const plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.position.x = -2;
scene.add(plane);
console.log(plane);

//第二个不带UV平面,所以贴图无法定位则无法显示
const geometry = new THREE.BufferGeometry();
const vertices = new Float32Array([-1.0, -1.0, 0.0, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0, -1.0, 1.0, 0.0]);
geometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));
const indices = new Uint16Array([0, 1, 2, 2, 3, 0]);
geometry.setIndex(new THREE.BufferAttribute(indices, 1));
const material = new THREE.MeshBasicMaterial({ map: texture });
const mesh = new THREE.Mesh(geometry, material);
mesh.position.x = 2;
scene.add(mesh);
console.log(mesh);

设置 UV 坐标,使贴图可以正常显示,UV 坐标的值范围是 0 到 1,表示贴图的左下角和右上角。两个为一组,表示一个顶点的 UV 坐标。

js 复制代码
const geometry = new THREE.BufferGeometry();
const vertices = new Float32Array([-1.0, -1.0, 0.0, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0, -1.0, 1.0, 0.0]);
geometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));
const indices = new Uint16Array([0, 1, 2, 2, 3, 0]);
geometry.setIndex(new THREE.BufferAttribute(indices, 1));

//设置UV坐标
const uv = new Float32Array([0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0]);
geometry.setAttribute("uv", new THREE.BufferAttribute(uv, 2));

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

对应关系:

(-1.0, -1.0, 0.0) -> (0.0, 0.0)、(1.0, -1.0, 0.0) -> (1.0, 0.0)、(1.0, 1.0, 0.0) -> (1.0, 1.0)、(-1.0, 1.0, 0.0) -> (0.0, 1.0)

法向量

法向量(Normal Vector)是指垂直于一个平面或曲面的向量,用于描述平面的方向或曲面的切线方向。

在三维图形学中,法向量通常用于计算光照、阴影、反射等效果。法向量通常与顶点坐标一起存储,用于计算每个顶点的光照效果。

  • 法向量与顶点坐标的关系

每个顶点都有一个法向量,用于描述该顶点所在平面的方向。法向量通常与顶点坐标一起存储,用于计算每个顶点的光照效果。

  • 法向量与面片的关系

每个面片通常由三个顶点组成,每个顶点都有一个法向量。面片的法向量可以通过计算三个顶点的法向量来得到。

  • 法向量与光照的关系

在计算光照效果时,需要计算光线与面片的法向量之间的夹角,从而得到光照强度。法向量与光照方向之间的夹角越小,光照强度越大。

设置法向

js 复制代码
//创建正常平面
const planeGeometry = new THREE.PlaneGeometry(2, 2);
const planeMaterial = new THREE.MeshBasicMaterial({ map: texture });
const plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.position.x = -2;
scene.add(plane);
console.log(plane);

//不带法向平面
const geometry = new THREE.BufferGeometry();
const vertices = new Float32Array([-1.0, -1.0, 0.0, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0, -1.0, 1.0, 0.0]);
geometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));
const indices = new Uint16Array([0, 1, 2, 2, 3, 0]);
geometry.setIndex(new THREE.BufferAttribute(indices, 1));
//设置UV坐标
const uv = new Float32Array([0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0]);
geometry.setAttribute("uv", new THREE.BufferAttribute(uv, 2));
// const material = new THREE.MeshBasicMaterial({ map: texture });
//这里设置跟第一个平面一样的材质便于观察
const mesh = new THREE.Mesh(geometry, planeMaterial);
mesh.position.x = 2;
scene.add(mesh);
console.log(mesh);

//添加环境贴图
let rgbeLoader = new RGBELoader();
rgbeLoader.load("./texture/st_fagans_interior_1k.hdr", (envMap) => {
  envMap.mapping = THREE.EquirectangularReflectionMapping;
  scene.environment = envMap;
  scene.background = envMap;
  planeMaterial.envMap = envMap;
});

可以看出左边有反射效果,右边因为没有法向量,所以没有反射效果。

js 复制代码
//自动设置法向量
geometry.computeVertexNormals();

//手动设置法向量
const normals = new Float32Array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0]);
geometry.setAttribute("normal", new THREE.BufferAttribute(normals, 3));

设置规则:

法向是垂直于平面的向量,三个坐标为一组,表示一个顶点的法向量。所以平面有四个顶点,那么四个点的法向量都是(0.0, 0.0, 1.0)。

法向量辅助器

法向量辅助器(NormalHelper)是一个用于可视化法向量的工具,可以用于调试和查看法向量的方向和长度。

js 复制代码
//导入顶点法向量辅助器
import { VertexNormalsHelper } from "three/examples/jsm/helpers/VertexNormalsHelper.js";
//创建法向量辅助器
const normalHelper = new THREE.VertexNormalsHelper(mesh, 0.1, 0x00ff00);
scene.add(normalHelper);

VertexNormalsHelper 构造函数接受三个参数:

  • object: 要显示法向量的对象。

  • size: 法向量的长度。

  • color: 法向量的颜色。

书洞笔记

相关推荐
Wyc7240913 分钟前
HTML:入门
前端·html
Sunny_lxm14 分钟前
自定义列甘特图,原生开发dhtmlxgantt根特图,根据数据生成只读根特图,页面展示html demo
前端·html·甘特图·dhtmlxgantt
熊猫钓鱼>_>1 小时前
建筑IT数字化突围:建筑设计企业的生存法则重塑
前端·javascript·easyui
GISer_Jing3 小时前
前端性能指标及优化策略——从加载、渲染和交互阶段分别解读详解并以Webpack+Vue项目为例进行解读
前端·javascript·vue
不知几秋3 小时前
数字取证-内存取证(volatility)
java·linux·前端
水银嘻嘻5 小时前
08 web 自动化之 PO 设计模式详解
前端·自动化
Zero1017136 小时前
【详解pnpm、npm、yarn区别】
前端·react.js·前端框架
&白帝&7 小时前
vue右键显示菜单
前端·javascript·vue.js
Wannaer7 小时前
从 Vue3 回望 Vue2:事件总线的前世今生
前端·javascript·vue.js
羽球知道7 小时前
在Spark搭建YARN
前端·javascript·ajax