zoukankan      html  css  js  c++  java
  • Shader之溶解效果的几种实现方法

    这里通过 “是否丢弃像素”的2种方法,写2个shader,效果是一样的,也提到了,丢弃某个像素的3种方式。

    是否丢弃:

      1.通过脚本控制shader变量判断当前是否丢弃像素,需要额外脚本;

      2.shader根据当前时间控制是否丢弃某个像素,不需要额外脚本。

    丢弃方法:

      1.通过clip函数进行丢弃像素;

      2.通过discard丢弃像素;

      3.通过设置alpha变量为0丢弃像素。

    1)DissolveOne.shader通过脚本控制

    Shader "Unlit/DissolveOne"
    {    
        Properties
        {
            //外部脚本控制_Value来控制是否丢弃某个像素
            _MainTex ("Texture", 2D) = "white" {}
            _DissolveTex("Texture", 2D) = "white" {}
            _DissSize("DissSize", Range(0, 1)) = 0.1 //溶解阈值,小于阈值才属于溶解带
            _DissColor("DissColor", Color) = (1,0,0,1)//溶解带的渐变颜色,与_AddColor配合形成渐变色
            _AddColor("AddColor", Color) = (1,1,0,1)
            _Value("Value", Range(0,1)) = 0.5 //这个属性其实不用开放出来的,通过脚本控制就好,但我想看效果却懒得写脚本,就这样吧
        }
        SubShader
        {
            Tags { "RenderType"="Opaque" }
            LOD 100
    
            Pass
            {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                
                #include "UnityCG.cginc"
    
                struct appdata
                {
                    float4 vertex : POSITION;
                    float2 uv : TEXCOORD0;
                };
    
                struct v2f
                {
                    float2 uv : TEXCOORD0;
                    float4 vertex : SV_POSITION;
                };
    
                sampler2D _MainTex;
                sampler2D _DissolveTex;
                float4 _MainTex_ST;
                half _Value;//脚本控制的变量
                half _DissSize;
                half4 _DissColor, _AddColor;
    
                v2f vert (appdata v)
                {
                    v2f o;
                    o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
                    o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                    return o;
                }
                
                fixed4 frag (v2f i) : SV_Target
                {
                    fixed4 col = tex2D(_MainTex, i.uv);
                    float dissolveValue = tex2D(_DissolveTex, i.uv).r;
                    float clipValue = dissolveValue - _Value;
                    clip(clipValue);// 如果clipValue<0则抛弃当前像素,
                    //clip is equivalent to (if(clipValue<0)discard;),但好像好像discard需要更高一点的硬件支持
                    //也可以通过设置col.a = 0抛弃当前像素:if(clipValue<0)col.a = 0;
                    if (clipValue > 0 && clipValue < _DissSize)
                    {
                        //溶解带渐变
                        half4 dissolveColor = lerp(_DissColor, _AddColor, clipValue / _DissSize)* 2;
                        col *= dissolveColor;
                    }
                    return col;
                }
                ENDCG
            }
        }
    }

    2)DissolveTwo.shader根据当前时间控制是否丢弃某个像素

    Shader "Unlit/DissolveTwo"
    {
        Properties
        {
            //shader根据当前时间控制是否丢弃某个像素
            _MainTex("Texture", 2D) = "white" {}
            _DissolveTex("Texture", 2D) = "white" {}
            _DissSize("DissSize", Range(0, 1)) = 0.1 //溶解阈值,小于阈值才属于溶解带
            _DissColor("DissColor", Color) = (1,0,0,1)//溶解带的渐变颜色,与_AddColor配合形成渐变色
            _AddColor("AddColor", Color) = (1,1,0,1)
            _DissSpeed("DissSpeed", Float) = 1
        }
        SubShader
        {
            Tags { "RenderType"="Opaque" }
            LOD 100
    
            Pass
            {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                
                #include "UnityCG.cginc"
    
                struct appdata
                {
                    float4 vertex : POSITION;
                    float2 uv : TEXCOORD0;
                };
    
                struct v2f
                {
                    float2 uv : TEXCOORD0;
                    float4 vertex : SV_POSITION;
                };
    
                sampler2D _MainTex;
                sampler2D _DissolveTex;
                float4 _MainTex_ST;
                half _DissSize;
                half4 _DissColor, _AddColor;
                half _DissSpeed;
    
                v2f vert (appdata v)
                {
                    v2f o;
                    o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
                    o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                    return o;
                }
                
                fixed4 frag (v2f i) : SV_Target
                {
                    // sample the texture
                    fixed4 col = tex2D(_MainTex, i.uv);
                    //因为这个溶解过程很快,所以为了看效果,可以改成:saturate(_Time.y % _DissSpeed / _DissSpeed),重复溶解
                    float dissolveFactor = saturate(_Time.y / _DissSpeed);
                    float dissolveValue = tex2D(_DissolveTex, i.uv).r;
                    float delta = dissolveValue - dissolveFactor;
                    if (delta < 0)
                    {
                        discard;
                    }
    
                    if (delta >= 0 && delta < _DissSize)
                    {
                        float leftFactor = delta / _DissSize;
                        half4 dissolveColor = lerp(_DissColor, _AddColor, leftFactor) * 2;
                        col *= dissolveColor;
                    }
                    return col;
                }
                ENDCG
            }
        }
    }

    两者溶解效果是一样的:

    参考文章:

    1.http://blog.csdn.net/u011047171/article/details/46873217

    2.http://www.cnblogs.com/Esfog/p/DissolveShader.html

  • 相关阅读:
    反射&异常
    成员方法
    继承&多态
    面向对象
    常用模块
    软件目录结构规范
    内置函数
    生产器&迭代器
    装饰器
    函数
  • 原文地址:https://www.cnblogs.com/Tearix/p/6868340.html
Copyright © 2011-2022 走看看