首页 文章

Perlin Noise:为什么二阶插值导数会产生正常/阴影伪影?

提问于
浏览
2

我正在研究/实现Perlin NoiseImproved Perlin Noise的版本 . Perlin在他的论文中说他取代了smoothstep函数

3t^2 - 2t^3

他曾经使用以下功能在网格单元的角上插入8个线性函数:

6t^5 - 15t^4 + 10t^3

因为smoothstep函数的二阶导数是不连续的 . 他说(并且在他所显示的图像中清晰可见),这会导致一些视觉假象,因为正常情况的方式是使用此功能的结果 . 现在我明白了不连续的功能是什么 . 我也理解如何使用Perlin噪声函数的偏导数在Perlin噪声函数中计算法线,但我不明白为什么二阶导数不连续会导致法线问题 . 使用Noise函数的一阶导数计算法线,而不是二阶导数 . 那么二阶导数不连续的事实怎么会对法线产生这样的影响呢?

enter image description here

有关improved Noise Function的更多详细信息 .

1 回答

  • 0

    那么二阶导数不连续的事实怎么会对法线产生这样的影响呢?

    首先,请记住二阶导数是法线的一阶导数 . 问题不在于计算法线,而在于法线在太空中的进展程度 . 这将直接影响照明并证明基础功能的平滑性,并且一般而言,功能越连续可导,其感觉越平滑 .

    虽然Perlin以前的方法导致连续法线和连续着色,但你仍然可以分辨边界的位置,因为着色没有连续导数,我们的感知被设计为感知它是什么:一个不是那样的连续表面在那个边界平滑

    看看这四个功能(从上到下):

    • Blatantly中断映射

    • 连续映射,不连续导数

    • 连续导数

    • 无限连续导数

    half TriangleWave (half x) {
    
                x = 2 * frac(x/2);
                return min(x, 2 - x);
            }
    
            half SShape (half x) {
    
                x = saturate(x);
                return x * x * (3 - 2 * x);
            }
    
            fixed4 frag (v2f f) : SV_Target {
    
                // Bottom to top coordinate system
                half x = 3 * f.tex.x;
                half y = f.tex.y;
    
                if (y > 0.75)
                    return frac(x);
                if (y > 0.5)
                    return TriangleWave(x);
                if (y > 0.25)
                    return SShape(TriangleWave(x));
                return 0.5 - 0.5 * cos(x*3.141592);
            }
    

    Functions smoothness comparison

    最后一个是最顺畅的,但你几乎无法从第三个告诉它 . 但第二个,虽然是一个连续的映射,仍然让你感觉到边界 .

    由于法线对照明的直接影响(以前的着色器很容易作为照明计算),您基本上是在第二个和第三个选项之间进行选择 . 这就是为什么你通常希望法线本身是连续可微的,而不仅仅是为了保持连续性

相关问题