我正在尝试学习创建和使用Perlin噪声的分析导数来快速生成法线。我一直在尝试使用Catlike Coding's tutorials中的一个代码,尽管我想到了“上”轴为1并在2D平面上采样时进行归一化的想法,但我找不到有关该做什么的任何信息。在3D表面上采样时。
这就是我的追求(它使用中心差异法线):
这就是这些法线在世界空间中的样子:
但是我得到的派生看起来像这样:
似乎它们可能相对于未位移球体的表面,是否意味着我需要使用未位移球体的法线来重新定向它们?然后,如何将导数转换为法线?
答案 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...
以下是一些查找法线和斜率的代码:
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)而不是旋转噪声来进行斜率混合。也要尝试弄乱。