法线纹理原理及实现

法线纹理简介

法线纹理技术又叫凹凸纹理,英文Bump Mapping,法线纹理的思想是取代对三角面上的顶点法线进行插值,而是简单的通过从纹理中取样来获取法线方向。这种技术能够更好的模拟真实世界的场景,因为大多数的表面(特别是我们在游戏中感兴趣的那些地方)并没光滑到使光线能够按照我们用之前的方法插值得到的法线方向进行反射,反而表面上的凹凸之处会使得光线沿着其照射点处的大致反射方向进行反射。对于每一个纹理,他们的法线都能被计算出来并且存放在一张特殊纹理—— 法线纹理之中。当在片元着色器中进行光照计算的时候,我们可以借助于纹理坐标从法线纹理中采样来获得当前像素的法线信息,并像一般法线一样使用它。

TB坐标系推导

顶点法线是在模型的局部坐标系之下定义的,我们需要通过世界矩阵将其变换到世界坐标系之下,原型图如下图所示
在这里插入图片描述
由图可得

在这里插入图片描述

在这里插入图片描述
变换得
在这里插入图片描述
进而得

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

定点Tagent求解代码

struct Vertex
{
    Vector3f m_pos;
    Vector2f m_tex;
    Vector3f m_normal;
    Vector3f m_tangent;
    Vertex() {}
    Vertex( const Vector3f& pos, 
            const Vector2f& tex, 
            const Vector3f& normal, 
            const Vector3f& Tangent )
    {
        m_pos = pos;
        m_tex = tex;
        m_normal = normal;
        m_tangent = Tangent;
    }
}; 

for (unsigned int i = 0 ; i <  Indices.size() ; i += 3) {
    Vertex& v0 = Vertices[Indices[i]];
    Vertex& v1 = Vertices[Indices[i+1]];
    Vertex& v2 = Vertices[Indices[i+2]];
    Vector3f Edge1 = v1.m_pos - v0.m_pos;
    Vector3f Edge2 = v2.m_pos - v0.m_pos;
    float DeltaU1 = v1.m_tex.x - v0.m_tex.x;
    float DeltaV1 = v1.m_tex.y - v0.m_tex.y;
    float DeltaU2 = v2.m_tex.x - v0.m_tex.x;
    float DeltaV2 = v2.m_tex.y - v0.m_tex.y;
    float f = 1.0f / (DeltaU1 * DeltaV2 - DeltaU2 * DeltaV1);
    Vector3f Tangent, Bitangent;
    Tangent.x = f * (DeltaV2 * Edge1.x - DeltaV1 * Edge2.x);
    Tangent.y = f * (DeltaV2 * Edge1.y - DeltaV1 * Edge2.y);
    Tangent.z = f * (DeltaV2 * Edge1.z - DeltaV1 * Edge2.z);
    Bitangent.x = f * (-DeltaU2 * Edge1.x - DeltaU1 * Edge2.x);
    Bitangent.y = f * (-DeltaU2 * Edge1.y - DeltaU1 * Edge2.y);
    Bitangent.z = f * (-DeltaU2 * Edge1.z - DeltaU1 * Edge2.z);
    v0.m_tangent += Tangent;
    v1.m_tangent += Tangent;
    v2.m_tangent += Tangent;
}
for (unsigned int i = 0 ; i < Vertices.size() ; i++) {
    Vertices[i].m_tangent.Normalize();
} 

片元着色器中法线求解

vec3 CalcBumpedNormal()
{
    vec3 Normal = normalize(Normal0);
    vec3 Tangent = normalize(Tangent0);
    Tangent = normalize(Tangent - dot(Tangent, Normal) * Normal);
    vec3 Bitangent = cross(Tangent, Normal);
    vec3 BumpMapNormal = texture(gNormalMap, TexCoord0).xyz;
    BumpMapNormal = 2.0 * BumpMapNormal - vec3(1.0, 1.0, 1.0);
    vec3 NewNormal;
    mat3 TBN = mat3(Tangent, Bitangent, Normal);
    NewNormal = TBN * BumpMapNormal;
    NewNormal = normalize(NewNormal);
    return NewNormal;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值