У меня есть плоская поверхность воды с дудв и нормальная карта, прикрепленная к ней. Карта dudv работает правильно, и нормальная карта также прикреплена правильно (визуализация нормальной карты выглядит так, как должна). Зеркальные блики всегда отображаются не в том месте, как если бы направление света было неправильным. Освещение работает корректно без нормального отображения, поэтому я не верю, что это направление света, но, вероятно, что-то с касательным пространством. Поскольку я вычисляю касательное пространство от статического набора векторов, я смущен, когда он может пойти не так.Нормальное отображение на плоской поверхности воды дает неправильные блики
Здесь в вершинном шейдере я создаю матрицу ТБН, что я использую для создания касательного пространства векторов, которые я посылаю в пиксельный шейдер:
const vec3 TANGENT = vec3(1.0, 0.0, 0.0);
const vec3 NORMAL = vec3(0.0, 1.0, 0.0);
const vec3 BITANGENT = vec3(0.0, 0.0, -1.0);
out vec3 FragPos;
out vec3 TangentFragPos;
out vec3 TangentLightDir;
out vec3 TangentPlayerPos;
void main()
{
FragPos = vec3(model * vec4(vertex, 1.0));
mat3 mod = transpose(inverse(mat3(model)));
[...]
vec3 n = normalize(mod * NORMAL);
vec3 t = normalize(mod * TANGENT);
vec3 b = normalize(mod * BITANGENT);
mat3 TBN = transpose(mat3(t, b, n));
TangentFragPos = TBN * FragPos;
TangentLightDir = TBN * sun.Position.xyz;
TangentPlayerPos = TBN * playerPos;
}
В пиксельный шейдер я тогда образец нормальный вектор из нормальное отображение и использование трансформированных касательного пространства векторов вычислить блики:
in vec3 FragPos;
in vec3 TangentFragPos;
in vec3 TangentLightDir;
in vec3 TangentPlayerPos;
uniform sampler2D normalMap;
void main()
{
[...]
vec3 normal = texture(normalMap, vec2(TexCoords * TextureScale) + vec2(Time)).xyz;
normal = normalize(normal * 2.0 - 1.0);
// normal = vec3(0.0, 0.0, 1.0); // this gives proper specular highlights, but not mapped
// Specular lighting
vec3 lightDir = normalize(-TangentLightDir);
viewDir = normalize(TangentPlayerPos - TangentFragPos);
vec3 reflectDir = normalize(reflect(-lightDir, normal));
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 64);
vec3 lighting = sun.Specular * spec * fresnel;
color.xyz *= lighting;
}
Обратите внимание, что я делаю освещение в мировом пространстве.
Освещение прекрасно работает без нормального отображения, но как только я вводим матрицу TBN в уравнения, зеркальные блики находятся не в правильном направлении на воде.
EDIT
Я добавил изображение, чтобы увидеть, как она выглядит в настоящее время и где зеркальная свет должен быть. Это может добавить некоторое дополнительное понимание проблемы:
EDIT2
Вот странная вещь. Если я вручную определяю нормальный вектор как vec3(0.0, 0.0, 1.0)
(указывающий вверх в касательном пространстве), я получаю идеальные зеркальные блики (но без изменения отображения), и как только я беру нормаль с нормальной карты, я снова получаю неправильные подсветки, поэтому я бы сказал, причина вопроса была бы у нормалей. Нормальная карта я использую, однако это нормальная карта по умолчанию вы обычно видите, как вы можете увидеть ниже:
Почему когда я беру нормальный из этой карты нормалей (который уже должен быть в касательном пространстве), зеркальные блики ломаются?
Это для отложенного затенения? Если нет, вы должны вычислять эти векторы освещения в вершинном шейдере и интерполировать их. В противном случае вы делаете много ненужной работы в шейдере фрагмента (который работает на порядки чаще, чем вершинный шейдер). –
Что еще более важно, ваша матрица TBN представляется транспонированной. Вместо этого я попробую 'mat3 (TANGENT, BITANGENT, NORMAL)'. –
Это для прямого рендеринга. Я постараюсь использовать транстовую версию TBN и спасибо за предложения. Как только это сработает, я сделаю тангенциальные вычисления в вершинном шейдере – ABHAY