2017-01-02 13 views
3

В настоящее время я работаю над своим первым движком на базе OpenGL. Мне нужно нормальное отображение в качестве функции, но оно работает неправильно.Проблемы с нормальным отображением OpenGL - Нормали, возможно, сталкиваются с неправильным направлением?

Here is an animation of what is Happening

Артефакты зависят от угла между светом и нормалей на поверхности. Движение камеры никоим образом не влияет на это. Я также (по крайней мере пока) идет по пути менее эффективного метода, когда нормаль, извлеченная из нормальной карты, преобразуется в пространство просмотра, а не преобразует все в касательное пространство.

Вот соответствующие части моего кода:

Генерация касательные и бикасательных

 for(int k=0;k<(int)mb->getIndexCount();k+=3) 
     { 
      unsigned int i1 = mb->getIndex(k); 
      unsigned int i2 = mb->getIndex(k+1); 
      unsigned int i3 = mb->getIndex(k+2); 

      JGE_v3f v0 = mb->getVertexPosition(i1); 
      JGE_v3f v1 = mb->getVertexPosition(i2); 
      JGE_v3f v2 = mb->getVertexPosition(i3); 

      JGE_v2f uv0 = mb->getVertexUV(i1); 
      JGE_v2f uv1 = mb->getVertexUV(i2); 
      JGE_v2f uv2 = mb->getVertexUV(i3); 

      JGE_v3f deltaPos1 = v1-v0; 
      JGE_v3f deltaPos2 = v2-v0; 
      JGE_v2f deltaUV1 = uv1-uv0; 
      JGE_v2f deltaUV2 = uv2-uv0; 

      float ur = deltaUV1.x * deltaUV2.y - deltaUV1.y * deltaUV2.x; 

      if(ur != 0) 
      { 
       float r = 1.0/ur; 

       JGE_v3f tangent; 
       JGE_v3f bitangent; 

       tangent = ((deltaPos1 * deltaUV2.y) - (deltaPos2 * deltaUV1.y)) * r; 
       tangent.normalize(); 

       bitangent = ((deltaPos1 * -deltaUV2.x) + (deltaPos2 * deltaUV1.x)) * r; 
       bitangent.normalize(); 

       tans[i1] += tangent; 
       tans[i2] += tangent; 
       tans[i3] += tangent; 
       btans[i1] += bitangent; 
       btans[i2] += bitangent; 
       btans[i3] += bitangent; 
      } 
     } 

Here's a picture of the Tangents

Вычисление матрицы ТБН в Vertex Shader (mNormal корректирует нормальный для не- равномерные весы)

vec3 T = normalize((mVW * vec4(tangent, 0.0)).xyz); 
tnormal = normalize((mNormal * n).xyz); 
vec3 B = normalize((mVW * vec4(bitangent, 0.0)).xyz); 

tmTBN = transpose(mat3(
T.x, B.x, tnormal.x, 
T.y, B.y, tnormal.y, 
T.z, B.z, tnormal.z)); 

Наконец вот где я использую сэмпл нормально с нормальной карты и попытаться преобразовать его, чтобы просмотреть пространство в пиксельный шейдер

fnormal = normalize(nmapcolor.xyz * 2.0 - 1.0); 
fnormal = normalize(tmTBN * fnormal); 

«nmapcolor» является выборочный цвет от нормального отображения. «fnormal» затем используется, как обычно, в расчетах освещения.

Я пытаюсь решить это так долго и не имею абсолютно никакого представления о том, как это сделать. Любая помощь будет принята с благодарностью.

EDIT - Я немного изменил код для работы в мировом пространстве и вывел результаты. Большая платформа не имеет нормального отображения (и она работает правильно), в то время как меньшая платформа. World Space Normals

Я добавил, в каком направлении обращены нормали. Оба они должны быть одного цвета, но они совершенно разные. Кажется, что матрица mTBN не правильно преобразует нормальное касательное пространство в мир (и обычно просматривает) пространство.

+0

Это может быть глупый вопрос, но вы должны преобразовать 'tnormal'' mVW' в вершинный шейдер? – Jadh4v

+0

Попытка, чтобы это не исправить. Я думаю, что 'mNormal' позаботится об этом, так как это инверсная транспонирование mVW. – Ruxify

+0

Попробуйте инвертировать 'nmapcolor.y = 1 - nmapcolor.y', возможно, вы смешали где-нибудь по оси y по сравнению с условными обозначениями. – ybungalobill

ответ

0

Ну ... Я решил проблему. Оказывается, моя нормальная реализация карт была идеальной. Проблема на самом деле была в моем классе текстур. Это, конечно, мой первый раз, когда я писал механизм рендеринга OpenGL, и я не понимал, что функция unlock() в моем классе текстур сохранила ВСЕ мои текстуры как GL_SRGB_ALPHA, включая нормальные карты. Только диффузные текстуры карт должны быть GL_SRGB_ALPHA. Временно заставляя все текстуры загружаться, поскольку GL_RGBA исправил проблему. Не могу поверить, что у меня была эта проблема в течение 11 месяцев, только чтобы найти ее было что-то такое маленькое.