MENU

【Unity】カットアウトシェーダーにカラー・加算を追加する方法

f:id:min0124:20160828115925p:plain

前回の文字を描くようにアニメーションする方法をもう少し良くするべく、シェーダーを作成してみました。

min.hatenablog.jp

結果的には、ネットから探したシェーダーのほうがはるかに便利でしたが、徐々に勉強していきます。

自作でカットアウト(透明・カラー・加算)

Shader "Unlit/Transparent Cutout Additive" {
Properties {
    _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
    _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
}

SubShader {
    Tags {"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
    LOD 100

    Blend SrcAlpha One

    Pass {
        Lighting Off
        Alphatest Greater [_Cutoff]
        SetTexture [_MainTex] { combine texture } 
    }
}
}
  • 一行追加Blend SrcAlpha Oneするだけで、加算になります

ちなみにアルファブレンドにする場合はBlend SrcAlpha OneMinusSrcAlphaを追加するだけです。

TintColorも追加

色も変化できるようにしてみます。

_TintColor ("Tint Color", Color) = (0.5,0.5,0.5,0.5)

AlphaToMask True

ColorMask RGB カラーチャネルの書き込みを設定

        SetTexture [_MainTex]
        {
            Combine texture, texture
        }
        SetTexture [_MainTex] {
            constantColor [_TintColor]
            Combine previous * constant, previous * constant
        } 

上記を加えてると

// Unlit alpha-cutout shader.
// - no lighting
// - no lightmap support
// - no per-material color

Shader "Unlit/Transparent Cutout Additive" {

Properties {
    _TintColor ("Tint Color", Color) = (0.5,0.5,0.5,0.5)
    _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
    _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
}

SubShader {
    Tags {
    "Queue"="AlphaTest"
    "IgnoreProjector"="True"
    "RenderType"="TransparentCutout"
    }
    Cull Off
    LOD 100

    Blend SrcAlpha One
    AlphaToMask True
    ColorMask RGB

    Pass {
        Lighting Off
        Alphatest Greater [_Cutoff]
        SetTexture [_MainTex]
        {
            Combine texture, texture
        }
        SetTexture [_MainTex] {
            constantColor [_TintColor]
            Combine previous * constant, previous * constant
        }  
    }
}
}

f:id:min0124:20170910213918p:plain

これで加算とカラーを追加できました。

ただし、もともとの素材がアルファで強弱つけているので、最後にいくとだんだん薄くなってしまいます。

なので、別の方法で表現する必要がありそうです。

カットアウト(透明・カラー・加算・マスク・他)

行き詰まって、検索してみたらやりたいことができるシェーダー見つけました。

f:id:min0124:20170910212712p:plain

Shader "Transparent/Cutout/Additive Cutout" {
    Properties{
        [HDR]_TintColor("Tint", Color) = (1,1,1,1)
        _MainTex("Base (RGB) Trans (A)", 2D) = "grey" {}
        _Cloud1Tex("Cloud 1 (RGB) Trans (A)", 2D) = "grey" {}
        _Cloud2Tex("Cloud 2 (RGB) Trans (A)", 2D) = "grey" {}
 
        //_CutTex("Cutout (A)", 2D) = "white" {}
        _Cutoff("Alpha cutoff", Range(0,1)) = 0.5
        _AlphaThreshold("Alpha threshold", Range(0,1)) = 0.01
        _CutoffScroll("Cutoff Scroll Speed", Vector) = (0, 0, 0, 0)
        _InvFade("Soft Factor", Range(0.01,3.0)) = 1.0
        _Boost("Brightness Boost", Range(1, 20)) = 1.0
        _ExternalAlpha("External Alpha", Range(0, 1)) = 1.0
        //_AlphaPower("Alpha power", Range(1, 150)) = 1
    }
 
        SubShader{
            Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" "PreviewType" = "Plane" }
            Blend OneMinusDstColor One
            Alphatest Greater[_Cutoff]
            AlphaToMask True
            ColorMask RGB
            //ColorMask RGB
            Cull Off
            Lighting Off
            ZWrite Off
            //Fog{ Mode Off }
            //Fog Off
       
 
       
        //Cull off
        CGPROGRAM
        #pragma surface surf NoLighting nofog  //one one alpha// Blend One One
        #pragma target 3.0
        #pragma multi_compile _ SOFTPARTICLES_ON
 
    sampler2D _MainTex;
    sampler2D _Cloud1Tex;
    sampler2D _Cloud2Tex;
 
    fixed4 _TintColor;
    float _Cutoff;
    float _AlphaThreshold;
    uniform float _ExternalAlpha = 1;
    float4 _CutoffScroll;
    float _InvFade;
    float _Boost;
    sampler2D_float _CameraDepthTexture;
    fixed4 LightingNoLighting(SurfaceOutput s, fixed3 lightDir, fixed atten)
    {
        fixed4 c;
        c.rgb = s.Albedo;
        c.a = s.Alpha;
        return c;
    }
    float Remap(float value, float inMin, float inMax, float outMin, float outMax)
    {
        return outMin + (((value - inMin) / (inMax - inMin)) * (outMax - outMin));
    }
 
    struct Input
    {
        float2 uv_MainTex;
        float2 uv_Cloud1Tex;
        float2 uv_Cloud2Tex;
        float4 color : COLOR;
        float3 worldPos;
#ifdef SOFTPARTICLES_ON
        float4 screenPos;
        float eyeDepth;
#endif
    };
#ifdef SOFTPARTICLES_ON
    void vert(inout appdata_full v, out Input o)
    {
        UNITY_INITIALIZE_OUTPUT(Input, o);
        COMPUTE_EYEDEPTH(o.eyeDepth);
    }
#endif
    void surf(Input IN, inout SurfaceOutput o)
    {
 
        //Arrange scrolling into 2 separate vectors
        float2 scrollOffsetCloud1;
        float2 scrollOffsetCloud2;
        float time;
        time = _Time[0];// +IN.worldPos.y;
 
        scrollOffsetCloud1.x = (time * _CutoffScroll.x);
        scrollOffsetCloud1.y = (time * _CutoffScroll.y);
        scrollOffsetCloud2.x = (time * _CutoffScroll.z);
        scrollOffsetCloud2.y = (time * _CutoffScroll.w);
 
        //Pull main texture...
        fixed4 mainTexelColor = tex2D(_MainTex, IN.uv_MainTex);
        mainTexelColor = mainTexelColor * _TintColor * IN.color;// *fixed4(1, 0, 0, 0);
 
        //..Then get cloud texture and multiply
        fixed4 cloud1TexelColor = tex2D(_Cloud1Tex, IN.uv_Cloud1Tex + scrollOffsetCloud1);
        fixed4 cloud2TexelColor = tex2D(_Cloud2Tex, IN.uv_Cloud2Tex + scrollOffsetCloud2);
 
        //MAGIC
        fixed4 finalColor;
        finalColor = mainTexelColor;
        finalColor.a = (mainTexelColor.a * cloud1TexelColor.a * 2) * cloud2TexelColor.a * 2;
 
 
        //Cutoff math
        float ca = finalColor.a ;
        float a = ca;
        float progress = 1 - IN.color.a;
        float thresh = _AlphaThreshold;
        float fadeMin = clamp(_Cutoff - thresh, 0, 1);
        float fadeMax = clamp(_Cutoff + thresh, 0, 1);
 
       
        float currentAlpha = ca * (1 - progress) * _ExternalAlpha;;
        a = clamp(Remap(currentAlpha, fadeMin, fadeMax, 0, 1), 0, 1);
        float fade = 1;
        #ifdef SOFTPARTICLES_ON
            float rawZ = SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(IN.screenPos));
            float sceneZ = LinearEyeDepth(rawZ);
            fade = saturate(_InvFade * (sceneZ - IN.screenPos.w));   //float partZ = IN.eyeDepth;
        #endif
 
        o.Alpha = a;
        o.Albedo = clamp(finalColor.rgb * a * _Boost, 0, 1) * fade;
    }
 
 
    ENDCG
    }
 
        Fallback "Transparent/VertexLit"
}