小结
今天继续了基础纹理方面的学习,主要收获是关于凹凸映射中法线纹理的部分。首先是稍微搞懂了点,切线空间在法线纹理中起的作用(TNB矩阵)。由于昨天没有认真看切线空间这部分,而且书上给的篇幅也不是很多。导致在读后面的代码时,感觉非常困难。像这种细节还是不能略的。看快了,容易扯着蛋hhhh。 不过我感觉关于法线纹理还得停几天,代码实现起来的时候细节还是挺多的,还是没有彻底吃透。
此外,大致阅读了点HLSL 的书,说实话现在我对于那些shader语言还是有点晕。到底是个什么关系? 还是不能只停留在Unity shader 上。有必要学点真正的shader语言。
法线纹理在切线空间下实现的代码
Shader “Unlit/bump mapping”
{
Properties
{ _Color("Color Tint ",Color)=(1,1,1,1)
_MainTex(“MainTex”,2D) = “white”{} //模型纹理坐标
_BumpMap(“Normal Map”,2D) = “bump”{} // 法线纹理坐标。bump 内置法线纹理,默认为模型自带法线信息
_BumpScale(“BumpScale”,Float) = 1.0 // 控制凹凸程度,为0时,意味该法线纹理不会对光照产生任何影响
_Specular(“Specular”,Color) = (1,1,1,1)
_Gloss(“Gloss”,Range(8.0,256)) = 20
}
SubShader
{
Pass
{ Tags { "LightMode" = "ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#include "Lighting.cginc"
#include "UnityCG.cginc"
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST; //纹理属性(平铺,偏移系数)
sampler2D _BumpMap;
float4 _BumpMap_ST; //同上
float _BumpScale; // 法系纹理对光照的反应程度
fixed4 _Specular;
float _Gloss;
struct a2v
{
float4 vertex:POSITION;
float3 normal:NORMAL;
float4 tangent:TANGENT; //将顶点的切线方向填充至tangent中(4个变量,w决定z方向)
float4 texcoord:TEXCOORD0; //纹理坐标
};
struct v2f
{
float4 pos:SV_POSITION;
float4 uv:TEXCOORD0; //uv存放了两种纹理的坐标(模型,法线)
float3 LightDir:TEXCOORD1;
float3 ViewDir:TEXCOORD2;
};
//顶点着色器工作,将光线,视角,转换到切线空间,描述纹理变换之后的方位
v2f vert (a2v v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv.xy = v.texcoord.xy*_MainTex_ST.xy + _MainTex_ST.zw; //纹理属性ST变换
o.uv.zw = v.texcoord.xy*_BumpMap_ST.xy + _BumpMap_ST.zw; //法线纹理变换
TANGENT_SPACE_ROTATION; //内置宏,获得TNB矩阵
o.LightDir = mul(rotation,ObjSpaceLightDir(v.vertex)).xyz; //将入射光从模型空间变换到切线空间
o.ViewDir = mul(rotation,ObjSpaceViewDir(v.vertex)).xyz; //同上
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed3 tangentLightDir = normalize(i.LightDir); //归一化
fixed3 tangentViewDir = normalize(i.ViewDir);
fixed4 packedNormal = tex2D(_BumpMap, i.uv.zw); //对法线纹理采样
fixed3 tangentNormal = UnpackNormal(packedNormal); //将按像素方式存储的法线数据(),映射回法线数据
tangentNormal.xy *= _BumpScale; // 切线及副法线乘以对光线的影响系数(控制凹凸效果)
tangentNormal.z = sqrt(1-saturate(dot(tangentNormal.xy,tangentNormal.xy))); //计算切线空间中的法线
fixed3 albedo = tex2D(_MainTex,i.uv.xy).rgb*_Color.rgb; // 获得纹素数据
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT * albedo; //环境光
fixed3 diffuse = _LightColor0.rgb*albedo*max(0, dot(tangentNormal, tangentLightDir));//反射光(使用的是切线空间坐标系)
fixed3 h = normalize(tangentNormal + tangentLightDir);
fixed3 specular = _LightColor0.rgb*_Specular.rgb*pow(max(0,dot(tangentNormal,h)),_Gloss);
return fixed4(specular + ambient + diffuse, 1);
}
ENDCG
}
} Fallback "Specular"
}
敲的时候,还是做不到脱书,得继续加油啊!