Я нашел решение. Что я сделал, так это построил кватернион вращения, используя нормаль к поверхности мирового пространства, повернул производный вектор на обратное этому вращению, затем превратил его в нормаль, как если бы вы это делали на плоскости, и снова повернул обратно с нормальным вращением.
Использование производных в качестве нормалей поверхности теперь выглядит следующим образом
А теперь микширование октав на основе наклона нормалей выглядит так ...
А это ...
А это
А вот код, который находит нормаль и наклон:
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 также имеет пример микширования с помощью slope, разделив высоту на 1 + точку (производная.yz, производная.yz) вместо вращения шума, с которым я тоже собираюсь попробовать.
person
Chrism
schedule
20.12.2018
vec3 normal = vec3(normalize(vertex.xyz - (derivative.xyz * 0.45)));
. Это даст вам правильную вершину нормали. - person Pedro Henrique   schedule 26.01.2021