《UnityShader入门精要》纹理贴图——基础纹理 笔记及代码注释

纹理最初的目的是使用一张图片来控制模型的外观,使用纹理映射技术,可以把一张图黏在模型表面,逐纹素的控制模型颜色

美术人员建模时候,通常会在建模软件中利用纹理展开技术把纹理映射坐标(texture-mapping coordinates)存储在每个顶点上。这些坐标使用一个二维变量(u,v)来表示

不同的图形语言的纹理坐标不同

《UnityShader入门精要》纹理贴图——基础纹理 笔记及代码注释_第1张图片

 

 本章 我们编写的是单张纹理贴图,使用的是上章的高光反射

效果图:

《UnityShader入门精要》纹理贴图——基础纹理 笔记及代码注释_第2张图片

 

Shader "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;
            //除了纹理图片外 我们还得给他声明一个float4类型变量
            //变量名字不是随便起的 约定俗成的为 纹理名_ST ST是缩放(scale)和平移(translation)
            //该变量可以让我们得到该纹理的缩放和平移值
            //_MainTex_ST.xy 存储的是缩放值 _MainTex_ST.zw存储的是偏移值 可以在材质面板调节
            sampler2D _MainTex;
            float4 _MainTex_ST;

            fixed4 _Specular;
            float _Gloss;

            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;
            };
            //a2v结构体中使用TEXCOORD0 语义声明了一个新的变量texcoord
            //Unity会将第一组纹理坐标存储到该变量中
            //v2f结构体中添加用于存储纹理坐标的变量uv 便于片元着色器采样
            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 = TRANSFORM_TEX(v.texcoord,_MainTex);
                o.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
                  //或者可以直接使用内部公示计算
                    //  o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
                return o;
            }
            fixed4 frag(v2f i) : SV_Target{
                fixed3 worldNormal = normalize(i.worldNormal);
                fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
                //用纹理采样漫反射颜色 tex2D : CG函数 对纹理采样
                //第一个参数是被采样纹理 第二个参数是float2纹理坐标 返回纹素值
                //采样结果和颜色属性_Color的乘积作为材质的反射率 albedo
                fixed3 albedo = tex2D(_MainTex,i.uv).rgb * _Color.rgb;
                //获取环境光乘上采样结果 得到采样后的环境光
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
                //计算漫反射颜色 和 采样结果相乘 saturate 和 max 同理
                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"
}
纹理的属性
纹理属性的第一个属性是纹理类型。
其中比较重要的是

Wrap Mode:他决定了当纹理坐标超过[0,1]后贴图将如何被平铺

《UnityShader入门精要》纹理贴图——基础纹理 笔记及代码注释_第3张图片《UnityShader入门精要》纹理贴图——基础纹理 笔记及代码注释_第4张图片

他有几种模式 其中
Repeat模式下,纹理坐标超过一,则它的整数部分会被舍弃,直接用小数部分采样。
Clamp模式下,如何纹理坐标大于1,则会被截取到1,小于0则截取到0。
《UnityShader入门精要》纹理贴图——基础纹理 笔记及代码注释_第5张图片
上面分别是使用repeat和clamp的结果
还有一个是比较重要的是 Filter Mode
面板属性下方有个Fliter Mode,他们分别表示3种滤波
《UnityShader入门精要》纹理贴图——基础纹理 笔记及代码注释_第6张图片
下图给出了从一个倾斜角度观察一个网格结构的地板时,使用不同的Filter Mode得到的效果
Point,Biliner,Trilinear
《UnityShader入门精要》纹理贴图——基础纹理 笔记及代码注释_第7张图片

你可能感兴趣的:(UnityShader,unity,贴图,unity,游戏引擎,材质)