UnityShader学习12 关于法线贴图
法线贴图可以使光滑的物体表面看起来凹凸有致,比如砖块、地面等等这些,如果全部都由建模来体现细节的话会使顶点急剧增多,性能消耗急剧增加,所以就有了法线贴图。
砖块、地面等等的模型细节表面能和光照实时交互,得益于法线贴图。
法线贴图记录的是法线的信息,然后根据光照向量来进行点积,从而得到光照强度,进而实现物体凹凸有致的感觉。
基本思路:
把贴图转换成灰度图,然后根据贴图每个像素的颜色分量的一个值(由于是灰度图,所以rgb三个分量都是相等的,所以这里才说是一个值)的上、下的差值,求出差分向量v;
同理,利用左、右,求出差分向量u;然后这两组向量进行叉乘,求出法向量。求出的法向量记录进图片的rgb分量中,由于rgb分量的范围是0到1,所以要进行一个映射。
最后,由于我们的求出的法向量是基于nv坐标系的,如果在多个平面使用同一个法线贴图,这就会造成光照效果的错误(比如说cube),所以,我们要对光进行一个变换来变换到切线空间(TBN)。切线空间的相关文章:https://blog.csdn.net/Game_jqd/article/details/74858146
以下是用c#代码实现法线贴图:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class CreateNormalMap : MonoBehaviour { public Texture2D tex0;//原始纹理 public Texture2D tex1;//处理后的法线纹理 // Use this for initialization void Start () { for (int h = 1; h < tex0.height - 1; h++) { for (int w = 1; w < tex0.width - 1; w++) { float uleft = tex0.GetPixel(w - 1, h).r;//左边 float uright = tex0.GetPixel(w, h - 1).r;//右边 float u = uright - uleft; float vtop = tex0.GetPixel(w, h - 1).r; float vbottom = tex0.GetPixel(w, h + 1).r; float v = vbottom - vtop; Vector3 vector_u = new Vector3(1, 0, u); Vector3 vector_v = new Vector3(0, 1, v); Vector3 N = Vector3.Cross(vector_u, vector_v); float r = N.x * 0.5f + 0.5f; float g = N.y * 0.5f + 0.5f; float b = N.z * 0.5f + 0.5f; tex1.SetPixel(w, h, new Color(r, g, b)); } tex1.Apply(false); } } }
浙公网安备 33010602011771号