寒霜PBR阅读与实践[1]:Material材质--Physically Based Rendering 3.0 --SIGGRAPH 2014

Material材质:

Material Model 材质模型:

Energy conservation 能量守恒:

Shape characteristics 形状特征:

寒霜的标准材质模型:

Material system 材质系统:

材质定义:

Disney base material:

Gbuffer layout :

Render loop 渲染循环:

PBR and decals :

实践展示:


前记:自己写了一遍,不知道有没有写对,欢迎指正----------------------------------------------博主:mx

Material材质:

一个Material model,通常用BSDF(双向散射分布函数)进行模拟,可以分解为两部分:反射部分(BRDF)和透射部分(BTDF)。

Material Model 材质模型:

在这个标准材料模型的背景下,一个表面响应f通常被分解成两个不同的项称为“漫反射”(fd)的低角频率信号和称为“镜面”(fr)的低到高角频率信号。

fr项,我们常用的BRDF,如下:

FGD三个函数分别为法线分布函数(Normal Distribution Function),菲涅尔方程(Fresnel Rquation)和几何函数(Geometry Function):

  • 法线分布函数:估算在受到表面粗糙度的影响下,取向方向与中间向量一致的微平面的数量。这是用来估算微平面的主要函数。
  • 几何函数:描述了微平面自成阴影的属性。当一个平面相对比较粗糙的时候,平面表面上的微平面有可能挡住其他的微平面从而减少表面所反射的光线。
  • 菲涅尔方程:菲涅尔方程描述的是在不同的表面角下表面所反射的光线所占的比率。

D在表面的外观中起着重要的作用,GGX分布,擅长捕捉真实世界的表面。对于高粗糙度值,G项也起着重要作用。Heitz 证明了Smith可见性函数是正确且精确的G项。masking-shadowing函数的更精确形式模拟了由于微表面而导致的masking-shadowing之间的相关性,下面这个就是masking-shadowing函数:

下图则是显示了简单的Smith函数和高度相关的Smith函数之间的区别。

对于漫反射(fd)项,他遵循朗伯模型,可以将其简化为:

并且与fr使用相同的粗糙度

但是这个方程没有解析解。Burley提出了另一个建立在真实世界表面观测的漫反射模型。虽然这个模型是经验的,但它允许我们重现MERL数据库材料的主要特征。由于这个原因和它的简单性,寒霜中使用了这个模型。这个漫反射项考虑了材料的粗糙度,并在切线角度产生了一些向后的反射,公式如下:

Energy conservation 能量守恒:

为了不凭空产生多余的能量,寒霜使用了一个计算简单并且能量守恒的模型,通过确定半球方向的定向反射,确保总的反射能量恒定等于半球上的照明能量,这个BRDF(diffuse + specular 部分)模型为:

由于寒霜的高光和漫反射模型之间的非直接关系,要做出适当的推导并不容易(关于高光和漫反射项都基于microfacet模型的情况)。

迪士尼漫射模式的一个重要问题是它不是能量守恒的。下图显示了迪斯尼漫反射模型的半球方向反射率。我们可以清楚地看到这个BRDF不是节能的,因为得到的反射率值大于1。

寒霜对迪斯尼漫反射模型进行了轻微的修改,以补偿能量的增加,同时保持它的反射特性。往里面加入了重整化因子。上面这个图可以看到比较结果。

这个新的模型代码实现如下:

float Fr_DisneyDiffuse ( float NdotV , float NdotL , float LdotH ,float linearRoughness )

{

float energyBias = lerp (0, 0.5 , linearRoughness );

float energyFactor = lerp (1.0 , 1.0 / 1.51 , linearRoughness );

float fd90 = energyBias + 2.0 * LdotH * LdotH * linearRoughness ;

float3 f0 = float3 (1.0f, 1.0f, 1.0 f);

float lightScatter = F_Schlick (f0 , fd90 , NdotL ).r;

float viewScatter = F_Schlick (f0 , fd90 , NdotV ).r;

return lightScatter * viewScatter * energyFactor ;

}

下图是效果对比:

Shape characteristics 形状特征:

基于为表面的高光BRDF具有某些属性,这些属性经常被忽略,但对最终外观有很大影响。有两个现象特别重要:

①半角参数化:该参数化意味着BRDF形状的非线性变换,从入射角度的各向同性到切线角度的各向异性。

②非镜面反射:通常假设BRDF lobe以反射视图方向(也称为镜面方向)为中心。然而,由于(n·l)和阴影掩蔽项G的存在,当粗糙度增加时,BRDF lobe 向发现方向移动。这种移动被称为“Off-specular peak”,它在粗糙的表面上起着重要的作用。这种现象如下图所示。

对于高粗糙度值,非镜面峰值会导致较大的差异。为了考虑到这一重要特征,一般需要对“主导方向”进行建模,该方向在区域光和基于图像的光评估中使用(应该是用环境法线)

寒霜的标准材质模型:

镜面反射项:是采用Smith correlated 可见性函数 和 GGX NDF 的一种特殊的微平面BRDF模型

漫反射项:采用能量重整后的迪士尼漫反射模型

代码实现如下:

float3 F_Schlick (in float3 f0 , in float f90 , in float u)

{

return f0 + (f90 - f0) * pow (1. f - u, 5.f);

}

float V_SmithGGXCorrelated ( float NdotL , float NdotV , float alphaG )

{

// Original formulation of G_SmithGGX Correlated

// lambda_v = (-1 + sqrt ( alphaG2 * (1 - NdotL2 ) / NdotL2 + 1)) * 0.5 f;

// lambda_l = (-1 + sqrt ( alphaG2 * (1 - NdotV2 ) / NdotV2 + 1)) * 0.5 f;

// G_SmithGGXCorrelated = 1 / (1 + lambda_v + lambda_l );

// V_SmithGGXCorrelated = G_SmithGGXCorrelated / (4.0 f * NdotL * NdotV );

// This is the optimize version

float alphaG2 = alphaG * alphaG ;

// Caution : the " NdotL *" and " NdotV *" are explicitely inversed , this is not a mistake .

float Lambda_GGXV = NdotL * sqrt ((- NdotV * alphaG2 + NdotV ) * NdotV + alphaG2 );

float Lambda_GGXL = NdotV * sqrt ((- NdotL * alphaG2 + NdotL ) * NdotL + alphaG2 );

return 0.5 f / ( Lambda_GGXV + Lambda_GGXL );

}

float D_GGX ( float NdotH , float m)

{

// Divide by PI is apply later

float m2 = m * m;

float f = ( NdotH * m2 - NdotH ) * NdotH + 1;

return m2 / (f * f);

}

// This code is an example of call of previous functions

float NdotV = abs( dot (N, V)) + 1e -5f; // avoid artifact

float3 H = normalize (V + L);

float LdotH = saturate ( dot (L, H));

float NdotH = saturate ( dot (N, H));

float NdotL = saturate ( dot (N, L));

//Specular BRDF

float3 F = F_Schlick (f0 , f90 , LdotH );

float Vis = V_SmithGGXCorrelated (NdotV , NdotL , roughness );

float D = D_GGX (NdotH , roughness );

float3 Fr = D * F * Vis / PI;

// Diffuse BRDF

float Fd = Fr_DisneyDiffuse (NdotV , NdotL , LdotH , linearRoughness ) / PI;

Material system 材质系统:

材质定义:

寒霜的一个材质基础定义:

①lighting path 光照通道 : 延迟渲染,前向渲染,或者是两者混合

②input parameters 输入参数: diffuse, smoothness, thickness, 等等.

③material model 材质模型 : rough surface, translucency, skin, hair, non-PBR rough

surface 等等.

④GBuffer layout GBuffer的内存布局:在延迟渲染中使用,可以选择多少个buffer可以使用.

Disney base material:

Disney material :使用以下的参数:

· Normal : 法线

· BaseColor: 定义非金属物体的漫反射反照率和金属物体在正入射时的菲涅尔反照率(fo),对于金属物体,这个属性的低部位定义了一个微镜面遮挡。

· Smoothness :定义对象的粗糙度。寒霜选择使用平滑之后的值而不是直接的粗糙度,因为将直接值映射为平滑值对美工来说更直观。与Burley的描述类似,平滑被重新映射为感知线性平滑(1-αlin)。

· MetalMask: 定义材质的金属度

· Reflectance : 定义菲涅耳反射值,这个值被映射从正常的fo到一个艺术家友好的范围 。该属性的下半部分定义了非金属材料的微镜面遮挡术语。

Smoothness:

对于smoothness 重映射,我们分析了不同的重映射函数,并与美工进行了测试。下图:显示了不同的重映射函数和结果。

Reflectance:

寒霜选择了如下的映射:


目标是映射到一个范围,这个范围可以包括宝石的高菲涅耳值,并且重新映射RGB128到普通介质的4%反射率。对于宝石来说,fo大约从红宝石的8%上升到钻石的17%。我们选择将函数限制在16%作为近似值。下图显示了与常用值的比较。1%或2%的fo变化是很难被注意到的。4%以上的快速增长值与此非常吻合。

Gbuffer layout :

约束:

寒霜的Gbuffer 有如下的约束:

· 所有的基本属性(Normal, BaseColor, smooth, MetalMask, Reflectance)需要是可混合的,以支持延迟贴花。不可混合的属性,比如MaterialId被存储在alpha通道中。

· MSAA支持防止使用色度子采样的BaseColor属性。

· 需要将常用的参数收集到同一个缓冲区中。

· 所有MaterialId都需要存放在同一个地方。

· 性能要求意味着我们的基础材料/标准材料只使用四个缓冲器(不包括深度)。

Two-color base material:

这种材质的Gbuffer布局如下:

这种材质主要是表示金属和电介质的交界物质(金属度在0到1之间的物质),如金属氧化物。

这种两个颜色怎么转换到单种颜色的材质呢?

Disney base material 采用baseColor,metal, reflectance 定义,而Two-color base material 采用diffuse color, f0 color 定义,他们之间的转换关系如下:

Old base material:

旧的不是PBR的材质,这里就不多赘述了

Render loop 渲染循环:

整个流程如下:

// GBuffer creation

ForEach different stencil bit do

Render GBuffer pass for deferred material with n number of buffers

Do branching in shaders if needed

Render GBuer pass for deferred material with (n + 1) number of buffers

Do branching in shaders if needed

// Fix-up pass

ForEach deferred material requiring sharing the deferred shading pass

Render GBuer x-up pass

// Decals

Render deferred decals aecting common parameters

// Deferred shading

ForEach individual deferred shading pass required do

Render deferred shading

Do branching in shaders if needed

// Forward rendering and lighting

ForEach ForwardMaterialModel do

Render forward lighting

为什么有Fix-up pass 呢,因为对于几何体密集的通道,希望减少GBuffer的创建成本。一个典型的案例是植被,对于它,寒霜希望只填满基础GBuffer布局的前两个缓冲区,然后用fix-up pass来修补缺失的GBuffer参数。

PBR and decals :

贴花可以被视为分层材料属性的动态系统,允许我们创造丰富的外观和变化。寒霜主要使用延迟着色来渲染贴花,寒霜列出了一些主要的陷阱和相应的抉择。

· 正确性 : 混合操作的正确性很重要,并且希望混合操作后,恢复为原来的属性也必须是正确的。对于Normal,使用标准编码如Normal * 0.5 +0.5或Normal.z , Normal.Y,这种只有一个替换(即线性插值)能够做到恢复之后也是正确的。但是像添加细节这种的有效操作将产生错误的结果。在这种情况下,寒霜选择避免压缩一些属性,并依赖于简单的线性插值alpha混合。

· 相互影响 : 为了正确混合,贴花和目标表面应该使用相同的材料模型(即相同的参数列表)。从生产和性能的角度来看,这是不可管理的,因为它需要通过MaterialID创建贴花,并为每个情况做一个模板传递。我们选择将贴花参数限制在游戏所选择的材料中的公共参数集合中。一般正常,基本颜色,平滑。其他参数,如金属面具,反射(或f0颜色)只考虑迪士尼(或双色)的基础材料被选择。然而。影响其他materialid而不是默认值的贴花将产生走样。MaterialData和MaterialID不是可混合的数据,只能被替换。一种选择是使用alpha通道的单独混合因子来强制一个中立值,比如0。另一个选项是禁止贴花影响MaterialID = 0以外的其他材料。

· 间接光照 : 在任何照明计算之前,表面需要受到贴花的影响。然而寒霜中,间接满发射是在GBuffer创建过程中计算的,这阻止了任何对材料属性的进一步修改。一种解决方法便是使用覆盖关卡的光照探针计算所有的间接漫反射照明。另一个解决方案是使用贴花预传递,在创建GBuffer之前将贴花属性存储在缓冲区中。这需要渲染接收贴花的对象两次。在寒霜中,由于这种解决方案所隐含的开销,我们选择留下走样。

· 发光 : 由于寒霜中GBuffer的存储空间有限,出于性能原因,emissive信息有时会与radiosity缓冲区结合使用。缓冲区会将radiosity与albedo结合起来。在这种情况下,贴花修改反照率将会将修改emissive颜色。在寒霜中,接受了处理radiosity和贴花而产生的走样。

· 突出形状的保持与镜面反射走样 : 任何正常的参数修改都意味着在像素占用下的NDF的改变。这意味着它将偏向于任何在贴花应用之前已经执行的形状。一个解决方案是在贴花应用后执行一个普通的过滤pass作为后处理。

· 前向渲染的表面 : 延迟贴花不兼容透明和任何前向渲染的对象。在这种情况下,常见的解决方案是依赖于前向贴花,混合它们的照明结果与表面照明。支持前向渲染对象的贴花参数混合是可能的,但这需要美术方面的严格限制(有限的混合模式,限制纹理数组的纹理大小等)。这个问题与照明应用有一些相似之处。应用已经发现的照明解决方案可以接触到新的方法---分片延迟/前向贴花。

实践展示:

常规的简单pbr

Frostbite pbr

(雾。不知道是不是我写错了,感觉Frostbite pbr的细节变少了,但是确实符合论文里面的说法,在高粗糙度上有更高的能量,欢迎指正)

常规的简单pbr diffuse

Frostbite pbr diffuse

常规的简单pbr specular

Frostbite pbr specular

后记:还是感觉效果怪怪的,有点过曝的感觉-----------------------------------------------------博主:mx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值