Исходя из ответа kvark, хотелось бы добавить еще мысли.
Если вам нужна ортонормированная матрица касательного пространства, вам все равно придется поработать. Даже если вы добавите атрибуты касательной и бинормали, они будут интерполироваться на этапах шейдера, и в конце они не нормализуются и не являются нормальными по отношению друг к другу.
Предположим, что у нас есть нормализованный нормальный вектор n
, а также касательная t
и бинормальb
, или мы можем вычислить их из производных следующим образом:
// derivations of the fragment position
vec3 pos_dx = dFdx( fragPos );
vec3 pos_dy = dFdy( fragPos );
// derivations of the texture coordinate
vec2 texC_dx = dFdx( texCoord );
vec2 texC_dy = dFdy( texCoord );
// tangent vector and binormal vector
vec3 t = texC_dy.y * pos_dx - texC_dx.y * pos_dy;
vec3 b = texC_dx.x * pos_dy - texC_dy.x * pos_dx;
Конечно, ортонормированная матрица касательного пространства может быть вычислена с помощью перекрестного произведения, но это будет работать только для правосторонних систем. Если матрица была зеркалирована (левая система), она превратится в правую систему:
t = cross( cross( n, t ), t ); // orthonormalization of the tangent vector
b = cross( n, t ); // orthonormalization of the binormal vector
// may invert the binormal vector
mat3 tbn = mat3( normalize(t), normalize(b), n );
В приведенном выше фрагменте кода бинормальный вектор перевернут, если касательное пространство является левосторонней системой. Чтобы этого избежать, нужно пройти тяжелый путь:
t = cross( cross( n, t ), t ); // orthonormalization of the tangent vector
b = cross( b, cross( b, n ) ); // orthonormalization of the binormal vectors to the normal vector
b = cross( cross( t, b ), t ); // orthonormalization of the binormal vectors to the tangent vector
mat3 tbn = mat3( normalize(t), normalize(b), n );
Обычный способ ортогонализации любой матрицы - это процесс Грама – Шмидта:
t = t - n * dot( t, n ); // orthonormalization ot the tangent vectors
b = b - n * dot( b, n ); // orthonormalization of the binormal vectors to the normal vector
b = b - t * dot( b, t ); // orthonormalization of the binormal vectors to the tangent vector
mat3 tbn = mat3( normalize(t), normalize(b), n );
Другая возможность состоит в том, чтобы использовать определитель матрицы 2 * 2, который получается из выводов координат текстуры texC_dx
, texC_dy
, чтобы учесть направление вектора бинормали. Идея состоит в том, что определитель ортогональной матрицы равен 1, а определитель ортогональной зеркальной матрицы равен -1.
Определитель может быть вычислен с помощью функции GLSL determinant( mat2( texC_dx, texC_dy )
или по формуле texC_dx.x * texC_dy.y - texC_dy.x * texC_dx.y
.
Для вычисления ортонормированной матрицы касательного пространства бинормальный вектор больше не требуется, и можно избежать вычисления единичного вектора (normalize
) бинормального вектора.
float texDet = texC_dx.x * texC_dy.y - texC_dy.x * texC_dx.y;
vec3 t = texC_dy.y * pos_dx - texC_dx.y * pos_dy;
t = normalize( t - n * dot( t, n ) );
vec3 b = cross( n, t ); // b is normlized because n and t are orthonormalized unit vectors
mat3 tbn = mat3( t, sign( texDet ) * b, n ); // take in account the direction of the binormal vector
person
Rabbid76
schedule
04.07.2017
v_nglNormal
по сравнению сa_normal
? - person Mike Weir   schedule 13.09.2014