Я реализую базовую карту высот с простым затенением (ambient + diffuse). Затенение реализовано на фрагментном шейдере, который показан ниже.
#version 330
in vec3 fragNormal;
out vec4 outColor;
uniform vec3 lightDirection;
uniform vec3 lightColor;
uniform vec3 objectColor;
void main()
{
float ambientStrength = 0.1f;
vec3 ambientColor = ambientStrength * lightColor;
vec3 norm = normalize(fragNormal);
float diff = max(dot(norm, -normalize(lightDirection)), 0.0f);
vec3 diffuseColor = diff * lightColor;
outColor = vec4((ambientColor + diffuseColor) * objectColor, 1);
}
Что я делаю, так это вычисляю простой диффузный компонент на основе нормального fragNormal. Эта переменная передается непосредственно из вершинного шейдера.
Вот скриншот того, что у меня сейчас есть:
Это ожидаемый результат от карты высот с затенением пикселей?
Меня немного раздражает тот факт, что поверхность не очень гладкая.
Но если это ожидается, какая-нибудь техника, которая улучшает то, что у меня есть в настоящее время?
Для вычисления нормалей я использовал следующий алгоритм:
Метод конечных разностей (переполнение стека)
Использование пиксельного шейдера не дает вам плавного затенения бесплатно. Как правило, наличие только нормального на треугольник дает плоскую штриховку, которую вы видите на скриншоте. Вам нужен какой-то метод вычисления средневзвешенного значения нормалей для каждой вершины — метод взвешивания действительно зависит от вас (Вот это список возможностей).
А также Вот является SO сообщением, дающим псевдокод для нахождения весовых нормалей вершин.
Метод, который вы опубликовали, кажется быстрым способом аппроксимации нормалей для точки на карте высот. это Страница, кажется, указывает на то, чтобы сделать что-то похожее (вычисление суммы нормалей вокруг точки), чтобы достичь подобного эффекта сглаживания, при этом используя конечную разницу.