UnityShader

【Unity Shader入门精要学习】基础纹理(一)

2019-08-25  本文已影响0人  小王子称号发放NPC

单张纹理

Shader "Unlit/SingleTexture"
{
    Properties
    {
        _Color("Color Tint",Color)=(1.0,1.0,1.0,1.0)
        _MainTex("Main Tex",2D) = "white"{}
        _Specular("Specular",Color)=(1.0,1.0,1.0,1.0)
        _Gloss("Gloss",Range(1.0,100.0)) = 30.0
    }

    SubShader
    {
        Pass
        {
            Tags{"LightModel"="ForwardBase"}
            CGPROGRAM
            #include "Lighting.cginc"
            #pragma vertex vert
            #pragma fragment frag

            fixed4 _Color;
            sampler2D _MainTex;
            float4 _MainTex_ST;
            fixed4 _Specular;
            float _Gloss;

            struct a2v
            {
                float4 pos:POSITION;
                float3 normal:NORMAL;
                float4 texcoord:TEXCOORD0;
            };

            struct v2f
            {
                float4 clipPos:SV_POSITION;
                float4 worldPos:TEXCOORD0;
                float3 worldNormal:TEXCOORD1;
                float2 uv:TEXCOORD2;
            };

            v2f vert(a2v a)
            {
                v2f o;
                o.clipPos = UnityObjectToClipPos(a.pos);
                o.worldPos = mul(unity_ObjectToWorld,a.pos);
                //o.worldNormal = mul(a.normal,unity_WorldToObject);
                o.worldNormal = UnityObjectToWorldNormal(a.normal);
                o.uv = a.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
                //o.uv = TRANSFORM_TEX(a.texcoord,_MainTex);
                return o;
            }

            fixed4 frag(v2f v):SV_TARGET
            {
                float3 worldNormal = normalize(v.worldNormal);
                float3 worldLightDir = normalize(UnityWorldSpaceLightDir(_WorldSpaceLightPos0.xyz));
                float3 worldViewDir = normalize(UnityWorldSpaceViewDir(v.worldPos));
                float3 halfNormal = normalize(worldLightDir + worldViewDir);

                
                fixed3 albedo = tex2D(_MainTex,v.uv).rgb * _Color.rgb;
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
                fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(worldNormal,halfNormal)),_Gloss);

                //diffuse
                fixed3 diffuse = _LightColor0.rgb * albedo * saturate(dot(worldNormal,worldLightDir));

                return fixed4(ambient + specular + diffuse,1.0);
            }

            ENDCG
        }
    }

    FallBack "Specular"
}

注意shader中纹理坐标的变换:

o.uv = a.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
o.uv = TRANSFORM_TEX(a.texcoord,_MainTex);

1、纹理属性

wrap mode
wrap mode它决定了当纹理坐标超过[0,1]范围后将会如何平铺。它有两种模式:
(1)Repeat,在这种模式下,如果纹理坐标超过了1,那么它的整数部分会被舍弃,而直接使用小数部分进行采样,这样的结果是纹理将会不断重复(因为一直采样的是0--1之间的部分)
(2)clamp,这种模式下如果纹理坐标大于1,那么就会截取到1,如果小于0则会截取0。所以超过的部分则相当于绘制的是边界部分。
Filter Mode
Filter Mode它决定了当纹理由于变换而产生拉伸时将会采用哪种滤波模式。
Point,Bilinear,Trilinear,它们得到的图片滤波效果依次提升,但需消耗的性能也依次增大。纹理滤波会影响放大缩小纹理时得到的图片质量,例如有时需要把一张64X64的纹理贴在512X512的平面上,就需要放大图片。
(1)Point,使用了最邻近滤波,在放大缩小时,它采样的像素数目通常只有一个,因此图像看起来有一种像素风。

repeat+point
(2)Bilinear,使用了线性滤波,对于每个像素,它会找到4个邻近像素,然后对它们进行线性插值混合后得到最终像素,因此图像看起来像被模糊了
repeat+bilinear
(3)Trilinear,它几乎和Bilinear的效果是一样的,只是Trilinear还会在多级渐远纹理之间进行混合,如果一张纹理没有使用多级渐远,那么Trilinear和Bilinear的结果是一样的
repeat+trilinear
多级渐远纹理(mipmapping)
纹理的缩小过程比放大更加复杂一些,此时原纹理中的多个像素会将对应一个目标像素,往往需要处理抗锯齿问题,而多级渐远纹理就是为了处理这个问题的。
多级渐远纹理技术将原纹理提前用滤波处理以得到更多更小的图像,每一级都是对上一级的降采样结果。这样在实时运行时, 可以快速的得到结果像素,如当摄像机远离时可以使用较小的纹理。多级渐远纹理会增大内存占用空间,用空间换时间。
纹理的尺寸
尽量使用2的幂次方尺寸的纹理。
上一篇 下一篇

猜你喜欢

热点阅读