【UnityShader】单张纹理
纹理最初的目的就是使用一张照片来控制模型的外观。
使用纹理映射可以将图片附着再模型表面。一般用一个二位坐标(u,v)来表示纹理映射坐标,也称UV坐标。
我们通常使用一张纹理来代替物体漫反射颜色。
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld' Shader "Custom/Chapter7-SingleTexture" { Properties{ _Color("Color Tint",Color) = (1,1,1,1) _MainTex("Main Tex",2D) = "white"{} _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 #include "Lighting.cginc" fixed4 _Color; sampler2D _MainTex; fixed4 _Specular; float _Gloss; float4 _MainTex_ST;//纹理类型属性 struct a2v{ float4 vertex : POSITION; float3 normal : NORMAL; float4 texcoord:TEXCOORD0; //将第一组纹理坐标存储在该变量中 }; struct v2f{ float4 pos:SV_POSITION; float3 worldNormal:TEXCOORD0; float3 worldPos:TEXCOORD1; float2 uv:TEXCOORD2; //存储纹理坐标的变量 }; v2f vert(a2v v){ v2f o; o.pos = UnityObjectToClipPos(v.vertex); o.worldNormal = UnityObjectToWorldNormal(v.normal); o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; o.uv = v.texcoord.xy*_MainTex_ST.xy+_MainTex_ST.zw; return o; } fixed4 frag(v2f i):SV_Target{ fixed3 worldNormal = normalize(i.worldNormal); fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos)); fixed3 albedo = tex2D(_MainTex,i.uv).rgb*_Color.rgb; //材质的反射系数的采样 fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz*albedo; fixed3 diffuse = _LightColor0.rgb*albedo*max(0,dot(worldNormal,worldLightDir)); fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos)); fixed3 halfDir = normalize(worldLightDir+viewDir); fixed3 specular = _LightColor0.rgb*_Specular.rgb*pow(max(0,dot(worldNormal,halfDir)),_Gloss); return fixed4(ambient+diffuse+specular,1.0); } ENDCG } } FallBack "Diffuse" }
在属性里声明了_MainTex的纹理属性,_Color来做 整体物体的色调控制
float4 _MainTex_ST;//纹理类型属性
Unity中,使用纹理名_ST的方式来声明某个纹理的属性,对顶点纹理坐标进行偏移和缩放。Unity也提供了一个内置宏TRANSFORM_TEX来帮我们计算。
o.uv = v.texcoord.xy*_MainTex_ST.xy+_MainTex_ST.zw;
计算过法线和光照方向后,进行纹理取样。实质是利用tex2D函数取样。第一个参数是要被取样的纹理,第二个参数是纹理坐标。
最后将取样结果和颜色属性_Color的乘积来作为材质的反射率。
fixed3 albedo = tex2D(_MainTex,i.uv).rgb*_Color.rgb; //材质的反射系数的采样
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz*albedo;
fixed3 diffuse = _LightColor0.rgb*albedo*max(0,dot(worldNormal,worldLightDir));
最后叠加漫反射,环境光和高光返回即可。