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

在上一个文章中,使用的shader仍有可以改进的地方。
上一篇中并没有没有对硬边缘做可调整的操作(可以通过参数调整过渡值),同时因为我们不需要对高光进行过渡处理,没有对高光值做Power处理,这会使得高光值的变化不够满足需求,这次加上,同时,我想让渲染效果更佳漂亮,于是决定对于明暗交界线处的颜色增加饱和度,有很多二次元的画师的画中都有表现这一点
我们看看这次的完成效果。(由于录制gif图的话,很大放不下,于是就以图片的形式看看吧)
[Unityshader]在unity中尝试实现三渲二的效果(二)_第1张图片
[Unityshader]在unity中尝试实现三渲二的效果(二)_第2张图片[Unityshader]在unity中尝试实现三渲二的效果(二)_第3张图片[Unityshader]在unity中尝试实现三渲二的效果(二)_第4张图片
[Unityshader]在unity中尝试实现三渲二的效果(二)_第5张图片
明暗分割线处,会采样当前纹理的颜色,增加饱和度。

可控的边缘

想要使得边缘变得可以过渡,我们将使用smoothstep来替代step。
smoothstep(x,y,z);(z为漫反射的值)
当y>z>x时,结果z在0-1之间的插值,
当zy时返回1。
一般来说会取x和y为相反数。x,y的绝对值决定了过渡的强度因为[x,y]这个区间的长度决定了插值结果的长度。

增加明暗交界线饱和度提高效果

指定明暗交界线区域

float BDedge=(1-smoothstep(-_BDsmooth,_BDsmooth,abs(diffuseV-_BDEdgePos)-_BDEdge));

先来梳理下各变量表达的意思:
diffuseV指的是光方向向量点乘法向量的结果,取值范围是(-1,1)。
有一定数学基础的应该能理解,abs(x-y)绝对值函数,的含义是x和y之间的距离。
在这里指的就是当前的漫反射值与明暗交界线的漫反射值的差值。

于是smoothstep现在表示的意思就是,距离比_BDsmooth这个值要大的设置为1(白色),小于_BDsmooth的设置为1-0之间的差值,而绝对值是一直大于0的,故不会小于-_BDsmooth(假设_BDsmooth不是负数),从而形成了一条可过渡的线在物体上,可以通过_BDEdgePos调整明暗交界线的位置。

最后我们要把这个值用一减去从而得到黑白颠倒的图形,因为我们希望明暗交界线是白色(1,1,1,1)的这样就能和颜色值相乘,同时两边为黑色(0,0,0,0)就不会对其他区域产生影响。

改变饱和度

个人对饱和度的理解是,灰阶的rgb+不完全的rgb数值:
[Unityshader]在unity中尝试实现三渲二的效果(二)_第6张图片在这里插入图片描述
取一个颜色中数值最低的那位,如图即r通道,生成一个灰度rgb即各通道值相同,于是生成了(0.2,0.2,0.2)的向量,然后我们再用原值减去这个值就能够得到不带灰阶的颜色。此时如果把减去后的值乘上一个大于1的常数就能提升饱和度。
在UnityShader中提供了我们float Luminance(fiexd4 color);方法来轻松获取物体的明度

下面提供完整代码,注意要附上光照贴图,否则会发生高光不可改变的表现

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
        _HighLightSmooth("高光过渡",Range(0,1))=0.1
        _HighLightPower("高光Power值",Range(1,86))=1

        _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"="ForwardBase" }
        LOD 100
        Pass
	{
		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
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "Lighting.cginc"

            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(lightTex,1))+BDedge*(surfacecolor-bv4)*_BDColorValue;
            }
            ENDCG
        }                                                                                                                                                
    }
    Fallback "Specular"
}

你可能感兴趣的:([Unityshader]在unity中尝试实现三渲二的效果(二))