
Properties
{
_MainTex ("Main Tex", 2D) = "white" {}
}// 宏效果等同于
// o.uv = v.texcoord.xy * _MianTex.xy + _MianTex.zw;
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;
fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(worldNormal, worldLightDir));使用高度纹理来计算法线,计算后得到不同的颜色,使得纹理看起来有凹凸质感。
高度图中存储的是强度值(identity),颜色越浅说明该位置表面越往外凸起
法线纹理存储的是表面法线方向。
切线空间存储方式
副切线:由法线和切线叉积得到
模型空间存储法线
优点
切线空间存储法线:
优点
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _BumpMap;
float _MainTexScale;struct a2v
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 tangent : TANGENT;
float4 texcoord : TEXCOORD0;
};// 叉乘得到副切线
float binormal = cross(normalize(v.normal), normalize(v.tangent.xyz)) * v.tangent.w;
// 切线空间基向量构成正交矩阵,因此法线变换矩阵就是切线空间的变换矩阵
float3x3 rotation = float3x3(v.tangent.xyz, binormal, v.normal);
// 也可以使用TANGENT_SPACE_ROTATION宏来获取到切线空间的旋转矩阵
TANGET_SPACE_ROTATION // 等同于上述两步
// 将需要计算的变量变换到切线空间
o.LightDir = mul(rotation, ObjSpaceLightDir(v.vertex)).xyz;
o.viewDir = mul(rotation, ObjSpaceViewDir(v.vertex)).xyz;// 解映射
tangentNormal.xy = (packedNormal.xy * 2 - 1) * _BumpScale;
tangentNormal.z = sqrt(1.0 - saturate(dot(tangentNormal.xy, tangentNormal.xy)));
// tangentNormal = UnpackNormal(packedNormal); //等同于上两步
// 计算切线空间的顶点法线
tangentNormal.xy *= _MainTexScale;
tangentNormal.z = sqrt(1.0 - saturate(dot(tangentNormal.xy, tangentNormal.xy)));struct v2f
{
float4 pos : SV_POSITION;
float4 uv : TEXCOORD0;
float4 TtoW0 : TEXCOORD1;
float4 TtoW1 : TEXCOORD2;
float4 TtoW2 : TEXCOORD3;
};float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w;
//存储切线空间到世界空间的变换矩阵,以及顶点在世界坐标的表示。
o.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);float3 worldPos = float3(i.TtoW0.w, i.TtoW1.w, i.TtoW2.w);
fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));
fixed3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));
fixed3 bump = UnpackNormal(tex2D(_BumpMap, i.uv.zw));
bump.xy *= _BumpScale;
bump.z = sqrt(1.0 - saturate(dot(bump.xy, bump.xy)));
bump = normalize(half3(dot(i.TtoW0.xyz, bump), dot(i.TtoW1.xyz, bump), dot(i.TtoW2.xyz, bump)));有时需要更要灵活地控制光照结果,因此可以使用渐变纹理来控制漫反射光照的结果
Valve公司首先使用了一种基于冷到暖色调的着色技术(cool-towarm tones)
这种方式可以自由地控制物体地漫反射光照,不同地渐变纹理有不同地特性
遮罩纹理能保护某些区域,使他们免于修改
使用纹理的一般流程使:
遮罩纹理可以让美术人员更加精准地控制模型表面地各种性质
立方体纹理(Cubemap)是环境映射(Environment Mapping)的一种实现方法, 环境映射可以模拟周围环境,而是用了环境映射的物体可以看起来像渡了层金属一样反射出轴为的环境
深度纹理实际上就是一张渲染纹理,只不过里面存储的像素值不是颜色值,而是一个高精度的深度值。由于被存储在一张纹理中,深度纹理里的深度值范围是[0, 1],而且通常是非线性分布的 总体来说,这些深度值来自于顶点变换后得到的归一化的设备坐标(Normalized Device Coordinates)
camera.depthTextureMode = DepthTextureMode.Depth;