您的位置:首页 > 其它

三言两语说shader(七)黑幕扩散

2016-04-09 21:18 260 查看
按计划继续,目前为止写了三篇对工程已有shader的分析解读,当然实际上我读的shader远不止这三个啦,比如这周就把乐乐同学的blog里的几十篇文章泛泛通读了一遍,主要也是为自己开始构思写一些简单的shader作准备,所谓“思而不学则殆”,不多看些别人的东西自己就想搞创作明显是要吃亏的。

所谓“黑幕扩散”,就是一开始屏幕全黑,然后从中心向外逐渐展示出游戏画面。

为什么我要做这么一个东西呢?一是它想来比较简单。二是去年这个时候,一个UI妹子提出了这个需求,我那时哪懂什么shader咯,只好想了个笨办法,找她要了张中间挖了一个圆孔的黑图,贴面片上,放摄像机前面,然后用扩大面片尺寸的方法,好歹也给实现了,哈哈,这当然很蠢。

现在我是具备这个能力了,可惜妹子也早已离职。

废话不多说,开工。

shader是能利用内置的time变量通过取模方式在时间跨度上做一些动画效果的,比如那些UV动画、滚动的波浪、跳动的心之类的。

但是也都只能循环播放,假如想做一些一次性的变化,比如内置一个bool IsAlreadyRunning标志量,第一次运行时执行某些代码,然后将此标志量改变,第二次运行时,就不再执行某些代码,这种功能我估计是必须借助外部脚本控制的,假如哪位大神能不借助外力神奇的只让shader动画播放一次,请赐教。

我的想法是在之前黑屏shader的基础上加个半径属性,使半径圆内不黑掉即可。

试了下是可行的,HLSL有个内置函数distance,然后屏幕中心点借用Unity提供的内置参数_ScreenParams即可。代码如下:

Shader "MyShader/BlackScreenSpread"
{
Properties
{
_Color("Main Color", Color) = (0.5,0.5,0.5,0.5)
_MainTex ("Base (RGB)", 2D) = "white" {}
_Radius("ViewRadius", float) = 0.0
}

SubShader
{
Pass
{
CGPROGRAM
#include "UnityCG.cginc"
#pragma vertex vert_img
#pragma fragment frag

fixed4 _Color;
sampler2D _MainTex;
float _Radius;

float4 frag (v2f_img i) : COLOR
{
float2 centerPoint = float2(_ScreenParams.x / 2, _ScreenParams.y / 2);
if ( distance(i.pos.xy, centerPoint) > _Radius)
{
return tex2D(_MainTex, i.uv) * _Color;
}
else
{
return tex2D(_MainTex, i.uv);
}
}
ENDCG
}
}
Fallback off
}


注意这里用了if else这种流程控制语句,因为我查了下Cg/HLSL是支持这些流程控制关键字的,所以就试了下。

但我们会发现别人的shader中基本看不到if,传说这种写法效率极低,具体怎么回事去网上可以搜到相关解释。

不使用if的计算方法肯定是有的,不过我就暂时偷个懒不深究了。

另外在Unity Editor中圆的中心往往和画面中心有偏差,具体原因我也不深究了,反正发布了一个Android包实机测试画面是正确的。

效果如下:



外部控制脚本加个radius变量更新下就好了,这里也略过。

另外通过这次实验我发现顶点经过MVP变换后,pos的xy确实已经是屏幕的像素坐标了,而且坐标原点在左上角,往右是x轴正向,往下是y轴正向。

最后扯点别的,因为我Unity重新安装过,这次为了用UnityRemote看实际效果,又装了次JDK和Android SDK,好像Unity5.0后就要多设置一个JDK路径了,我设了好久都说路径无效,后来把JDK重新装在C盘而不是原来的D盘就没问题了,真是坑。

UnityRemote最终还是不能使用,有谁还在用的可以告诉我一声。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: