Cook-Torrance BRDF以及Lambert BRDF上有很多材料。 Real Shading in Unreal Engine 4和Moving Frostbite to BPR深入解释了如何将它们实现为实时渲染。
他们省略的是两个BRDF的组合,以创建完整的着色模型。如果我理解正确,我们可以使用至少两个基本原则来做到这一点:镜面和金属工作流程。 Here是对它们的比较。
我决定实施金属工作流程。所以我有以下参数来计算:
对于镜面反射部分,我需要确定镜面反射颜色。
Mamoset表示
使用金属度贴图时,绝缘曲面 - 像素设置为0.0 金属度图中的(黑色) - 被赋予固定的反射率值 (线性:0.04 sRGB:0.22)并使用反射率映射进行漫反射 值。对于金属表面 - 像素设置为1.0(白色) 金属度图 - 镜面颜色和强度取自 反照率地图,着色器中的漫反射值设置为0(黑色)。
因此,镜面反射颜色应按以下方式计算:
vec3 specularColor = mix(vec3(0.04), material.albedo, material.metalness);
随后,这可用于计算反射辐射。为了限制我的问题的范围,我将在这里参考Brian Karis的实现,其中包括:
vec3 L_specular = specularIBL(specularColor, material.roughness, normal, view);
对于漫反射部分,我需要确定反照率。
上述相同的引用描述了它的工作原理:
vec3 albedo = mix(material.albedo, vec3(0), material.metalness);
现在,Lambert BRDF可用于计算来自某些入射辐照度E的漫反射光照:
vec3 L_diffuse = f_lambert(albedo) * E;
为了获得最终的光亮度,漫反射和镜面反射部分组合在一起:
vec3 L = kd * L_diffuse + ks * L_specular;
我的问题是如何计算kd
和ks
?
ks
。 kd
计算:
vec3 kd = (1 - ks) * (1 - material.metalness);
我在非金属上得到的结果并不是我所期望的,例如将它与虚幻引擎进行比较。在正常入射时预期的反射要低得多,这应该归因于在非金属情况下设定的低F0。但我检查了更多的来源,0.04似乎是常用的值。
有人可以确认Codinglabs的建议计算吗?或者甚至提供Epic使用的代码?
答案 0 :(得分:1)
正如您已经确定的,反照率对应于材质的漫反射颜色。
说到镜面反射,它有两种方式:电介质或导体(通常为金属)。
对于电介质,这很简单,镜面反射颜色始终为纯白色(无着色),并由菲涅尔和基础反射率(也称为 F0< /strong>) :此标量仅表示直视表面时反射的光的百分比。
“0.04”值对应于 4% 基础反射率,您可以通过将 1.5 的 IOR 替换为 < em>n1 在菲涅耳反射率公式和空气的 IOR(近似于 1.0)对于 n2 (taken off Wikipedia):
在互联网上很容易找到给定材料的 IOR,而且大多数介电常数都在 1.5 左右。
在导体的情况下,公式不是那么简单,所以你会发现实现的通常方法(由 Codinglabs、UE4 和其他引擎)是明确指定金属的色调/反射/镜面颜色,因为它对艺术家更友好。例如,纯红色意味着 100% 的红光被反射,而 100% 的蓝光和绿光被吸收。
金属性术语只是一个粗略的近似值,用于在明确的艺术家指定的反射颜色与正确/计算出的 F0 之间进行插值,后者适用于电介质。 >
我不相信您发布的链接上的公式是完全正确的。能量守恒定律意味着漫反射和镜面反射能量之和为1.0。因此,kd 应该是:
kd = (1 - ks)
这样想:任何未被材料吸收的光都应该被反射。
此外,(1 - material.metalness) 在计算镜面反射颜色时已经考虑在内:
vec3 specularColor = mix(vec3(0.04), material.albedo, material.metalness);
还有漫反射颜色:
vec3 albedo = mix(material.albedo, vec3(0), material.metalness);
纯导体基本上只有镜面反射,没有扩散。