openGL中关于顶点的法线、切线、副切线

openGL系列文章目录

前言

我们在openGL中绘制球体,或者圆环体的时候,经常可以到法线、切线、副切线这几个词,一脸疑惑,特别是副切线,这时什么鬼?

一、法线(normal)

物体模型由成百上千个平坦的三角形围成.三角形上附加纹理的方式来增加额外细节. 提升真实感.
但是近看时,就有问题了.变成平面.缺乏细节.原因:
物体表面并非平坦的. 而是表示出无数(凹凸不平的)细节.如果以光的视角来看这个问题:是什么使表面被视为完全平坦的表面来照亮?
这时就需要法线

法线定义

三维平面的法线是垂直于该平面的三维向量。曲面在某点P处的法线为垂直于该点切平面的向量。
在这里插入图片描述

二、切线(tangent)

切线定义

几何上,切线指的是一条刚好触碰到曲线上某一点的直线。更准确地说,当切线经过曲线上的某点(即切点)时,切线的方向与曲线上该点的方向是相同的。平面几何中,将和圆只有一个公共交点的直线叫做圆的切线。
在这里插入图片描述

副切线(bitangent)

副切线(Bitangent)有时也被叫作副法线(Binormal),不管怎样,说的都是同一个东西。
副切线是同时垂直于由法线与切线的向量,所以可以由法线与切线的叉积计算得出。
但是这样的向量有两条,那到底哪一条才是真正的副切线呢?
经过计算后的副切线向量(蓝色的线)。
在这里插入图片描述

在着色器中的描述和计算

vec3 tangent;
vec3 binormal;

vec3 c1 = cross(a_normal, vec3(0.0, 0.0, 1.0));
vec3 c2 = cross(a_normal, vec3(0.0, 1.0, 0.0));

if (length(c1)>length(c2))
{
    tangent = c1;
}
else
{
    tangent = c2;
}

tangent = normalize(tangent);

binormal = cross(v_nglNormal, tangent);
binormal = normalize(binormal);

法线,切线,副切线函数实现

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;

    }
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值