【猫猫的Unity Shader之旅】之混合效果

  今天的好消息是,模型不再用立方体啦,也不是球和Plane,那些太土了,体现不出Shader的高大上有木有。囧了个囧,咳咳,我们是做学问,不要在意这些细节……

  好吧,我们这次的主角是Unity娘,大家到Asset Store可以免费下载到这个萌妹子~

  【猫猫的Unity Shader之旅】之混合效果_第1张图片

勤劳的Shader君

  之前也有说过,我们的Shader最终任务是要计算颜色,但是为了最终的显示效果让老板满意,Shader君也算是煞费苦心啦。没办法,谁叫人家只是个小职员呢,工作多,没提成,额,此处省略一万字……总之,勤劳的Shader君不仅给出了PlanA,还给出了PlanB,然而,最终的颜色只有一个,怎么办,么办,办?

  不管怎样,Shader君最终还是给出了一个特定的颜色。也许是ColorA,也许是ColorB,也许两者都有。这种将多种颜色通过计算得到一种颜色的方法,就叫做混合。

萌妹的限量版马甲

  这次我们要做的是给Unity娘换一件个性的衣服,但是又不能完全去掉原来的衣服的特征,万一换个马甲不认识了呢……

  首先我们要给这件马甲一个单独的材质,叫做bodyMat,然后在新的Shader中定义两个贴图,这样就通过tex2D得到两个颜色信息。为了实现混合,最简单的方法就是把这两个颜色值相乘,代码如下:

Shader "Custom/ClothesShader" {
    Properties {
        _MainTex ("Base (RGB)", 2D) = "white" {}
        _MainTex2 ("Another Texture", 2D) = "white" {}
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        #pragma surface surf Lambert

        sampler2D _MainTex;
        sampler2D _MainTex2;

        struct Input {
            float2 uv_MainTex;
        };

        void surf (Input IN, inout SurfaceOutput o) {
            half4 c = tex2D (_MainTex, IN.uv_MainTex);
            half4 c2 = tex2D (_MainTex2, IN.uv_MainTex);
            o.Albedo = c.rgb * c2.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    } 
    FallBack "Diffuse"
}

  这就是限量款的效果:

  【猫猫的Unity Shader之旅】之混合效果_第2张图片

  颜色在Unity中是以四元数来表示,Color(r1, g1, b1, a1)与Color(r2, g2, b2, a2)相乘的结果就是它们各自分量相乘后的颜色,即Color(r1*r2, g1*g2, b1*b2, a1*a2),这里我们只用了前三个分量,不过道理是一样的。

  先来看下我们用到的第二张贴图(第一张是人家原来的衣服没啥好看的)

  【猫猫的Unity Shader之旅】之混合效果_第3张图片

  这是一张黑白相间的图,对于白色的部分,与第一张图得到的颜色相乘后,还是原来的颜色,对于黑色的部分,相乘后变成黑色,所以第二幅图就好像盖在了第一幅图上一样。

  然而这种方式不是所有时候都能如我们所愿,比如把图中的黑色换成浅绿色:

  【猫猫的Unity Shader之旅】之混合效果_第4张图片

  可以看到绿色和第一幅图的颜色混合后会有变化,既不是第一幅图的颜色,也不是第二幅图的颜色。这种结果并没有错,只是不一定使我们想要的,我们可能希望花纹的部分完全是第二幅的颜色。

  解决这个问题需要用到Color的第四个分量Alpha了,用Alpha值来控制哪些地方需要用第一幅图的颜色,哪些地方用第二幅图的颜色。

Shader "Custom/ClothesShader" {
    Properties {
        _MainTex ("Base (RGB)", 2D) = "white" {}
        _MainTex2 ("Another Texture", 2D) = "white" {}
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        #pragma surface surf Lambert

        sampler2D _MainTex;
        sampler2D _MainTex2;

        struct Input {
            float2 uv_MainTex;
        };

        void surf (Input IN, inout SurfaceOutput o) {
            half4 c = tex2D (_MainTex, IN.uv_MainTex);
            half4 c2 = tex2D (_MainTex2, IN.uv_MainTex);
            o.Albedo = c.rgb * (1.0 - c2.a) + c2.rgb * c2.a;
            o.Alpha = c.a;
        }
        ENDCG
    } 
    FallBack "Diffuse"
}

  修改后的效果如图:

  【猫猫的Unity Shader之旅】之混合效果_第5张图片

  看到这里不知道大家有没有疑惑,我们用到了透明度,但是#pragma后面却没有加alpha,渲染顺序也没有改为Transparent,这是为什么呢?需要说明的是,那些透明材质中说到的内容,只是在将一个模型作为透明物体渲染时才会用到,而我们这个模型本身不是透明的,只是用了一下Alpha值而已。

  附一下用到的工程。

结束语

  今天没什么想说的啦。今天是劳动节,相传这是个需要大家更多地劳动的节日。好吧,希望大家都能像Shader君那样,做一个勤劳的人。

你可能感兴趣的:(【猫猫的Unity,Shader之旅】,猫猫的Unity,Shader之旅)