Unity中背景渐变shader对贝塞尔曲线的应用

发表于2019-01-28
评论0 7.8k浏览
有些游戏中的背景会随机的变化,并且周围有一圈渐变的黑边,看上去很舒服,所以本篇文章就给大家分享下背景渐变shader对贝塞尔曲线的应用。

首先做一个渐变,很简单,2个颜色做插值:
return  lerp(_Color1 ,_Color2,o.uv.y);
因为uv的y坐标的范围是0-1,所以最后一个参数直接使用y坐标即可。

看下效果:

渐变的效果是有了,但是效果不是很理想,所以我们再来对渐变的速率进行一些调整,这时我们之前文章中讲到的贝塞尔曲线就派上了用场。我们先来把公式放到我们的shader中:
fixed GetBezierat(fixed a, fixed b, fixed c, fixed d, fixed t)
		    {
		        return (pow(1 - t, 3) * a +
		                3 * t * (pow(1 - t, 2)) * b +
		                3 * pow(t, 2) * (1 - t) * c +
		                pow(t, 3) * d);
		    } 
与之前一样,公式没有变,只更改了一下调用的api。

有了公式我们就可以让渐变的过程按照我们想要的方式来进行,首先调整出一个我们喜欢的曲线,看下代码:
return  lerp(_Color1 ,_Color2,GetBezierat(0,-1,2,1,o.uv.y));

效果:

以Polyforge游戏为例,原游戏中,背景中还有一圈渐变的黑边,我们可以根据像素点到中心的距离来判断,然后距离越远,亮度越低,修改一下fragment中的代码:
            	fixed4 c = lerp(_Color1 ,_Color2,GetBezierat(0,-1,2,1,o.uv.y));
            	fixed dis = distance(fixed2(0.5,0.5),o.uv.xy);
                return  (1-dis) * c;

其中fixed2(0.5,0.5)为中心点的坐标,因为我们想要的效果是距离中心越远亮度越低,所以这里需要用1-dis来乘上颜色,看下效果:

同样的,也得调整渐变范围,还是用贝塞尔曲线,对距离进行一下处理:
dis = GetBezierat(0,0,1,2,dis)*0.5;

这里乘以0.5是为了避免出现纯黑得情况,看下最终效果:

这里只是对原游戏的效果进行模仿,想要实际应用还要做更细致的调整,如果谁有更好的方式欢迎留言。

其实这里使用程序生成一张Texture2D的贴图来做效率上应该会更好一些,但是最近对shader方面比较关注,所有在这里就顺便使用shader来实现了。

最后上完整shader代码:
Shader "Custom/GradualColor" {
	Properties {
		_Color1 ("Color1", Color) = (0,0,0,1)
		_Color2 ("Color2", Color) = (1,1,1,1)
	}
	SubShader {
		Tags { "RenderType"="Opaque" }
		LOD 200
		Pass{  
            CGPROGRAM  
            #include "UnityCG.cginc"  
            #pragma vertex vert_img  
            #pragma fragment frag  
			fixed4 _Color1;
			fixed4 _Color2; 
			fixed GetBezierat(fixed a, fixed b, fixed c, fixed d, fixed t)
		    {
		        return (pow(1 - t, 3) * a +
		                3 * t * (pow(1 - t, 2)) * b +
		                3 * pow(t, 2) * (1 - t) * c +
		                pow(t, 3) * d);
		    }
            float4 frag( v2f_img o ) : COLOR  
            {  
            	fixed4 c = lerp(_Color1 ,_Color2,GetBezierat(0,-1,2,1,o.uv.y));
            	fixed dis = distance(fixed2(0.5,0.5),o.uv.xy);
            	dis = GetBezierat(0,0,1,2,dis)*0.5;
                return  (1-dis) * c;
                //return  lerp(_Color1 ,_Color2,o.uv.y);
            } 
            ENDCG  
		}
	}
	FallBack "Diffuse"
}

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

标签: