[UnityShader入门精要读书笔记]13.基础纹理

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

在Shader中,我们还需要为纹理类型的属性声明一个float4类型的变量_MainTex_ST。其中,_MainTex_ST的名字不是任意起的。在Unity中,我们需要使用纹理名_ST的方式来声明某个纹理的属性。其中,ST是缩放(scale)和平移(translation)的缩写。_MainTex_ST可以让我们得到该纹理的缩放和平移的值。_MainTex_ST.xy存储的是缩放值,_MainTex_ST.zw存储的是偏移值。


shader "custom/single Texture"{

    //1.为了使用纹理,我们需要在Properties语义块中添加纹理属性。

    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

    }

        //2.在subshader语义块中定义了一个Pass语义块。这是因为顶点/片元着色器的代码需要写在Pass语义块,而非SubShader语义块中。而且,我们在Pass的第一行指明了该Pass的光照模式:

        SubShader{

        Pass{

        Tags{ "LightMode" = "ForwardBase" }

        //3.然后,使用CGPROGRAM和ENDCG来包围CG代码片,以定义最重要的顶点着色器和片元着色器代码。首先,我们使用#pragma指令来告诉Unity我们的顶点着色器和片元着色器叫什么。

        CGPROGRAM

#pragma vertex vert

#pragma fragment frag

        //4.为了使用Unity内置的一些变量,还要包含Unity的内置文件Lighting.cginc

#include "Lighting.cginc"

        //5.定义和Properties声明的属性类型相匹配的变量。

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

        //6.定义顶点着色器的输入和输出结构体(输出结构体同时也是片元着色器的输入结构体)

        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;

    };

    //顶点着色器只需要计算世界空间下的法线方向和顶点坐标,并把他们传递给片元着色器。在顶点着色器中,我们使用纹理的属性值_MainTex_ST来对顶点纹理坐标进行变换,得到最终的纹理坐标。计算过程是,首先使用缩放属性_MainTex_ST.xy对顶点纹理坐标进行缩放,然后再使用偏移属性_MainTex_ST.zw对结果进行偏移,Unity提供了一个内置宏TRANSFORM_TEX来帮我们计算上述过程。TRANSFORM_TEX是在UnityCG.cginc定义的:
    //define TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy = name##_ST.zw) 它接受两个参数,第一个参数是顶点纹理坐标,第二个参数是纹理名,在它的实现中,将利用纹理名_ST的方式来计算变换后的纹理坐标。

    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 = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;

        return o;
    }
    //我们还需要实现片元着色器,并在计算漫反射是使用纹理中的纹素值:我们首先计算世界空间下的法线方向和光照方向。然后,使用CG的tex2D函数对纹理进行采样。它的第一个参数是需要被采样的纹理,第二个参数是一个float2类型的纹理坐标,它将返回计算得到的纹素值。我们使用采样结果和颜色属性_Color的乘积来作为材质的反射率albedo,并把它和环境光照想成得到环境光部分。随后,我们使用albedo来计算漫反射光照的结果,
    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"

}

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值