在3D表面上使用分析性Perlin噪声导数

时间:2018-12-08 23:39:58

标签: math 3d derivative procedural-generation perlin-noise

我正在尝试学习创建和使用Perlin噪声的分析导数来快速生成法线。我一直在尝试使用Catlike Coding's tutorials中的一个代码,尽管我想到了“上”轴为1并在2D平面上采样时进行归一化的想法,但我找不到有关该做什么的任何信息。在3D表面上采样时。

这就是我的追求(它使用中心差异法线):

这就是这些法线在世界空间中的样子:

但是我得到的派生看起来像这样:

似乎它们可能相对于未位移球体的表面,是否意味着我需要使用未位移球体的法线来重新定向它们?然后,如何将导数转换为法线?

1 个答案:

答案 0 :(得分:0)

我想出了一个解决方案。我所做的就是使用世界空间表面法线构造一个旋转四元数,按照该旋转的反方向旋转导数向量,然后像在平面上那样将其转换为法线,然后再次以法向旋转将其旋转回去。 / p>

Using the derivatives as surface normals now looks like this

And now mixing octaves based on the slope of the normals looks like this...

And this...

And this

以下是一些查找法线和斜率的代码:

float3 qRotateVector(float3 v, float4 q) {
    float3 t = 2.0 * cross(q.xyz, v);
    return v + q.w * t + cross(q.xyz, t);
}

float4 qFromToRotation(float3 v) {
    float3 up = float3(0.0, 1.0, 0.0);
    float d = dot(up, v);

    if (d < -0.999999) {
        return float4(0.0, 0.0, 1.0, 0.0);
    }
    else if (d > 0.999999) {
        return float4(0.0, 0.0, 0.0, 1.0);
    }
    else {
        return normalize(float4(cross(up, v), d + 1.0));
    }
}

float noiseSlope(float3 derivatives, float3 normal) {
    float4 noiseRotation = qFromToRotation(normal);
    float3 derivativeNormal = qRotateVector(derivatives, float4(-noiseRotation.xyz, noiseRotation.w));
    return abs(dot(normalize(float3(-derivativeNormal.x, 1.0, -derivativeNormal.z)), float3(0.0, 1.0, 0.0)));
}

(我最初尝试使用矩阵,但在使用云台锁定时一直遇到问题)

经过实验,我发现Inigo Quilez还有一个示例,它通过将高度除以1 +点(derivative.yz,derivative.yz)而不是旋转噪声来进行斜率混合。也要尝试弄乱。