参考教程
学习记录
这篇文章中,我们将介绍使用纹理的法线贴图来实现感官上的凹凸效果。在之前我们的文章中我们使用一张纹理图片实现墙壁的纹理效果,但是在光照下因为纹理在一个平面的原因,法线总是向着一个方向。所以总是没有真实感,而这篇文章中我们用一张和纹理对应的法线图片进行贴图来增强真实感。
我们的源纹理如下:
法线纹理如下:
法线贴图其实就是将纹理上位置对应的法线存入纹理中,我们可以直接在 pixel 着色器中计算出像素点对应的法线从而避免了使用插值法得到的所有法线共向的问题。
在实现之前,或许需要了解以下内容:切线空间,切线副切线的计算(这些内容可能会找个时间去专门介绍也可能不会=。=)
首先我们给顶点结构体中添加了三个属性:
1 | XMFLOAT3 nor; |
分别为法线,切线,副切线。这三个属性可以通过计算得到也可以直接给定(一般的模型会有这些属性),在这里我们试着使用顶点数据进行计算。
1 | inline HRESULT CalculateTangentAndBiTangent(Vertex *&vertices, UINT *&indices, const UINT nNumIndices) { |
我们在 InitCubeVertexAndIndexBuffer
里写入定点数据和索引数据后调用这个方法。
同时,我们的顶点格式变了,所以 InputLayout 也要改变:
1 | D3D11_INPUT_ELEMENT_DESC layout[5]; |
我们现在有五个属性,在着色器里也需要变化:
1 | struct vertexInputType { |
在顶点着色器里我们对法线这些数据进行处理:
1 | pixelInputType main( vertexInputType input ){ |
片段着色器里我们对法线贴图进行计算 bumpNormal = (bumpMap.x * input.tangent) + (bumpMap.y * input.binormal) + (bumpMap.z * input.normal);
,这将是我们计算凹凸法线的公式。然后我们会用这个法线去和光照做计算。
1 | Texture2D tex[2]; |
lightDir
是我们的光照方向,bumpNormal
则是我们计算出来的凹凸法线,使用它来进行光照计算后,效果如下:
可以看到,比起直接使用插值法得到的数据法线计算光照,使用法线贴图后我们的纹理多了一些细节,更加具有真实感。