Unity中背景渐变shader对贝塞尔曲线的应用
发表于2019-01-28
有些游戏中的背景会随机的变化,并且周围有一圈渐变的黑边,看上去很舒服,所以本篇文章就给大家分享下背景渐变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" }