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

如何基于高度场纹理计算像素法向量复现Core Image Shaded Material滤镜?

用Metal复现Core Image Shaded Material滤镜的核心实现细节

1. 从高度场纹理计算法向量

高度场的法向量通过相邻像素的高度梯度推导,在Metal片段着色器中可按以下步骤实现:

  • 定义高度场纹理的采样步长:float2 step = 1.0 / float2(heightTexture.width, heightTexture.height);
  • 获取当前像素及上下左右邻点的高度值(假设高度存储在纹理的R通道):
    float h = heightTexture.sample(sampler, uv).r;
    float hLeft = heightTexture.sample(sampler, uv - float2(step.x, 0.0)).r;
    float hRight = heightTexture.sample(sampler, uv + float2(step.x, 0.0)).r;
    float hDown = heightTexture.sample(sampler, uv - float2(0.0, step.y)).r;
    float hUp = heightTexture.sample(sampler, uv + float2(0.0, step.y)).r;
    
  • 计算X、Y方向的梯度,推导法向量并归一化:
    float dx = (hRight - hLeft) / (2.0 * step.x);
    float dy = (hUp - hDown) / (2.0 * step.y);
    float3 normal = normalize(float3(-dx, -dy, 1.0));
    
    这里的负号对应高度场的坐标系方向,可根据实际纹理的Y轴方向调整。

2. RGB像素转换为2分量法向量

如果你的RGB纹理是存储法向量的图,通常是将法向量的X、Y分量从[-1,1]映射到[0,1]区间后存在R、G通道:

  • 采样RGB法向量纹理:float3 rgbNormal = normalTexture.sample(sampler, uv).rgb;
  • 将R、G通道反向映射回[-1,1]区间,得到2分量法向量:
    float2 xyNormal = rgbNormal.rg * 2.0 - 1.0;
    
    若需要完整法向量,Z分量可通过sqrt(1.0 - dot(xyNormal, xyNormal))计算,但Shaded Material滤镜仅需XY分量用于半球图查找。

3. 半球着色图的采样坐标计算

文档中的公式是基于像素坐标的,但Metal纹理采样默认使用归一化UV([0,1]范围),所以可以简化:

  • 用归一化法向量的XY分量计算采样UV:float2 lookupUV = (normal.xy + 1.0) * 0.5;
  • 直接用该UV采样半球着色图:float3 finalColor = shadingTexture.sample(sampler, lookupUV).rgb;
    如果必须使用像素坐标采样,再乘以着色图的尺寸即可,不过归一化UV是Metal的常规用法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 06:30:01