本文借鉴《Unity Shader入门精要》,算是对自己学习的总结,也希望分享下所学知识~~
**纹理:**使用一张图片来控制模型的外观。
使用 纹理映射(textrue mapping)
技术,把一张图贴在模型表面,逐 纹素(texel)
控制模型的颜色。
美术人员建模时,利用 纹理展开技术
把 纹理映射坐标(texture-mapping coordinates)
存储在每个顶点上。
纹理映射坐标使用一个二维变量(u,v)来表示,其中u是横向坐标,v是纵向坐标。纹理映射坐标也称为UV坐标。
通常会使用单张纹理代替漫反射颜色,也就是纹理采样。
使用Blinn-Phong光照模型计算:
Shader "SingleTexture"
{
Properties
{
_Color ("Color Tint", Color) = (1,1,1,1)//纹理颜色
_MainTex ("Texture", 2D) = "white" {}//纹理
_Specular ("Specular", Color) = (1,1,1,1)
_Gloss("Gloss", Range(8.0, 256)) = 20
}
SubShader
{
Tags { "LightMode" = "ForwardBase" }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
#include "UnityCG.cginc"
struct v2f
{
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
float2 uv : TEXCOORD2;
};
fixed4 _Color;
sampler2D _MainTex;
//使用 纹理名_ST 声明某个纹理的属性 ST是缩放scale和平移translation的缩写
//_MainTex_ST.xy 存储的是缩放值,_MainTex_ST.zw存储的是偏移值
// 对应inspector里面的 tiling(平铺) offset(平移)
float4 _MainTex_ST;
fixed4 _Specular;
float _Gloss;
v2f vert (appdata_base v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldNormal = UnityObjectToWorldNormal( v.normal );
o.worldPos = mul( unity_ObjectToWorld, v.vertex).xyz;
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);//内置函数:对顶点纹理坐标进行计算
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = UnityWorldSpaceLightDir(i.worldPos);
//使用Cg的tex2D函数对纹理进行采样,通过它计算返回得到的纹素值
fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;//new值函数:计算反射率 albedo
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 "SPECULAR"
}
纹理属性:
a)Wrap Mode:决定了纹理坐标超过[0,1]返回后,如何被平铺
**1.repeat:**如果纹理坐标超过了1,那么它的整数部分将会被舍弃,而直接使用小数部分进行采样,这样的结果是纹理将会不断重复
**2.clamp:**超过范围的部分将会截取到边界值,形成一个条型结构
b)在不同平台发布游戏时,需要考虑目标平台的纹理尺寸和质量问题。
如果导入的纹理大小超过了 Max Texture Size
中的设置值,那么Unity会把该纹理缩放为这个最大分辨率。
c)导入纹理可以是非正方形的,但长宽的大小应该是2的幂,例如2、4、6、8、16、32、64等。
如果使用了非2的幂的大小(Non Power of Two,NPOT)的纹理,这些纹理会占用更多的内存空间,而且GPU读取该纹理的速度也会有所下降。
有的平台不支持NPOP纹理,unity会把它缩放成最近的2的幂的大小。