Three.js 材质篇(中):从兰伯特到PBR,一篇文章看懂五种光照材质

上篇我们认识了四种"免灯光"材质。今天给场景加上光,让五种吃光照的材质同台竞技:

  1. Lambert (水粉画,漫反射)
  2. Phong (油画,带高光)
  3. Toon (动漫风,卡通光)
  4. Standard (单反照,PBR真实感)
  5. Physical (加镀膜,清漆层)

读完这篇,你不仅能看懂材质演变史,更能在实际项目中做出"以假乱真"的物体。

至关重要的"配合":环境光与点光源

在讲解这些材质前,必须加一个小节,因为它们是"吃光照"的,没有光就是黑色。

⚠️ 重要:这五种材质都需要光照才能显示颜色。没有光,它们就是一团黑色。

ini 复制代码
// 添加环境光,让物体不至于太暗

const ambientLight = new THREE.AmbientLight(0x404060);

scene.add(ambientLight);

// 添加一个点光源,让它转起来,方便观察材质

const pointLight = new THREE.PointLight(0xffffff, 1);

pointLight.position.set(2, 3, 4);

scene.add(pointLight);

// 让光源动起来,展示光影变化

const tick = () => {

    const time = Date.now() * 0.002;
    
    pointLight.position.x = Math.sin(time) * 3;
    
    pointLight.position.z = Math.cos(time) * 2;
    // ... 渲染
}

1.MeshLambertMaterial (兰伯特) ------ 初代目,漫反射

`// MeshLambertMaterial

const material = new THREE.MeshLambertMaterial()`

想象一面粗糙的水泥墙 ,或者一件没上釉的陶器。光照上去,光线朝各个方向均匀散开,你不会看到某个点特别亮。这就是纯粹的漫反射,就像磨砂光面。

可以看到它的质感非常的细腻,光感很柔和,材质看起来很高级。

2. MeshPhongMaterial ------ 油画,带高光

在磨砂质感的基础上出现了反光点,像高光一样,像上了釉的陶瓷瓶,有高光质感,接下来创建:

`// MeshPhongMaterial const material = new THREE.MeshPhongMaterial()

material.shininess = 10 // 光泽度,越高高光点越小越亮

material.specular = new THREE.Color(0x1188FF) //颜色`

可以看到shininess数值越大反光点汇聚成一个点很亮,数值越小,高光散开,很柔和像珍珠光。

3. MeshToonMaterial ------ 动漫风,卡通光

// MeshToonMaterial const material = new THREE.MeshToonMaterial()

就像动漫或二次元手办。真实的光影是渐变的(暗→灰→亮),而卡通材质把光影压缩成几个明显的色块------暗部一块、中间调一块、亮部一块,边界清晰,感觉可以用来制作甜甜圈效果。

4. MeshStandardMaterial ------ 单反照,PBR真实感(核心重点)

现代Three.js的绝对主力 。基于物理的渲染(PBR),使用 roughness(粗糙度)和 metalness(金属度)两个直观参数,能模拟几乎所有真实材质。

`const material = new THREE.MeshStandardMaterial()

material.metalness = 0.7//金属度

material.roughness = 0.2//粗糙度 ` 为了展示我们需要给项目加入一个环境贴图:

import { RGBELoader } from 'three/examples/jsm/Addons.js'//引入RGBELoader

RGBELoader 用来加载 HDR(高动态范围)环境贴图,这张图既是背景,又是光源------就像把你的3D物体放进一个真实拍摄的"光影胶囊"里。

ini 复制代码
/**
  * 环境贴图
  */
 
const rgbeLoader = new RGBELoader()

rgbeLoader.load('/textures/environmentMap/2k.hdr',(environmentMap) => 

{
    environmentMap.mapping = THREE.EquirectangularReflectionMapping

    scene.background = environmentMap // 设置背景显示什么
    
    scene.environment = environmentMap // 设置物体反射/受光来自哪里
})

此时我们拥有了一个背景。

想象你在摄影棚里拍一个金属球

  • 普通打光:你需要放好几个灯,调半天位置和亮度,才能让球体表面有好看的反光
  • 用 RGBELoader :直接把球放进一个球形灯箱里,灯箱内壁贴着一张"真实的房间照片"------球体表面的反光,就是这张照片里的窗户、墙壁、灯光

RGBELoader 加载的 .hdr 文件,就是这张"灯箱内壁的照片"

我们使用控件调整金属度到最高,粗糙度为0,最光滑的状态能得到一个金属质感的物体,可以反射到环境贴图中的楼窗户等,非常棒!

参数 作用 取值范围 示例
roughness 表面粗糙程度 0(镜面)→ 1(完全漫反射) 0.3 光滑,0.8 磨砂
metalness 金属化程度 0(非金属)→ 1(纯金属) 0.1 像塑料,0.9 像铁

5.MeshPhysicalMaterial ------ 加镀膜,清漆层(旗舰加强版)

`// MeshPhysicalMaterial const material = new THREE.MeshPhysicalMaterial()

material.metalness = 0//金属度

material.roughness = 0.15//粗糙度

material.map = doorColorTexture //使用门纹理

`

可以看出来我们的门好像被困在一种清漆里面被封起来的质感。

下一篇预告:材质篇(下)------ Standard vs Physical,普通车漆和豪华镀膜的区别在哪?

本篇的五种光照材质里,MeshStandardMaterial 是 PBR 主力,能应付 90% 的场景。

但如果你想要车漆的表层清漆反光玻璃的透射折射 、或者丝绸的绒毛光泽 ------就需要升级到 MeshPhysicalMaterial

下一篇,我们用对比表格和代码示例,把 StandardPhysical 的区别讲透,顺便解锁 transmissionclearcoatsheen 等高级参数。

📚 本文是学习 Three.js Journey(Bruno Simon 的付费课程)的学习笔记,代码为个人练习所写,概念讲解融入了个人的理解和比喻。

相关推荐
anOnion6 小时前
构建无障碍组件之Menu Button pattern
前端·html·交互设计
用户47949283569157 小时前
claude Fable用不了?把Gpt 5.5pro接到你的claude code里
前端·后端
JieE2127 小时前
LeetCode 101. 对称二叉树|JS 递归 + 迭代双解法,彻底搞懂镜像判断
javascript·算法
冬奇Lab9 小时前
AI Workflow 定义的四次演进:从 Markdown 到 JS 脚本,再到分布式多 Agent
javascript·人工智能·agent
zhangxingchao9 小时前
Kotlin常用的Flow 操作符整理
前端
IT_陈寒11 小时前
React的useState居然还有这种坑?我差点删库跑路
前端·人工智能·后端
Pedantic12 小时前
SwiftUI 手势笔记
前端·后端
橙子家12 小时前
浏览器缓存之【结构化数据库与缓存】: IndexedDB、Cache storage 和 Storage buckets
前端
user205855615181313 小时前
X6 中边悬浮置顶,规避 `mouseleave` 事件丢失问题
前端
李明卫杭州13 小时前
CSS aspect-ratio 属性完全指南
前端