Войти
ПрограммированиеТерминыГрафика

Tangent Space (Пространство касательных)

Tangent space (Пространство касательных) — векторное пространство, при помощи базисов которого векторы из трёхмерного пространства (обычно объектного пространства) переносятся в текстурное пространство трехмерного объекта.

В данном случае текстурное пространство расширено с двухмерного до трёхмерного, добавлением оси Z, сама текстура лежит в плоскости XOY, ось Z направлена на наблюдателя, если бы он, смотрел на эту текстуру сверху.

Базисы пространства касательных задаются для каждой вершины трёхмерного объекта. Три единичных вектора, составляющие базис и называющиеся tangent, binormal и normal  не обязательно могут быть взаимно перпендикулярными.

Вектор tangent — касательный вектор в некоторой точке поверхности к этой поверхности, направление которого задано вдоль увеличения значений координат по оси X (или u, в терминах uv координат для текстур) текстурного маппинга объекта. Аналогично binormal вдоль оси Y. Вектор normal является векторным произведением tanget-а и binormal-и, что по идее, должно соответствовать обычной нормали в рассматриваемой точке к поверхности трёхмерного объекта.

Через пространство касательных задаётся ориентация текстурного пространства на поверхности трёхмерного объекта. Это необходимо, например, для просчёта освещения, когда одни параметры, например, нормали поверхности, заданы текстурой (например, картой нормали), а другие, например, вектор направления к источнику света, задан в трёхмерном пространстве. То есть пространство касательных переносит одни параметры в пространство других параметров, а именно, вектор из трёхмерного пространства переносится в текстурное пространство.

Используется для диффузно-спекулярного bump mapping-а, параллакс маппинга.

Поскольку, после преобразования в текстурное пространство, в полученном векторе, который далее участвует в просчётах, не сохраняется информация о том, что базис состоит из не взаимно перпендикулярных векторов, можно видеть, что достаточно для преобразования хранить только поворот для вектора из трёхмерного пространства. То есть пространство касательных можно подобрать с базисами с взаимно перпендикулярными векторами, а, следовательно, поменять каждый базис на кватернион в целях возможной оптимизации.

Расчет базиса(для одного фейса)

Способ №1:

    float bump_factor=0.5f;
    vec3 sw;
    vec3 u( m_Vertex[i].m_TexCoord[0],
            m_Vertex[ii].m_TexCoord[0],
            m_Vertex[iii].m_TexCoord[0]);
    vec3 v( m_Vertex[i].m_TexCoord[1],
            m_Vertex[ii].m_TexCoord[1],
            m_Vertex[iii].m_TexCoord[1]);
    vec3 id(1,1,1);
    sw=u*id;
    sw=sw*(bump_factor/v.Dot(sw));

    m_Vertex[i].m_T = m_Vertex[i].m_Position*sw.x + 
                      m_Vertex[ii].m_Position*sw.y +
                      m_Vertex[iii].m_Position*sw.z;

    sw=v*id;
    sw=sw*(bump_factor/u.Dot(sw));

    m_Vertex[i].m_B = m_Vertex[i].m_Position*sw.x + 
                      m_Vertex[ii].m_Position*sw.y +
                      m_Vertex[iii].m_Position*sw.z;
    
    m_Vertex[i].m_T.Normalize();
    m_Vertex[i].m_B.Normalize();


Способ №2:

  vec3 e0 ( 
    m_Vertex[b].m_Position.x - m_Vertex[a].m_Position.x, 
    m_Vertex[b].m_TexCoord.x - m_Vertex[a].m_TexCoord.x, 
    m_Vertex[b].m_TexCoord.y - m_Vertex[a].m_TexCoord.y 
    );
  vec3 e1 ( 
    m_Vertex[c].m_Position.x - m_Vertex[a].m_Position.x,
    m_Vertex[c].m_TexCoord.x - m_Vertex[a].m_TexCoord.x, 
    m_Vertex[c].m_TexCoord.y - m_Vertex[a].m_TexCoord.y 
    );
  vec3 cp = e0 * e1;

  if ( fabs ( cp.x ) > (10e-6) )
  {
    m_Vertex[a].m_T.x = -cp.y / cp.x;
    m_Vertex[a].m_B.x = -cp.z / cp.x;
  }else{
    m_Vertex[a].m_T.x = 0;
    m_Vertex[a].m_B.x = 0;
  }

  e0.x = m_Vertex[b].m_Position.y - m_Vertex[a].m_Position.y;
  e1.x = m_Vertex[c].m_Position.y - m_Vertex[a].m_Position.y;
  cp   = e0 * e1;

  if ( fabs ( cp.x ) > (10e-6) )
  {
    m_Vertex[a].m_T.y = -cp.y / cp.x;
    m_Vertex[a].m_B.y = -cp.z / cp.x;
  }else{
    m_Vertex[a].m_T.y = 0;
    m_Vertex[a].m_B.y = 0;
  }

  e0.x = m_Vertex[b].m_Position.z - m_Vertex[a].m_Position.z;
  e1.x = m_Vertex[c].m_Position.z - m_Vertex[a].m_Position.z;
  cp   = e0 * e1;

  if ( fabs ( cp.x ) > (10e-6) )
  {
    m_Vertex[a].m_T.z = -cp.y / cp.x;
    m_Vertex[a].m_B.z = -cp.z / cp.x;
  }
  else
  {
    m_Vertex[a].m_T.z = 0;
    m_Vertex[a].m_B.z = 0;
  }

  if ( ( m_Vertex[a].m_T * m_Vertex[a].m_B ).Dot(m_Vertex[a].m_Normal) < 0 )
    m_Vertex[a].m_T.Negate() ;

Что такое Tangent Space (Пространство касательных)?

#векторы, #нормали, #пространство, #тангенты, #трансформации

14 августа 2005 (Обновление: 22 сен. 2009)