2015-03-09 3 views
4

У меня есть плоская поверхность воды с дудв и нормальная карта, прикрепленная к ней. Карта 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

Я добавил изображение, чтобы увидеть, как она выглядит в настоящее время и где зеркальная свет должен быть. Это может добавить некоторое дополнительное понимание проблемы:

  Screenshot

EDIT2

Вот странная вещь. Если я вручную определяю нормальный вектор как vec3(0.0, 0.0, 1.0) (указывающий вверх в касательном пространстве), я получаю идеальные зеркальные блики (но без изменения отображения), и как только я беру нормаль с нормальной карты, я снова получаю неправильные подсветки, поэтому я бы сказал, причина вопроса была бы у нормалей. Нормальная карта я использую, однако это нормальная карта по умолчанию вы обычно видите, как вы можете увидеть ниже:

Normal map of water

Почему когда я беру нормальный из этой карты нормалей (который уже должен быть в касательном пространстве), зеркальные блики ломаются?

+0

Это для отложенного затенения? Если нет, вы должны вычислять эти векторы освещения в вершинном шейдере и интерполировать их. В противном случае вы делаете много ненужной работы в шейдере фрагмента (который работает на порядки чаще, чем вершинный шейдер). –

+0

Что еще более важно, ваша матрица TBN представляется транспонированной. Вместо этого я попробую 'mat3 (TANGENT, BITANGENT, NORMAL)'. –

+0

Это для прямого рендеринга. Я постараюсь использовать транстовую версию TBN и спасибо за предложения. Как только это сработает, я сделаю тангенциальные вычисления в вершинном шейдере – ABHAY

ответ

3

Это уже более недели отладки, и я наконец нашел проблему. Я использую гамма-коррекцию, и мой класс текстур по умолчанию загружает текстуру с свойством GL_SRGB в качестве внутреннего формата текстуры, поэтому OpenGL правильно преобразует текстуры с коррекцией гаммы в своих линейных братьев.

Проблема заключалась в том, что я также загрузил карту dudv и Normal с этим классом текстур, не изменяя это свойство, поэтому нормальная карта и dudv применяли гамма-> линейную коррекцию OpenGL и, таким образом, дали неверные результаты.

Загрузка этих текстур GL_RGB решила проблему.

2

Вы находитесь в левой или правой системе координат? Рассматривали ли вы проверку действительности ваших статических векторов матрицы TBN?

EDIT: Биттангент извлекается путем пересечения нормального и касательного. Итак, normal(0,1,0) x tangent(1,0,0) равно bitangent(0,0,-1)

+0

Это должен быть комментарий, а не ответ. –

+0

Извините, мне не разрешили добавлять комментарии ... –

+0

Я нахожусь на правой системе координат. Если я правильно напомню, это означает, что битангант должен быть равен поперечному произведению нормали и касательной, которая с правым правилом дает вектор в положительном направлении z (в r-координатной системе координат). Если я не ошибаюсь, они должны быть правильными? – ABHAY

 Смежные вопросы

  • Нет связанных вопросов^_^