Я хочу сделать планету похожей на сферу. Общая идея такова:
- Создайте группу вершин единичной длины, которые составляют сферу.
- При рендеринге сферы шейдер оценивает 3D-симплексный шум в точке на единичной сфере.
- Результат используется как «высота» для смещения текущей вершины вдоль ее направления.
До сих пор все работает как надо.
Теперь я хочу добавить освещение и поэтому мне нужны нормали к поверхности.
При реализации частей, связанных с освещением, я быстро добавил метод для оценки нормалей ландшафта с использованием частных производных во фрагментном шейдере, например:
vec3 X = dFdx(ins.position);
vec3 Y = dFdy(ins.position);
vec3 normal = normalize(cross(X,Y));
где ins.position
— интерполированная мировая позиция.
Хотя это и работает, но выглядит не очень хорошо, потому что по существу приводит к нормалям для каждого лица.
Теперь собственно вопросы:
- Вычисление нормалей для каждой вершины приведет к гладким нормалям, в отличие от рисунка, верно?
- Одним из преимуществ Simplex Noise по сравнению с Perlin Noise является то, что он имеет «хорошо определенный и непрерывный градиент везде, который можно вычислить довольно дешево» (цитируя превосходный Симплексный шум демистифицирован), а с помощью градиента можно вычислить нормаль, правильно?
Если второй вопрос - "да", у меня две проблемы:
- Алгоритм симплексного шума был взят из популярного источника, который, к сожалению, не включает вычисление градиента. Я опубликую свою попытку добавить его ниже, но я понятия не имею, правильно ли это.
- Даже если бы у меня был градиент, я застрял на выводе нормали оттуда.
Любая помощь приветствуется!
Моя попытка реализации градиента (заменены последние несколько строк snoise а>):
float snoise(vec3 v, out vec3 grad)
{
......
// Mix final noise value
vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);
vec4 m2 = m * m;
vec4 m4 = m2 * m2;
vec4 pdotx = vec4(dot(p0,x0), dot(p1,x1), dot(p2,x2), dot(p3,x3));
vec4 temp = m2 * m * pdotx;
grad = -8.0 * (temp.x * x0 + temp.y * x1 + temp.z * x2 + temp.w * x3);
grad += m4.x * p0 + m4.y * p1 + m4.z * p2 + m4.w * p3;
grad *= 42.0;
return 42.0 * dot(m4, pdotx);
}
ОБНОВЛЕНИЕ:
Ответ на часть о вычислении нормали к поверхности из градиента был дан здесь: Surface нормаль к точке на смещенной сфере.
Остался вопрос, как внедрить вычисление градиента в GLSL-версию 3D Simplex Noise, потому что в моей реализации есть проблемы.
ОБНОВЛЕНИЕ 2:
Вычисление градиента кажется почти правильным, только масштабирование кажется неправильным.
Вместо умножения на 42 довольно хорошие результаты дает деление на 5, но это было выяснено методом проб и ошибок. . Правильный коэффициент масштабирования был бы хорош.
dFdx
иdYdx
. - person Justin   schedule 17.12.2014