美文网首页
Shader学习21——基于菲涅尔透明的扫描线

Shader学习21——基于菲涅尔透明的扫描线

作者: ShawnWeasley | 来源:发表于2021-03-26 17:24 被阅读0次

看到人家这样的一个效果,于是想自己也复制一个

Mar-26-2021 17-16-26.gif
想了一下思路,应该是菲涅尔的做的一个透明效果(单纯的菲涅尔透明可以看这篇),再去做了一个线的效果,线应该可以用纹理做性能更好,但本篇用计算做了个线。最终效果如下
Mar-26-2021 17-21-35.gif
代码如下:
Shader "Class/简单应用/扫描线透明菲涅尔"
{
    Properties{
        _Speed("Speed", Float) = 1  //扫描线移动速度
        //扫描线位置
        _DiscardFactor("DiscardFactor",Range(-2,2)) = 0.0
        //扫描线移动方向
        [KeywordEnum(LeftRight, UpDown, Around)] _Dir("Dir", Float) = 0
        //扫描线移动顺序-正反
        [KeywordEnum(JUST, BACK)] _ORDER("ORDER", Float) = 0
        //切口光的颜色
        _LightColor("LightColor",Color) = (1,1,1,1)
        //光的宽度
        _LightWidth("LightWidth",Range(0.0,0.1))=0.05

        _RimColor("RimColor", Color) = (1,1,1,1) //边缘光颜色
        _RimPower("RimPower",Range(0,2)) =0 //边缘光强度
    }
    SubShader{
        Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
        Pass {
            // 只有定义了正确的LightMode才能得到一些Unity的内置光照变量
            Tags { "LightMode"="ForwardBase"}

            LOD 200

            Blend SrcAlpha One //开启Blend混合,设置源颜色和目标颜色混合因子,混合模式可以多尝试,会有不同的效果


            CGPROGRAM
            #include "UnityCG.cginc"
            // 包含unity的内置的文件,才可以使用Unity内置的一些变量
            #pragma vertex vert
            #pragma fragment frag
            //设定宏定义
            #pragma multi_compile _DIR_LEFTRIGHT  _DIR_UPDOWN  _DIR_AROUND
            #pragma multi_compile _ORDER_JUST  _ORDER_BACK

            float _Speed;
            float _DiscardFactor;
            float4 _LightColor;
            float _LightWidth;

            fixed4 _RimColor;
            float _RimPower;
            struct a2v
            {
                float4 vertex : POSITION;    // 告诉Unity把模型空间下的顶点坐标填充给vertex属性
                float3 normal : NORMAL;        // 不再使用模型自带的法线。保留该变量是因为切线空间是通过(模型里的)法线和(模型里的)切线确定的。
            };

            struct v2f
            {
                float4 vertex : SV_POSITION; // 声明用来存储顶点在裁剪空间下的坐标
                float3 normal : NORMAL;  
                float3 worldPos:TEXCOORD0;
                float3 viewDir : TEXCOORD1;

            };

            // 计算顶点坐标从模型坐标系转换到裁剪面坐标系
            v2f vert(a2v v)
            {
                v2f o;
                //顶点坐标转换
                // 该步骤用来把一个坐标从模型空间转换到剪裁空间
                o.vertex = UnityObjectToClipPos(v.vertex); 

                //获取法线(把法线方向从模型空间转换到世界空间)。
                o.normal = UnityObjectToWorldNormal(v.normal);

                //顶点坐标转世界坐标
                o.worldPos= mul(unity_ObjectToWorld, v.vertex).xyz;

                //世界空间中从该点到摄像机的观察方向
                o.viewDir = normalize(UnityWorldSpaceViewDir(o.worldPos));
                return o;
            }

            fixed4 frag(v2f i) : SV_Target 
            {
                /**************************根据时间移动线******************************/
                float time = 2-fmod(_Time.z*_Speed , 4);  
                _DiscardFactor=time;
                /********************************************************/

                /**************************扫描线位置******************************/
                float factor =0;

                #if defined(_DIR_LEFTRIGHT)
                    factor = i.worldPos.x;
                #elif defined(_DIR_UPDOWN)
                    factor = i.worldPos.y;
                #elif defined(_DIR_AROUND)
                    factor = i.worldPos.z;
                #endif
                /********************************************************/
                
                /**************************实现扫描线******************************/
                fixed4 linecol=fixed4(0.0,0.0,0.0,0.0);
                #if defined(_ORDER_JUST)
                    //factor<_DiscardFactor的部分已经被裁减,剩下的部分在加个边界做切面的描边
                    if (factor>_DiscardFactor&&factor < _DiscardFactor+_LightWidth)
                    //从边界逐渐过度
                    linecol= _LightColor*smoothstep(_DiscardFactor+_LightWidth,_DiscardFactor,factor);
                #elif defined(_ORDER_BACK)
                    if (factor*-1>_DiscardFactor&&factor*-1< _DiscardFactor+_LightWidth)
                    linecol= _LightColor*(1-smoothstep(_DiscardFactor+_LightWidth,_DiscardFactor,factor*-1));
                #endif
                /********************************************************/

                /**************************边缘光实现******************************/
                //摄像机角度
                float3 view = normalize(i.viewDir);
                //摄像机入射角度和法线点乘,得出摄像机和法线的角度关系
                float NdotV = dot(i.normal,view);
                //菲涅尔 越接近边缘_RimPower - NdotV越大,然后筛除<0的数,乘以颜色
                float3 fresnel = _RimColor * saturate(_RimPower - NdotV)+linecol;
                /********************************************************/
                float alpha=smoothstep(0.0,0.5,(fresnel.r+fresnel.g+fresnel.b)*0.333);
                return fixed4(fresnel,alpha); //色彩叠加后与贴图颜色相乘
            }

            ENDCG
        }
        
    }
    FallBack "Diffuse"
}

相关文章

  • Shader学习21——基于菲涅尔透明的扫描线

    看到人家这样的一个效果,于是想自己也复制一个 想了一下思路,应该是菲涅尔的做的一个透明效果(单纯的 可以看这篇),...

  • Three.js MeshStandardMaterial菲涅尔

    前面两篇分别讲了Three.js的源码结构和Shader改写方法,本篇做一个基于Standard材质的菲涅尔。如未...

  • Shader-FresnelReflection(菲涅尔反射)

    菲涅尔公式:用来描述光在不同折射率的介质之间的行为。用公式推导出的光的反射称之为“菲涅尔反射”。 应用:运用于类似...

  • VR家装-Tips-玻璃

    玻璃一般情况下是黑色或者深墨绿色,注意菲涅尔反射、折射、透明三个值玻璃材质具有的3大特点。 菲涅尔反射:正对摄影机...

  • Zemax VR菲涅尔设计总结

    目前VR菲涅尔透镜使用一面凸面,一面菲涅尔面; 用理想菲涅尔设计有可能不能加工; 波长设计最好使用屏幕的RGB波长...

  • 24 菲涅尔节点

    金属的菲涅尔非常弱

  • 菲涅尔 Fresnel

    奥古斯汀·菲涅耳 Augustin Fresnel(1788~1827),法国土木工程师兼物理学家。 菲涅耳的科学...

  • [光照]菲涅尔反射

    1.综述 有一种情况,当我们站在湖边直接看脚边的湖面会发现水几乎是透明的,可以直接看到水底的小鱼和石子,但是抬头看...

  • 在材质中使用菲涅尔效果

    菲涅尔 是指光照基于观察者的角度来形成不同强度反射的现象。举例而言,站在一个水池边直视池底将无法看到水中存在的大量...

  • [Shader] 固定管线2 纹理混合及透明

    纹理混合 透明 通过上面对 fiexd function shader 的学习,可以假设如果需要透明,那么只要将各...

网友评论

      本文标题:Shader学习21——基于菲涅尔透明的扫描线

      本文链接:https://www.haomeiwen.com/subject/jqxshltx.html