0.简介
如果想让上一次的墙面更加真实一些,就需要法线纹理来修饰一下了。
1.法线纹理
我这里简单介绍一下法线纹理,模型表变的法向量一般都比较单一,例如上一篇博客里的墙面,法向量都是朝向一面的,这就带来一个问题,墙面就很假,很光滑,跟瓷砖一样的感觉,但是实际的墙面并不是,而其根本原因就是表面的法向量导致光的反射方向一样,所以才像瓷砖一样反光,如果表面的法向量是接近于真实的,效果就会好很多,那么可以换一个更加真实的模型,模型中细节多了,自然就好了,但是模型中细节越多顶点就越多,计算量就越大,如果在模型表面加上类似纹理一样的法向量,这样,就可以避免用复杂的模型了,当然想法很好,那么就来实践一下。
具体讲解请见如下文章
https://www.jianshu.com/p/eea4d8582499
2.实现
我建议是要看看上面给出的文章链接,讲的很好,重复的东西我就不在花时间叙述了。
mat3 Triangle::getTBN(vec5 _A, vec5 _B, vec5 _C)
{
//计算出三角形面的姿态矩阵
vec2 u = _B.textureUV - _A.textureUV;
vec2 v = _C.textureUV - _B.textureUV;
vec3 AB = wB.position - wA.position;
vec3 BC = wC.position - wB.position;
mat2 uv = mat2(u, v);
vec3 Eu1 = v.y * AB;
vec3 Eu2 = -v.x * BC;
float delta = 1.0 / (u.x * v.y - u.y * v.x);
vec3 E1 = normalize(vec3(Eu1.x + Eu2.x, Eu1.y + Eu2.y, Eu1.z + Eu2.z))* delta;
Eu1 = -u.y * AB;
Eu2 = u.x * BC;
vec3 E2 = normalize(vec3(Eu1.x + Eu2.x, Eu1.y + Eu2.y, Eu1.z + Eu2.z))* delta;
vec3 N = cross(E1, E2);
E2 = cross(E1,N);
return (mat3(normalize(E1),normalize(E2),normalize(N)));//返回左乘变换矩阵
}
三角形类中添加的TBN矩阵计算功能。
Ray Triangle::intersect(Ray ray)
{
Ray result(ray.direction, ray.position, ray.intensity, ray.color, nullptr);
if ((result = Plane::intersect(ray)).polygon == nullptr)
return Ray(ray.direction, ray.position, ray.intensity, vec3(0, 0, 0), nullptr);
//这里说明点在三角面是上
if (onTriangle0(wA.position, wB.position, wC.position, result.end.position))
{
//计算点所在的纹理坐标
vec5 p_end;
result.end.textureUV = getUVCoord(A, B, C, result.end);
//如果纹理是带有法向量纹理
if(m->hasNormalTexture)
result.normal = getTBN(A,B,C) * m->getNormal(result.end.textureUV);
return result;
}
return Ray(ray.direction, ray.position, ray.intensity, vec3(0, 0, 0), nullptr);
}
在光线碰撞计算的时候,加入了法向量获取,从法线纹理中获取。
3.效果
放大看看
看起来效果还可以吧,虽然真实的墙面不会这样油汪汪的,但是法线纹理的感觉是出来了。后面的墙面块数目比较多,所以计算起来时间比较长,后面需要想办法加速一下了。