You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

切线空间观察方向因子值重映射实现线性变化遮罩

切线空间类菲涅尔遮罩线性化方案

现有逻辑问题

你当前使用的计算式:

float mask = abs(-viewDirTangentSpace.x / viewDirTangentSpace.z)

本质是计算切线空间下视线与表面法线夹角θ的正切值tanθ:

  • 视线垂直表面时θ=0,tanθ=0
  • 视线逐渐转向掠射角时θ趋近90°,tanθ趋近无穷大
    这个值天然呈非线性增长,且没有做值域约束,是导致效果不符合预期的核心原因。
    当前效果参考

线性重映射实现

要得到随夹角θ线性变化的遮罩,只需要通过反正切函数把正切值还原为线性的角度值,再归一化到[0,1]区间即可,同时补上除零保护避免z值过小时出现渲染异常:

const float PI_HALF = 1.5707963;
const float EPSILON = 1e-4;
// 计算带除零保护的tanθ
float tanTheta = abs(-viewDirTangentSpace.x / max(viewDirTangentSpace.z, EPSILON));
// 还原为弧度制夹角θ,范围[0, PI/2)
float theta = atan(tanTheta);
// 线性映射到[0,1]区间,正对表面为0,掠射角为1
float linearMask = saturate(theta / PI_HALF);

如果需要匹配参考图里PS曲线调整后的过渡效果,不需要额外采样曲线纹理,直接加一个幂次参数控制边缘软硬即可,性能开销极低:

// edgePower参数控制边缘过渡:值越大边缘越锐利,值越小过渡范围越宽
// 匹配你给出的目标效果时,edgePower取1.2~2.0区间即可
float finalMask = pow(linearMask, edgePower);

目标效果参考

如果需要1:1匹配PS里的自定义曲线,可以把曲线导出为256像素的1维查找表(LUT),在shader里用linearMask作为UV采样LUT即可,精度足够满足生产需求。

内容的提问来源于stack exchange,提问作者MaT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 06:45:41