当前位置: 首页 > news >正文

用 Three.js 实现 PlayCanvas 风格 PBR 材质教程(第二篇):核心参数与光照模型

上一篇我们搭建了基础环境并实现了简单的自定义材质,本篇将基于完整代码,深入解析 PBR 的核心参数、光照模型的实现逻辑,以及如何通过代码将物理规律转化为视觉效果。

一、核心参数解析:从代码看 PBR 的物理基础

PlayCanvas 风格的 PBR 材质通过一组具有明确物理意义的参数描述材质特性,这些参数在代码中通过uniform变量传递,并在着色器中参与光照计算。

1. 基础参数与代码映射

参数名 代码变量 类型 范围 物理意义
基础色 albedo vec3 RGB 颜色 物体表面的固有颜色,非金属为漫反射色,金属为反射色
金属度 metalness float 0~1 区分金属(1)与非金属(0),控制漫反射 / 镜面反射比例
粗糙度 roughness float 0~1 控制表面光滑度,0 = 镜面,1 = 完全粗糙
折射率 ior float 1.0+ 决定光线折射 / 反射比例,计算基础反射率(F0)
镜面反射率 specularity vec3 RGB 颜色 控制非金属的高光强度,金属材质忽略此参数
环境反射强度 envMapReflectivity float 0~1 控制环境贴图的反射强度

2. 金属度(Metalness)的核心作用

金属与非金属的光学特性差异是 PBR 的核心,代码通过calcSpecularModulate函数实现这种差异:

vec3 calcSpecularModulate(in vec3 specularity, in vec3 albedo, in float metalness, in float f0) {vec3 dielectricF0 = f0 * specularity; // 非金属的基础反射率(由折射率和镜面反射率计算)return mix(dielectricF0, albedo, metalness); // 金属直接使用基础色作为反射率
}

代码逻辑解析

  • metalness=0(非金属):镜面反射率 = 折射率计算的 F0 × specularity
  • metalness=1(金属):镜面反射率 = albedo(基础色)
  • 中间值:通过mix函数平滑过渡,模拟半金属特性

同时,金属材质几乎没有漫反射,代码通过以下逻辑实现:

// 计算漫反射率:金属漫反射为0,非金属使用albedo作为漫反射率
litArgs_albedo = litArgs_albedo * (1.0 - litArgs_metalness);

3. 粗糙度(Roughness)与光泽度(Glossiness)

粗糙度描述表面的微观不平度,代码中通过calcGlossiness函数将其转换为光泽度(与粗糙度相反):

void calcGlossiness() {dGlossiness = 1.0 - roughness; // 光泽度 = 1 - 粗糙度dGlossiness += 0.0000001; // 避免零值,防止后续计算异常
}

作用

  • 光泽度越高(粗糙度越低):高光越集中,反射越清晰
  • 光泽度越低(粗糙度越高):高光越扩散,反射越模糊

在镜面反射计算中,光泽度直接影响采样的环境贴图层级(后续环境贴图章节详细讲解)。

4. 折射率(IOR)与基础反射率(F0)

折射率决定光线从空气进入材质时的反射比例,代码中通过以下公式计算垂直入射时的反射率(F0):

// 在evaluateBackend中计算F0
float f0 = litArgs_ior;
f0 = (f0 - 1.0) / (f0 + 1.0); // 折射率转反射率公式
f0 *= f0; // 垂直入射时的反射光比例

物理意义:F0 表示光线垂直入射时,反射光占总入射光的比例。例如:

  • 空气(IOR=1.0):F0=0(无反射)
  • 玻璃(IOR=1.5):F0≈0.04(4% 反射率)
  • 钻石(IOR=2.42):F0≈0.17(17% 反射率)

F0 是菲涅尔效应计算的基础,直接影响材质的反射强度。

二、光照模型的核心计算:从参数到颜色的转化

PBR 光照模型的核心是模拟光线与物体表面的交互,代码通过 “前端数据准备→后端光照计算” 的流程实现,核心逻辑集中在片元着色器的evaluateFrontendevaluateBackend函数中。

1. 前端计算(evaluateFrontend):数据准备与向量计算

前端计算的作用是将原始参数转换为光照计算所需的中间变量,包括读取材质参数、计算核心向量(法线、视线方向等)。

void evaluateFrontend() {// 1. 读取材质参数到d前缀变量(原始数据存储)calcAlpha();      // dAlpha = opacitycalcAlbedo();     // dAlbedo = albedocalcMetalness();  // dMetalness = metalnesscalcGlossiness(); // dGlossiness = 1 - roughnesscalcIor();        // dIor = iorcalcSpecularity();// dSpecularity = specularitycalcEmission();   // dEmissive = emissive// 2. 计算核心向量(用于光照计算)calcNormal();     // dNormal = 世界空间法线calcViewDir();    // dViewDir = 视线方向(相机→顶点)calcReflectDir(); // dReflectDir = 反射方向(基于法线和视线)// 3. 将d变量传递给litArgs变量(光照计算参数)litArgs_albedo = dAlbedo;litArgs_specularity = dSpecularity;litArgs_gloss = dGlossiness;litArgs_metalness = dMetalness;litArgs_ior = dIor;litArgs_worldNormal = dNormal;litArgs_viewDir = dViewDir;litArgs_reflectDir = dReflectDir;
}

核心向量解析

  • 法线向量(dNormal):normalize(vNormalW),表面朝向,决定光线反射方向
  • 视线方向(dViewDir):normalize(cameraWorldPos - vPositionW),从顶点指向相机
  • 反射方向(dReflectDir):normalize(reflect(-dViewDir, dNormal)),环境光反射的方向

2. 后端计算(evaluateBackend):光照核心逻辑

后端计算是 PBR 的 “大脑”,实现从参数到最终颜色的转化,包含 F0 计算、菲涅尔效应、漫反射与镜面反射计算等核心步骤。

步骤 1:计算基础反射率(F0)
// 根据折射率计算垂直入射的光照 反射光/总入射光的比例 f0
float f0 = litArgs_ior;
f0 = (f0 - 1.0) / (f0 + 1.0);
f0 *= f0;

这一步将折射率转换为物理上的基础反射率,是后续所有反射计算的基础。

步骤 2:修正高光反射率(考虑金属度)

// 根据f0和金属度调节高光反射率
litArgs_specularity = calcSpecularModulate(litArgs_specularity, litArgs_albedo, 
http://www.dtcms.com/a/290555.html

相关文章:

  • CS课程项目设计4:支持AI人机对战的五子棋游戏
  • RustDesk自建服务器完整部署指南:从零开始到成功连接。成功解决rustdesk报错:未就绪,请检查网络连接
  • Linux的系统调用机制总结
  • [Python] -项目实战10- 用 Python 自动化批量重命名文件
  • 重学前端008 --- CSS 无障碍 Quiz
  • 《高并发优化方案一》:本地锁 + 分布式锁实战详解
  • Excel函数 —— TEXTJOIN 文本连接
  • 支持不限制大小,大文件分段批量上传功能(不受nginx /apache 上传大小限制)
  • Apache Ignite Closure 和 Thread Pool
  • Ubuntu安装k8s集群入门实践-v1.31
  • WinForm-免费,可商用的WinForm UI框架推荐
  • 类似腾讯会议的私有化音视频会议软件,BeeWorks Meet
  • Go语言进阶书籍:Go语言高级编程(第2版)
  • 开源 Arkts 鸿蒙应用 开发(八)多媒体--相册和相机
  • 45.sentinel自定义异常
  • RIQ模型时间管理方法详解
  • Idea或Pycharm上.idea的忽略提交的问题总结
  • go语言八股
  • MySQL(149)如何进行数据清洗?
  • 09_Spring Boot 整合 Freemarker 模板引擎的坑
  • 【C++】stack和queue拓展学习
  • 库卡气体保护焊机器人省气的方法
  • Mac上安装Homebrew的详细步骤
  • 【CNN】卷积神经网络池化- part2
  • Pytorch01:深度学习中的专业名词及基本介绍
  • 有关Maven的个人笔记总结
  • Zetane:让深度学习不再抽象,一键3D可视化
  • SpringSecurity 详细介绍(认证和授权)
  • 直播专用域名租用全解析:开启直播新境界
  • 板凳-------Mysql cookbook学习 (十二--------3_2)