参考:

《Unity Shader入门精要笔记(十二):纹理属性》

一.基本纹理采样
1.UV坐标:将纹理通过“纹理映射坐标”(纹理展开技术)存储在每个顶点上,每个顶点对应着该纹理在2D坐标上的位置,这个坐标即为UV坐标,其中u为横向坐标,v为纵向坐标;
2.纹理可以有多种256x256或者1024x1024,但UV坐标范围通常被归一化为【0,1】
3.纹理坐标的原点位置:
DirectX:左上角
OpenGL&Unity:左下角

二.纹理的属性
Texture Type:
Texture:普通贴图
  Normal map:法线贴图
  Editor GUI and Legacy GUI:UI贴图
  Sprite(2D and UI):精灵
  Cursor:鼠标指针
  Reflection:反射贴图
  Cookie:遮罩贴图
  Lightmap:烘焙贴图
  Advanced:高级(可自定义一些贴图属性)
Texture 修改Tilling参数

Wrap Mode:

它决定了当纹理坐标超过[0, 1]范围后将如何平铺。有两项,repeat和clamp,repeat顾名思义,表示重复,当纹理坐标超过1时,整数部分被舍弃,直接使用小数部分进行采样,纹理会不断重复;clamp,纹理坐标大于1时会截取到1,小于0时会截取到0。如下图:

纹理映射python 纹理映射偏移_贴图


纹理映射python 纹理映射偏移_unity_02


两幅图都是平铺属性为(3,3)的效果,上图repeat就不断重复,下图clamp则截取到边界。

注意,如果要这样的效果,不要忘了Shader中使用纹理的属性(例如上一篇的_MainText_ST)对纹理坐标进行变换,也就是需要类似下面的代码:

o.uv = TRANSFORM_TEX(v.uv, _MainTex);

否则面板没有这个重复模式的选项。

还可以调整纹理坐标的偏移量,使纹理不以(0,0)为原点。下图展示了偏移属性为(0.2, 0.6)时分别使用两种Wrap Mode的结果。

纹理映射python 纹理映射偏移_shader_03


纹理映射python 纹理映射偏移_shader_04


Filter Mode:滤波模式

它决定了当纹理由于变换产生拉伸时会采用哪种滤波模式。有3种模式:Point,Bilinear,Trilinear。

a、Point模式:最近点采样,当纹理坐标没有刚好对应Texture上的一个采样点时,它会选择最近的一个采样点作为该坐标的采样值,当纹理没有拉伸变形时,这样还不错,因为速度是最快的,但如果拉伸变形了,会出现马赛克现象。

b、Bilinear模式:双线性过滤,以像素对应的纹理坐标为中心,采样它周围4个texel(纹素)的像素,取平均值作为该坐标采样值。这是Unity默认的模式,过渡效果相对平滑,当然速度会比最近点采样有一定下降。

c、Trilinear模式:三线性过滤,会对像素大小和纹素大小最接近的两层Mipmap level分别进行双线性过滤,再对结果进行线性插值。由于使用了两次双线性过滤,也就是计算2x4=8个像素的值,速度会更加下降,当然滤波效果更好。下图是一张64x64的纹理贴在512x512的平面时用三种过滤的效果图:

纹理映射python 纹理映射偏移_d3_05


多级渐远纹理技术

纹理映射python 纹理映射偏移_unity_06


纹理映射python 纹理映射偏移_贴图_07


代码:

Shader "Custom/Texture"
{
	Properties
	{
		_MainTex("MainTex",2D)="white"{}
		_Color("MainTex Color",COLOR)=(1,1,1,1)
		_Specular("Specular Color",Color)=(1,1,1,1)
		_Gloss("Gloss",Range(1,50))=20
	}

	SubShader
	{
		Pass
		{
			Tags{"LightMode"="ForwardBase"}

			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag

			#include"Lighting.cginc"
			#include"UnityCG.cginc"

			sampler2D _MainTex;
			float4 _MainTex_ST; //纹理的偏移和缩放(Tiling和offset)

			fixed4 _Color;
			fixed4 _Specular;
			half _Gloss;

			struct a2v
			{
				float4 vertex:POSITION;  //取得顶点位置
				float3 normal:NORMAL;
				float2 texcoord:TEXCOORD0; //纹理的顶点坐标(float2)
				
			};
			struct v2f
			{
				float4 svPos:SV_POSITION;  //剪裁空间下的顶点坐标
				float3 worldNormal:TEXCOORD0;
				float4 worldVertex:TEXCOORD1; //世界空间下的顶点坐标
				float2 uv:TEXCOORD2;
			};

			v2f vert(a2v v)
			{
				v2f f;
				f.svPos=UnityObjectToClipPos(v.vertex);
				f.worldNormal=UnityObjectToWorldNormal(v.normal); //法线从模型空间=》世界空间
				f.worldVertex=mul(unity_ObjectToWorld,v.vertex); //顶点坐标从模型空间=》世界空间

				//对纹理进行偏移和缩放
				//第一种:拆开计算
				f.uv=v.texcoord * _MainTex_ST.xy - _MainTex_ST .zw;
				//第二种(用自带的系统函数)
				//f.uv=TRANSFORM_TEX(v.texcoord,_MainTex);
				return f;

			}

			fixed4 frag(v2f f):SV_TARGET
			{
				fixed3 normalDir=normalize(f.worldNormal); //法线向量
				fixed3 lightDir=normalize(WorldSpaceLightDir(f.worldVertex)); //光线向量
				fixed3 viewDir=normalize(UnityWorldSpaceViewDir(f.worldVertex)); //视野方向
				fixed3 halfDir=normalize(lightDir + viewDir); //平分向量
				fixed3 texColor=tex2D(_MainTex,f.uv)*_Color; //纹理颜色

				fixed3 diffuse=_LightColor0.rgb * texColor.rgb * max(0,dot(lightDir ,normalDir)); //漫反射
				fixed3 specular=_LightColor0.rgb * _Specular.rgb * pow ( max(0,dot(normalDir,halfDir) ),_Gloss); //高光反射			

				//*texColor环境光和纹理融合效果好点
				fixed3 tempcolor=diffuse+specular+UNITY_LIGHTMODEL_AMBIENT.rgb*texColor; //UNITY_LIGHTMODEL_AMBIENT.rgb环境光颜色
				return fixed4(tempcolor,1);

			}

			ENDCG
		}
	}

	FallBack"SPECULAR"
}

效果:

纹理映射python 纹理映射偏移_纹理映射python_08