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: 法向量的颜色。

书洞笔记

相关推荐
庸俗今天不摸鱼21 分钟前
【万字总结】前端全方位性能优化指南(十)——自适应优化系统、遗传算法调参、Service Worker智能降级方案
前端·性能优化·webassembly
黄毛火烧雪下28 分钟前
React Context API 用于在组件树中共享全局状态
前端·javascript·react.js
Apifox39 分钟前
如何在 Apifox 中通过 CLI 运行包含云端数据库连接配置的测试场景
前端·后端·程序员
一张假钞41 分钟前
Firefox默认在新标签页打开收藏栏链接
前端·firefox
高达可以过山车不行41 分钟前
Firefox账号同步书签不一致(火狐浏览器书签同步不一致)
前端·firefox
m0_5937581043 分钟前
firefox 136.0.4版本离线安装MarkDown插件
前端·firefox
掘金一周1 小时前
金石焕新程 >> 瓜分万元现金大奖征文活动即将回归 | 掘金一周 4.3
前端·人工智能·后端
三翼鸟数字化技术团队1 小时前
Vue自定义指令最佳实践教程
前端·vue.js
Jasmin Tin Wei2 小时前
蓝桥杯 web 学海无涯(axios、ecahrts)版本二
前端·蓝桥杯
圈圈编码2 小时前
Spring Task 定时任务
java·前端·spring