Unity Shader学习笔记:基础纹理

来源:互联网 发布:网络自制综艺节目 编辑:程序博客网 时间:2024/04/30 06:30

差不多第二次看《Unity Shader入门精要》这本书了,第二次看的感觉很良好,阅读速度也不是一般的快。

在美术人员建模的时候,通常会在建模软件中利用纹理展开技术把纹理映射坐标存储在每一个顶点上。纹理映射坐标定义了该顶点在纹理中对应的2D坐标。通常,这些坐标使用一个二维变量(u,v)来表示,其实u是横向坐标,而v是纵向坐标。因此,纹理映射坐标也被称为UV坐标。
尽管纹理的大小可以是多种多样的,例如可以是256x256或者1024x1024,但顶点UV坐标的范围通常都被归一化到[0,1]范围内。其中unity使用的纹理坐标,原点位于纹理左下角。

使用纹理代替漫反射颜色

// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'Shader "Own/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;            //在Unity中,我们需要使用纹理名_ST的方式来声明某个纹理的属性。其中,ST是缩放和平移的缩写。            //_MainTex_ST可以让我们得到该纹理的缩放和平移(偏移)值,_MainTex_ST.xy存储的是缩放值,而            //_MainTex_ST.zw存储的是偏移值            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;            };            v2f vert(a2v v){                v2f o;                o.pos = mul(UNITY_MATRIX_MVP,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;                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 "Specular"}

在图片的Import Setting界面中,有一个属性Wrap Mode它决定了当纹理坐标超过[0,1]范围后将会如何被平铺。Wrap Mode有两种模式:
1.Repeat:在这种模式下,如果纹理超过了1,那么它的整数部分将会被舍弃,而直接使用小数部分采样,这样的结果是纹理将会不断重复;
2.Clamp:在这种模式下,如果纹理坐标大于1,那么将会截取到1,如果小于0,那么将会截取到0。
说明:
假设有一张图片:Tiling:x = 2,y = 2;Offset:x=0,y=0
根据上面的程序:顶点对应的纹理坐标就变成了:x = Ox * 2,y = Oy * 2,
即若:Ox = 0.5,Oy = 0.5此时x = 1,y = 1,则顶点对应的纹理坐标就是(1,1),最后采样得到的颜色也是(1,1)处的颜色
当Ox > 0.5,Oy > 0.5若采用Clamp模式,则此时由于x > 1,y >1,最后采样得到的颜色都是(1,1)处的颜色
若采用Repeat,则使用小数部分采样。
当然如果你在程序中:直接令x = Ox, y = Oy,则上面的设置并不会起作用。

在图片的Import Setting界面中,有一个属性Filter Mode属性,它决定了当前纹理由于变换而产生拉伸时将会采用哪种滤波模式。Filter Mode支持3中模式:Point,Bilinear以及Trilinear.它们得到的图片滤波效果依次提升,但需要耗费的性能也依次增大。通常我们会选择Bilinear滤波模式,若希望像素风,则选择Point模式。

阅读全文
0 0
原创粉丝点击