【光照】[PBR][法线分布]GGX实现方法对比
【从UnityURP开始探索游戏渲染】专栏-直达
GGX的全称与基本概念
GGX的全称:Ground Glass X (或 Generalized Trowbridge-Reitz Distribution)
首次提出:Walter等人在2007年发表的论文《Microfacet Models for Refraction through Rough Surfaces》中提出
GGX是一种法线分布函数(Normal Distribution Function, NDF),用于描述微表面模型中微观几何表面法线的概率分布。它是Unity URP中PBR渲染的核心组成部分,替代了传统的Beckmann分布。
GGX的数学原理
核心公式
在Unity URP中,GGX分布的实现基于以下公式:
$D_{GGX}(h)=\frac{α_g2}{π[(n⋅h)2(α_g2−1)+1]2}$
其中:
- h:半角向量(光线方向与视线方向的中间向量)
- n:表面法线
- $α_g$:粗糙度参数($α_g=roughness^2$)
Unity URP中的代码实现
在Packages/com.unity.render-pipelines.universal/ShaderLibrary/BRDF.hlsl中:
hlsl
// GGX/Trowbridge-Reitz分布函数
float D_GGX(float NdotH, float roughness)
{
float a = roughness * roughness; // 粗糙度平方
float a2 = a * a;
float NdotH2 = NdotH * NdotH;
float denom = NdotH2 * (a2 - 1.0) + 1.0;
denom = PI * denom * denom;
return a2 / max(denom, 0.000001); // 避免除零错误
}
GGX的核心特性
长尾分布特性
- 相比Beckmann分布,GGX具有更长的"尾巴"
- 能更好地模拟真实世界的材质高光衰减
- 产生更自然的反射光晕效果
能量守恒
- $∫_ΩD_{GGX}(h)(n⋅h)dω=1$
- 保证了光线能量在反射过程中不会无故增加或减少
- 是PBR渲染的基础要求
各向同性/各向异性支持
hlsl
// URP中各向异性GGX实现
float D_GGX_Anisotropic(float NdotH, float HdotX, float HdotY, float ax, float ay)
{
float denom = HdotX*HdotX/(ax*ax) + HdotY*HdotY/(ay*ay) + NdotH*NdotH;
return 1.0 / (PI * ax * ay * denom * denom);
}
GGX与其他分布函数对比
| 特性 | GGX | Beckmann | Blinn-Phong |
|---|---|---|---|
| 真实度 | ★★★★☆ | ★★★☆☆ | ★★☆☆☆ |
| 性能开销 | ★★☆☆☆ | ★★★☆☆ | ★☆☆☆☆ |
| 长尾表现 | 优异 | 中等 | 较差 |
| 移动端支持 | 良好 | 一般 | 优秀 |
| URP默认 | 是 | 否 | 仅在SimpleLit中使用 |
GGX在Unity URP中的实际应用
材质粗糙度映射
hlsl
// 粗糙度处理流程
float perceptualRoughness = PerceptualSmoothnessToPerceptualRoughness(smoothness);
float roughness = PerceptualRoughnessToRoughness(perceptualRoughness);
// 应用纹理采样
roughness = roughness * _RoughnessMap.Sample(sampler_MainTex, uv).r;
高光反射计算
hlsl
// BRDF.hlsl中的完整镜面反射计算
half3 BRDF_SpecularGGX(half3 F0, half roughness, half NdotH, half NdotL, half NdotV, half LdotH)
{
half D = D_GGX(NdotH, roughness); // GGX法线分布
half V = V_SmithGGXCorrelated(NdotL, NdotV, roughness); // 几何衰减
half3 F = F_Schlick(LdotH, F0); // 菲涅尔反射
return (D * V) * F;
}
环境光反射处理
hlsl
// 环境BRDF计算(使用GGX分布)
half2 envBRDF = tex2D(_BRDFLUT, float2(NdotV, roughness)).rg;
half3 envSpecular = specularColor * envBRDF.x + envBRDF.y;
GGX的视觉表现特点
粗糙材质表现
- 低粗糙度:锐利的高光反射
- 中粗糙度:柔和的散射光晕
- 高粗糙度:均匀的漫反射外观
边缘响应
- 在材质边缘产生自然的亮度衰减
- 模拟真实物体的菲涅尔效应
材质连续性
- 粗糙度参数从0到1变化时表现平滑过渡
- 避免传统模型的突兀变化
性能优化技巧
近似计算
hlsl
// GGX的移动端近似
float D_GGX_Mobile(float NdotH, float roughness)
{
float a = roughness * roughness;
float a2 = a * a;
float d = NdotH * NdotH * (a2 - 1.0) + 1.0;
return a2 / (d * d * PI);
}
预积分技术
- URP使用预计算的BRDF查找纹理(_BRDFLUT)
- 将复杂计算转移到预处理阶段
动态降级
hlsl
#if defined(SHADER_API_MOBILE)
// 移动端简化版GGX
#else
// 完整精度GGX
#endif
GGX分布作为Unity URP中PBR渲染的核心,通过其独特的数学特性和长尾分布,实现了比传统模型更真实的材质表现。虽然计算复杂度略高,但其在视觉质量和物理准确性上的优势使其成为现代实时渲染的标准选择。
【从UnityURP开始探索游戏渲染】专栏-直达
(欢迎点赞留言探讨,更多人加入进来能更加完善这个探索的过程,)
【光照】[PBR][法线分布]GGX实现方法对比的更多相关文章
- Linux和Windows下查看环境变量方法对比
摘自:Linux和Windows下查看环境变量方法对比 一.查看所有环境变量的名称和值 Linux下:export Windows下:set 二.根据名称查该环境变量的值 Linux下:echo $环 ...
- C语言清空输入缓冲区的N种方法对比
转自C语言清空输入缓冲区的N种方法对比 C语言中有几个基本输入函数: //获取字符系列 int fgetc(FILE *stream); int getc(FILE *stream); int get ...
- iPhone开发 数据持久化总结(终结篇)—5种数据持久化方法对比
iPhone开发 数据持久化总结(终结篇)—5种数据持久化方法对比 iphoneiPhoneIPhoneIPHONEIphone数据持久化 对比总结 本篇对IOS中常用的5种数据持久化方法进行简单 ...
- interrupt interrupted isInterrupted 方法对比、区别与联系 多线程中篇(八)
interrupt interrupted isInterrupted 是三个“长相”非常类似的方法. 本文将对这三个方法简单的对比下,首先了解下线程停止的方式 线程停止方式 在Java中如果想停止一 ...
- JavaScript中易混淆的DOM属性及方法对比
JavaScript中易混淆的DOM属性及方法对比 ParentNode.children VS Node.prototype.childNodes ParentNode.children:该属性继承 ...
- vue-cli 项目优化之3种方法对比:本地静态库资源(推荐)、cdn、DllPlugin
vue-cli 项目优化之3种方法对比:本地静态库资源(推荐).cdn.DllPlugin 事项 本地静态库资源 cdn DllPlugin 依赖 依赖cdn网站资源(有种完善方法:如果cdn引入不成 ...
- vue 和 react 组件间通信方法对比
vue 和 react 组件间通信方法对比: 通信路径 vue的方法 react的方法 父组件 => 子组件 props(推荐).slot(推荐).this.$refs.this.$childr ...
- js与jQuery方法对比
javascript与jQuery方法对比jquery对象转dom对象 // 方式一(推荐使用) $("input")[0] // 方式二 $("input" ...
- UIImage类方法总结及UIImage生成方法对比
http://mp.weixin.qq.com/s/A900w0Y5pGjuaB4j9Os9ww1.UIImage 生成方法的对比 Apple官方的文档为生成一个UIImage对象提供了两种方法: 1 ...
- Hibernate学习(5)- session的get与load方法对比
1.共同点:get和load都是根据Id单条查询获取对象 org.hibernate.Session.load(Class<User> theClass, Serializable id) ...
随机推荐
- Create React App 被 React 官方抛弃
新的开始 2023年3月17号 react官方文档正式更新,还顺带搬了个家,连网址都变了. 被嫌弃的CRA 不知道小伙伴有没有留意到了没:曾经官方推荐 创建项目的脚手架工具 create-react- ...
- VBlog 项目中注册用户流程解析
简介 项目来自 https://github.com/lenve/VBlog image 简单概括一下流程 浏览器中使用post 提交注册用户相关的信息, 然后 后端对于这个接口进行处理. 首先是 L ...
- 树莓派3B刷openwrt系统
树莓派3B刷openwrt系统 树莓派的固件下载link 下载完之后 使用Win32DiskImage 把固件烧录到内存卡里面 遇到输入不进去因为里面曾经烧录过linux 格式化的时候选择慢速格式化即 ...
- SciTech-Printing-精密成像+印刷-静电成像(激光印刷/成像)的原理介绍
静电成像的原理介绍 (2014-01-09 17:32:11) 标签: 静电成像 静电成像原理 文化 分类: 印艺技术 静电成像是利用光导材料的"光敏变电阻"特性: 在黑暗中为绝缘 ...
- SciTech-Mathmatics-ComplexSpace-Encode/Decode- (Discrete)Multi-Dimensional FourierTransform: arbitrary $R^n$ functions + SpectralAnalysis + ImageSynthesis__FourierSeries: PeriodicalFunctions
多维复空间上的离散傅立叶变换\(MD-DFT\)(Multi-Dimensional Discrete Fourier Transform) : 多维\(C^k\)(k维复数空间)上的\(MD-DFT ...
- Win11系统电脑关机后自动开机的问题
有不少电脑基地的小伙伴下载Win11操作系统来使用了,但有小伙伴遇到电脑关机之后突然又自动开机的问题,那么应该怎么办呢?下面技术员小编就来分享解决方法吧. Windows 11 关机后自动开机可能由硬 ...
- 关于VUE项目请示接口报错:Error: Network Error at createError (createError.js:17) at XMLHttpRequest.handleError的问题处理
今天在开发VUE项目时,发现一个问题,请示后端接口时报错,但是调试后端接口请示正常,但是前端就报错 看浏览器错误信息如下: 调试看到请示错误信息如下: Error: Network Error at ...
- c++ 数据类型及范围
short: \(-2^{15}\sim 2^{15}-1\) unsigned short: \(0\sim 2^{16}-1\) int: \(-2^{31}\sim 2^{31}-1\) uns ...
- CF2077C Binary Subsequence Value Sum 题解
前言: (虚假的想象学竞赛,实际的数学竞赛) 题意: 给出一个长度为 \(n\) 的二进制序列,我们对于每一个分割点(可以看做在元素与元素之间),其贡献为分割点右边的 \(cnt_1 - cnt_0\ ...
- MYSQL-01课堂笔记
mysql day01课堂笔记 1.什么是数据库?什么是数据库管理系统?什么是SQL?他们之间的关系是什么? 数据库: 英文单词DataBase,简称DB.按照一定格式存储数据的一些文件的组合. 顾名 ...