纹理采样

本文借鉴《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的幂的大小。

你可能感兴趣的:(纹理采样)