Irridescence从理论到实践
摘要:本文解析基于薄膜干涉的彩虹色渲染技术,详细介绍了KHR_materials_iridescence扩展的参数体系(厚度、折射率)及实现原理,包括BRDF模型在金属/电介质材质上的具体应用方法。
本文为这篇文章的翻译与整理
彩虹色(Iridescence)
彩虹色描述了一种色调随观察角和光照角变化的效果。
- 半透明层的薄膜产生相互反射,由于薄膜干涉,某些波长被吸收或放大。
- 例子包括肥皂泡、油膜和昆虫翅膀。
- 此扩展允许指定薄膜的厚度和折射率(IOR),实现彩虹色材质。
属性
| 类型 | 描述 | 必需 |
|---|---|---|
iridescenceFactor |
彩虹色强度因子。 | 否,默认值:0.0 |
iridescenceTexture |
彩虹色强度纹理。 | 否 |
iridescenceIor |
薄膜层的折射率。 | 否,默认值:1.3 |
iridescenceThicknessMinimum |
最小薄膜厚度(纳米)。 | 否,默认值:100.0 |
iridescenceThicknessMaximum |
最大薄膜厚度(纳米)。 | 否,默认值:400.0 |
iridescenceThicknessTexture |
厚度纹理。 | 否 |
- 强度计算:
iridescence = iridescenceFactor * iridescenceTexture.r
-
如果未设置纹理,假设值为
1.0。 -
如果
iridescenceFactor为零(默认),效果被禁用。 -
厚度计算:
thickness = mix(
iridescenceThicknessMinimum,
iridescenceThicknessMaximum,
iridescenceThicknessTexture.g
)
- 如果缺少厚度纹理,默认为
iridescenceThicknessMaximum。 - 色调变化源于反射波长的相长和相消干涉。
- 接近**可见光波长一半(380–750 nm)**的薄膜厚度产生最强的效果。
- 增加厚度由于混合干涉产生柔和色彩图案。
折射率(IOR)
- 薄膜折射率(
iridescenceIor)可以与基础材质不同。 - 薄膜折射率与基础材质折射率之间的差异越大,彩虹色效果越强。
- 折射率影响光程差和颜色偏移。
彩虹色BRDF
效果使用微表面BRDF和修改的菲涅尔反射项建模。
金属基础材质
metal_brdf =
iridescent_conductor_layer(
iridescence_strength = iridescence,
iridescence_thickness = iridescenceThickness,
iridescence_ior = iridescenceIor,
outside_ior = 1.0,
base_f0 = baseColor,
specular_brdf = specular_brdf(α = roughness^2)
)
电介质基础材质
dielectric_brdf =
iridescent_dielectric_layer(
iridescence_strength = iridescence,
iridescence_thickness = iridescenceThickness,
iridescence_ior = iridescenceIor,
outside_ior = 1.0,
base_ior = 1.5,
base = diffuse_brdf(color = baseColor),
specular_brdf = specular_brdf(α = roughness^2)
)
-
对于透射材质,
diffuse_brdf被与specular_btdf的混合替换(见KHR_materials_transmission)。 -
base_ior可以通过KHR_materials_ior修改。 -
与KHR_materials_specular结合时:
dielectric_brdf =
iridescent_dielectric_layer(
iridescence_strength = iridescence,
iridescence_thickness = iridescenceThickness,
iridescence_ior = iridescenceIor,
outside_ior = 1.0,
base_ior = 1.5,
base_f0_color = specularColor.rgb,
specular_weight = specular,
base = diffuse_brdf(color = baseColor),
specular_brdf = specular_brdf(α = roughness^2)
)
- 清漆层忽略与薄膜的界面以简化。
实现说明
金属基础材质
function iridescent_conductor_layer(iridescence_strength, iridescence_thickness, iridescence_ior, outside_ior, base_f0, specular_brdf) {
return mix(
conductor_fresnel(base_f0, specular_brdf),
specular_brdf * iridescent_fresnel(outside_ior, iridescence_ior, base_f0, iridescence_thickness),
iridescence_strength
)
}
电介质基础材质
function iridescent_dielectric_layer(iridescence_strength, iridescence_thickness, iridescence_ior, outside_ior, base_ior, base, specular_brdf) {
base_f0 = ((1 - base_ior)/(1 + base_ior))^2
iridescent_f = iridescent_fresnel(outside_ior, iridescence_ior, base_f0, iridescence_thickness)
return mix(
fresnel_mix(base_ior, base, specular_brdf),
rgb_mix(base, specular_brdf, iridescent_f),
iridescence_strength
)
}
rgb_mix确保能量守恒:
function rgb_mix(base, specular_brdf, rgb_alpha) {
rgb_alpha_max = max(rgb_alpha.r, rgb_alpha.g, rgb_alpha.b)
return (1 - rgb_alpha_max) * base + rgb_alpha * specular_brdf
}
- 与KHR_materials_specular结合时,添加base_f0_color和specular_weight:
function iridescent_dielectric_layer(...) {
base_f0 = ((1-base_ior)/(1+base_ior))^2 * base_f0_color
base_f0 = min(base_f0, float3(1.0))
fr = base_f0 + (1 - base_f0)*(1 - abs(VdotH))^5
iridescent_f = iridescent_fresnel(outside_ior, iridescence_ior, specular_weight * base_f0, iridescence_thickness)
return rgb_mix(base, specular_brdf, mix(specular_weight * fr, iridescent_f, iridescence_strength))
}
彩虹色菲涅尔
-
建模两个材质界面:
- 外部 → 薄膜
- 薄膜 → 基础材质
菲涅尔方程
float IorToFresnel0(float transmittedIor, float incidentIor) {
return pow((transmittedIor - incidentIor) / (transmittedIor + incidentIor), 2.0);
}
- 使用斯涅尔定律计算折射角的余弦:
float sinTheta2Sq = pow(outsideIor / iridescenceIor, 2.0) * (1.0 - pow(cosTheta1, 2.0));
float cosTheta2Sq = 1.0 - sinTheta2Sq;
if (cosTheta2Sq < 0.0) return vec3(1.0); // 全内反射
float cosTheta2 = sqrt(cosTheta2Sq);
相移
Δφ = (2π / λ) * OPD
OPD = 2 * iridescenceIor * iridescenceThickness * cosTheta2
- 每个界面的基础相位根据折射率关系近似为0.0或π。
- 忽略偏振。
解析光谱积分
- 在傅里叶空间中计算反射项:
vec3 R123 = clamp(R12 * R23, 1e-5, 0.9999);
vec3 r123 = sqrt(R123);
vec3 Rs = sq(T121) * R23 / (vec3(1.0) - R123);
vec3 C0 = R12 + Rs;
I = C0;
for (int m = 1; m <= 2; ++m) {
Cm *= r123;
vec3 Sm = 2.0 * evalSensitivity(float(m) * OPD, float(m) * phi);
I += Cm * Sm;
}
F_iridescence = max(I, vec3(0.0));
- 敏感性函数:
vec3 evalSensitivity(float OPD, vec3 shift) {
float phase = 2.0 * M_PI * OPD * 1.0e-9;
vec3 val = vec3(5.4856e-13, 4.4201e-13, 5.2481e-13);
vec3 pos = vec3(1.6810e+06, 1.7953e+06, 2.2084e+06);
vec3 var = vec3(4.3278e+09, 9.3046e+09, 6.6121e+09);
vec3 xyz = val * sqrt(2.0 * M_PI * var) * cos(pos * phase + shift) * exp(-sq(phase) * var);
xyz.x += 9.7470e-14 * sqrt(2.0 * M_PI * 4.5282e+09) * cos(2.2399e+06 * phase + shift[0]) * exp(-4.5282e+09 * sq(phase));
xyz /= 1.0685e-7;
vec3 rgb = XYZ_TO_REC709 * xyz;
return rgb;
}
- 颜色空间转换矩阵:
const mat3 XYZ_TO_REC709 = mat3(
3.2404542, -0.9692660, 0.0556434,
-1.5371385, 1.8760108, -0.2040259,
-0.4985314, 0.0415560, 1.0572252
);
完整推导在Belcour & Barla, 2017, section 4(解析光谱积分)中描述。
参考文献
- Belcour, L. and Barla, P. (2017): 微表面理论在变化彩虹色建模中的实用扩展
- Autodesk: Arnold for Maya用户指南 - 薄膜
- Drobot, M. and Micciulla, A. (2017): 使命召唤:无限战争中的实用多层材质
- Kneiphof, T., Golla, T., Klein, R. (2019): 变化彩虹色的微表面BRDF实时基于图像照明
- Akenine-Möller, T. et al. (2018): 实时渲染,第四版,第361页及以后
- Sussenbach, M. (2013): 实时渲染彩虹色物体
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 VanishingBlog!


