计算三角形网格的tangent space

又一篇学习笔记,参考Mathematics for 3D Game Programming and Computer Graphics和ShaderX4上一篇关于tangent space计算的文章写的东西。对于计算时需要分裂顶点的内容看的还不是太清楚-_-b。另外,目前的算法还不能完美处理镜像或者在纹理不连续处可能出现的问题,就算在Farcry中,很多问题也是通过美工来“隐藏”的,再一次应证了之前对美工重要性的结论^^。

 

 

 

 

 算法:

      Tangent space在Bump Map中有着重要作用,通常需要把灯光转换到tangent space进行计算。对由参数方程计算出的规则曲面(比如,球体,圆环)来说,很容易通过方程计算出tangent space,但对任意的三角形网格来说,则没有那么简单。

Tangent space是一个三维空间。对3D空间中的一个顶点来说,切空间的三条座标轴分别对应该点的法线N,切线T,和副法线(binormal)B,显然,对不同的顶点来说,切空间是不同的。那么在已知三角形三个顶点及其纹理坐标的时候,如何计算出NTB呢?

目前已知的数据有三角形的三个顶点在世界坐标中的位置: P0, P1,P2, 以及相应的纹理坐标在纹理空间中的位置C0 (U0,V0),C1,C2,则有:

 

P10 = P1 – P0,

P­20 = P2 - P1 ,

C10 = C1 – C0 = (U1-U0, V1-V0) = ( U10 ,V10)

C20 = C2 – C0.= (U2-U0, V2-V0) = ( U20 ,V20)

 

注意,P10在世界坐标中的方向和C10在纹理空间中的方向是一致的(这一点确实比较抽象,偶画图研究了好久才弄明白-_-),同样,20C20也是如此,发现这一点很重要,可以说是整个计算的基石。进一步来说,TB分别和纹理坐标轴UV是平行的。因此我们有:

 

P10 = U10T + V10B

P­20 = U20T + V20B

把矢量展开得到:

 

两边乘以[C10 C20]的逆矩阵,最后得到

 

法线N = T x B

这样我们就得到了坐标从切空间转变到世界坐标下的变换矩阵M = [ T B N ],当然,更加常用的是M的逆矩阵。注意,这里计算得出的只是面法线,如果需要计算每个顶点的法线,则应该对共享该顶点的多个面的法线取均值,求出结果。

 

实现:

 ogre calculate tangent:

Vector3 Math::calculateTangentSpaceVector(
 const Vector3& position1, const Vector3& position2, const Vector3& position3,
 Real u1, Real v1, Real u2, Real v2, Real u3, Real v3)
 {
   //side0 is the vector along one side of the triangle of vertices passed in, 
   //and side1 is the vector along another side. Taking the cross product of these returns the normal.
   Vector3 side0 = position1 - position2;
   Vector3 side1 = position3 - position1;
   //Calculate face normal
   Vector3 normal = side1.crossProduct(side0);
   normal.normalise();
   //Now we use a formula to calculate the tangent. 
   Real deltaV0 = v1 - v2;
   Real deltaV1 = v3 - v1;
   Vector3 tangent = deltaV1 * side0 - deltaV0 * side1;
   tangent.normalise();
   //Calculate binormal
   Real deltaU0 = u1 - u2;
   Real deltaU1 = u3 - u1;
   Vector3 binormal = deltaU1 * side0 - deltaU0 * side1;
   binormal.normalise();
   //Now, we take the cross product of the tangents to get a vector which 
   //should point in the same direction as our normal calculated above. 
   //If it points in the opposite direction (the dot product between the normals is less than zero), 
   //then we need to reverse the s and t tangents. 
   //This is because the triangle has been mirrored when going from tangent space to object space.
   //reverse tangents if necessary
   Vector3 tangentCross = tangent.crossProduct(binormal);
   if (tangentCross.dotProduct(normal) < 0.0f)
   {
     tangent = -tangent;
     binormal = -binormal;
   }

 return tangent;

 }

时间: 2024-09-21 07:50:07

计算三角形网格的tangent space的相关文章

Computing Tangent Space Basis Vectors for an Arbitrary Mesh

为一个任意网格模型计算其切线空间的基本向量(即切线空间的T B N三个向量) Modern bump mapping (also known as normal mapping) requires that tangent plane basis vectors be calculated for each vertex in a mesh. This article presents the theory behind the computation of per-vertex tangent

3D编程:第九章 Normal Mapping and Displacement Mapping

第九章 Normal Mapping and Displacement Mapping 本章主要讲述两种图形学技术,支持在不增加objects的poly primitive的情况下,在场景中增加更多的细节.第一种是normal mapping,通过创建一些"fake" geometry(虚设的多边形图元)模拟光照作用.第二种是displacement mapping,根据纹理数据moving vertices actually(与"fake"相对应,这里指真实的移动

MIT牛人解说数学体系

MIT牛人解说数学体系     在过去的一年中,我一直在数学的海洋中游荡,research进展不多,对于数学世界的阅历算是有了一些长进.   为什么要深入数学的世界 作 为计算机的学生,我没有任何企图要成为一个数学家.我学习数学的目的,是要想爬上巨人的肩膀,希望站在更高的高度,能把我自己研究的东西看得更深广一些. 说起来,我在刚来这个学校的时候,并没有预料到我将会有一个深入数学的旅程.我的导师最初希望我去做的题目,是对appearance和motion建立 一个unified的model.这个题

OGRE材质

"材质(material)",材质是一个很基本的术语,表示你的物体对光的反射方式.但是对它的实现并不像其解释这样简单,我们会用这一章节进行详细地介绍Ogre中相关的技术. 我们刚才提及过,材质定义了物体对光线反射的处理方法.这里暗示了材质的表现与光源的类型相关:聚光(Spotlights).点光源(point lights)以及有向光(directional lights)对材质的表现有着完全不同的影响.简单来讲,它们都是对物理世界真实光源类型的模拟,所以材质对它们的反射也遵守着其在物

ParallaxOcclusionMapping( POM ) DX9

ParallaxOcclusionMapping(后面成为POM)是一个不错的高级技术,在我看来它是至今让我印象最深刻的技术.与其说是视差,不如说准确的视线与高度图交点算法.在<Real-time Rendering>中也见过他的前身-ParallaxMapping,但是POM的精确度更高,对于斜视效果也很不错,这将让它在未来的重要技术中占有一席之地.闲话少说,还是重在实质技术.   在DX9的samples中,由ATI提高的POM案例,确实是一个不错的实践机会.看过2006的Dynamic

麻省理工(MIT)牛人解说数学体系

一.为什么要深入数学的世界 作为计算机的学生,我没有任何企图要成为一个数学家.我学习数学的目的,是要想爬上巨人的肩膀,希望站在更高的高度,能把我自己研究的东西看得更深广一些.说起来,我在刚来这个学校的时候,并没有预料到我将会有一个深入数学的旅程.我的导师最初希望我去做的题目,是对appearance和motion建立一个unified的model.这个题目在当今Computer Vision中百花齐放的世界中并没有任何特别的地方.事实上,使用各种Graphical Model把各种东西联合在一起

Skinned Mesh原理解析和一个最简单的实现示例

Skinned Mesh原理解析和一个最简单的实现示例   作者:n5 Email: happyfirecn@yahoo.com.cn Blog: http://blog.csdn.net/n5 2008-10月   Histroy: Version:1.01  Date:2008-11-01        修改了一些不精确的用语 Version:1.00 Date:2008-10-19     讲述骨骼动画的资料很多,但大部分都是针对DX8或DX9的SkinnedMesh进行讲解.我觉得对于骨

【Aladdin Unity3D Shader编程】之一 基本入门

OpenGL.DirectX以及GLSL.HLSL.CG OpenGL和DirectX是图像应用编程接口,用于渲染二维或者三维图形. GLSL着色语言是用来在OpenGL中着色编程的语言,有点在于跨平台性,可以再Windows.Linux.Mac甚至移动平台上工作. HLSL是微软控制着色的编译,几乎只支持微软自己的产品,如Windows,XBox等,其他平台没有可编译HLSL的编译器. CG是有英伟达公司出的真正意义上的跨平台着色器语言. GPU渲染管线概述 1.顶点着色器 顶点着色器是流水线

C语言中关于计算字符串中空格数的问题

以下是C语言代码:(请参看注释) #include <iostream>#include <stdlib.h>#include <stdio.h>using namespace std;int main(int argc, char *argv[]){ int count = 0 ; char* str ; printf("Input a string:"); gets(str); //此处不能使用scanf(%s,str)或者cin>>