[Unityshader]在unity中尝试实现三渲二的效果(三)

《[Unityshader]在unity中尝试实现三渲二的效果(三)》
这次进行的改进如下:

  • 多光源处理
  • 增加光照贴图的可控性

要进行多光源处理,我们需要使用前向渲染,因为这样才能访问到正确的光照信息。
当Unity中有多个配置为重要(important)的光源时,Unity会根据这些光对物体的影响程度(距离,强度等)来对这些光源做一个排序。对于最重要的那个光源(点光源除外)将会在设置LightMode为ForwardBase的那个pass中进行。而对于其它的重要光(能处理几个需要在项目设置->质量中设置最大像素光源数目)将会在设置为ForwardAdd的pass中进行。
《[Unityshader]在unity中尝试实现三渲二的效果(三)》
对于其它次要的光源,我希望它不会对阴影边缘产生饱和度增加的效果,同时,环境光ambient已经在ForwardBase的pass中计算过了,所以在计算其它光源的时候就不需要了再计算了。为了让次要的光源更可控,我们把DarkSideEdge做了可控的Power处理,同时使用了smoothstep来对边缘做过度化处理,这样可以让背光更加的可控。同时因为在主pass中我们对暗部的亮度做了可控处理,所以addpass也不需要暗部的颜色,也就是说只保留亮部的颜色叠加上去。所以在forwardpass中我们减去了很多运算和变量。
《[Unityshader]在unity中尝试实现三渲二的效果(三)》
只开启背光时,由于此时设置的背光是点光源模式,所以不会进入到ForwardBase中处理,而是进入到ForwardAdd中处理。
《[Unityshader]在unity中尝试实现三渲二的效果(三)》
只开启主光时。

以下为完整代码段

Shader "Unlit/anim2"
{ 
    Properties
    { 
        _MainTex ("主贴图", 2D) = "white" { }
        _LightTex("高光贴图",2D)="white"{ }
        _BaseColor("叠加色",Color)=(1,1,1,1)

        _DarkSideEdge("暗部范围",Range(-1,1))=0
        _DarksideSmooth("暗部边缘过渡",Range(0,1))=0
        _DarkSideBrightness("暗部亮度",Range(0,1))=1

        _HighLightEdge("高光范围",Range(-1,1))=0
        _HighLightMapLerp("高光贴图插值",Range(0,1))=1
        _HighLightSmooth("高光过渡",Range(0,1))=0.1
        _HighLightPower("高光Power值",Range(1,86))=1

        _SubDSEdge("背光亮部范围",Range(0,1))=0
        _SubDSPower("背光亮部Power",Range(1,10))=1
        _SubDSSmooth("背光亮部过渡",Range(0,1))=0

        _BDEdge("明暗分割线范围",Range(0,1))=0
        _BDEdgePos("明暗分割线位置",Range(-1,1))=0
        _BDsmooth("明暗分割线过渡",Range(0,1))=0
        _BDColorValue("明暗分割线饱和值",Range(0,10))=0
        
        _Factor("描边宽度",Range(0,1)) = 0.01		
		_OutLineColor("描边颜色",Color) = (0,0,0,1)

    }
    SubShader
    { 
        Tags {  "RenderType"="Opaque" }
        LOD 100
        Pass
	{ 
        NAME "OUTLINE"
		Cull Front //剔除前面
		CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
 
		struct v2f
	{ 
		float4 vertex :POSITION;
	};
   
	float _Factor;
	half4 _OutLineColor;
 
	v2f vert(appdata_full v)
	{ 
		v2f o;
		//将顶点沿法线方向向外扩展一下
		float4 pos=v.vertex+float4(v.normal*_Factor,1.0);
        o.vertex=UnityObjectToClipPos(pos);
 
		return o;
	}
 
	half4 frag(v2f v) :COLOR
	{ 
		//只显示描边的颜色
		return _OutLineColor;
	}
		ENDCG
	}
        
        Pass
        { 
            Tags{ "LightMode"="ForwardBase"}
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "Lighting.cginc"
            float _HighLightMapLerp;
            float _BDEdge;
            float _HighLightSmooth;
            float _DarksideSmooth;
            float _BDsmooth;
            float4 _BDEdgeColor;
            float _BDEdgePos;
            float _DarkSideEdge;
            sampler2D _MainTex;
            sampler2D _LightTex;
            float4 _MainTex_ST;
            float4 _LightTex_ST;
            fixed4 _BaseColor;
            float _DarkSideBrightness;
            float _HighLightEdge;
            float _BDColorValue;
            float _HighLightPower;
            struct appdata
            { 
                float4 vertex : POSITION;
                float3 normal:NORMAL;
                float2 uv:TEXCOORD0;
            };

            struct v2f
            { 
                float2 uv:TEXCOORD0;
                float3 worldNormal:TEXCOORD1;
                float3 worldPos:TEXCOORD2;
                float2 uvlight:TEXCOORD3;
                float4 vertex : POSITION;
  
            };

            v2f vert (appdata v)
            { 
                v2f o;
                o.vertex=UnityObjectToClipPos(v.vertex);
                o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;//获取世界空间的顶点位置
                o.worldNormal=mul(unity_ObjectToWorld,v.normal);//获取世界空间的法线向量
                o.uv=TRANSFORM_TEX(v.uv,_MainTex);
                o.uvlight=TRANSFORM_TEX(v.uv,_LightTex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            { 
                fixed3 lightTex=tex2D(_LightTex,i.uvlight);
                
                float3 lightDir=normalize(UnityWorldSpaceLightDir(i.worldPos));
                float3 viewDir=normalize(UnityWorldSpaceViewDir(i.worldPos));
                // sample the texture
                float3 worldNormal=normalize(i.worldNormal);

                float diffuseV=dot(worldNormal,lightDir);
                
                fixed4 surfacecolor=tex2D(_MainTex,i.uv)*_BaseColor;
                float diffStep=smoothstep(-_DarksideSmooth,_DarksideSmooth,diffuseV-_DarkSideEdge);
                float BDedge=(1-smoothstep(-_BDsmooth,_BDsmooth,abs(diffuseV-_BDEdgePos)-_BDEdge));//技术难题1:如何移动此光圈的位置
                float tmp=1-diffStep;
                float ds=tmp*_DarkSideBrightness;

                float highLightV=pow(dot(viewDir,reflect(-lightDir,worldNormal)),_HighLightPower);
                float hlvSp=smoothstep(-_HighLightSmooth,_HighLightSmooth,highLightV-_HighLightEdge);
                float bv=Luminance(surfacecolor);
                fixed4 bv4=fixed4(bv,bv,bv,0);
                
                fixed4 dsColor=(UNITY_LIGHTMODEL_AMBIENT+ds*surfacecolor*_BaseColor);
                return (_LightColor0*surfacecolor*diffStep+dsColor+hlvSp*fixed4(1,1,1,1)*_LightColor0*fixed4(lerp(lightTex,fixed3(1,1,1),_HighLightMapLerp),1))+BDedge*(surfacecolor-bv4)*_BDColorValue*Luminance(_LightColor0);
            }
            ENDCG
        }                  
        pass{ 
            Tags{ "LightMode"="ForwardAdd"}
            Blend oneminusdstcolor one
            CGPROGRAM
            #pragma multi_compile_fwdadd

             #pragma vertex vert
            #pragma fragment frag
            #include "Lighting.cginc"

            float _SubDSEdge;
            float _SubDSPower;
            float _SubDSSmooth;
            sampler2D _MainTex;

            float4 _MainTex_ST;

            fixed4 _BaseColor;

            struct appdata
            { 
                float4 vertex : POSITION;
                float3 normal:NORMAL;
                float2 uv:TEXCOORD0;
            };

            struct v2f
            { 
                float2 uv:TEXCOORD0;
                float3 worldNormal:TEXCOORD1;
                float3 worldPos:TEXCOORD2;
                float4 vertex : POSITION;
  
            };

            v2f vert (appdata v)
            { 
                v2f o;
                o.vertex=UnityObjectToClipPos(v.vertex);
                o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;//获取世界空间的顶点位置
                o.worldNormal=mul(unity_ObjectToWorld,v.normal);//获取世界空间的法线向量
                o.uv=TRANSFORM_TEX(v.uv,_MainTex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            { 
            #ifdef USING_DIRECTIONAL_LIGHT
                fixed3 lightDir=normalize(_WorldSpaceLightPos0.xyz);
            #else 
                fixed3 lightDir=normalize(_WorldSpaceLightPos0.xyz-i.worldPos);
            #endif
                // sample the texture
                float3 worldNormal=normalize(i.worldNormal);

                float diffuseV=pow(dot(worldNormal,lightDir),_SubDSPower);
                
                fixed4 surfacecolor=tex2D(_MainTex,i.uv)*_BaseColor;
                float diffStep=smoothstep(-_SubDSSmooth,_SubDSSmooth,diffuseV-_SubDSEdge);

                return (_LightColor0*surfacecolor*diffStep);
            }
            ENDCG
            }                                                                                                     
    }
    Fallback "Specular"
}
    原文作者:晨蓝fk
    原文地址: https://blog.csdn.net/qq_41083853/article/details/104419028
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞