素材来自蛮牛教育,学习就行啦,别转载了
opaque是不透明的意思
上一节中把图片弄成水波一样的代码只适用于静态波动,如果我们要让鼠标在图片上滑动的时候有水波的效果就不能用上一节的代码了,比如如下效果:
首先在c#脚本中这样定义,putpop函数用于在中心位置设置一个能量很大的像素,computeWave函数用于计算每个像素周围的插值并且能量衰减
鼠标指针指在某点的时候,就波动,不在就不波动,这个uv的偏移必须要在外部(c#脚本中update检测鼠标指针位置来计算uv偏移来实现)
在计算波纹的函数中,对波纹的每一个像素取其周围的八个点的和,除4减原来的像素,将每个像素限定在[-1,1]之间,uv的u偏移为左右像素的插值,v偏移为上下像素的插值,
把该像素的坐标(w,h)以及该像素颜色(这里rgb中b分量怎么是0),视频讲的是把uv的插值通过颜色的形式赋给它,waveB[w,h]-=waveB[w,h]*0.001f;不管waveB[w,h]为正还是负经过计算都会趋近于0,意思是让该值的能量衰减一点点。
而在shader中把uv限定在[0,1]之间乘以一个很小的值
效果如下:
当然poppup函数是将中心点置为1向四周能量衰减,实际上我们应该找到鼠标的指针坐标,该坐标一个圆的范围内对周围坐标进行能量赋值
我们将poppup函数改成这个函数,并且调用putDrop(64,64)效果如下,能量从中间向周边扩散,并且波的能量能扩散到图片边界还能反弹回来
最后检测鼠标的指针,射线检测把指针坐标从世界空间转到模型空间即可
效果如下:
对于效率问题:当前的宽和高我们设定的是128*128,但是当把宽高设为512*512时候,查看帧率为16.7FPS非常消耗GPU
优化方法:
耗时的计算是computeWave方法,我们将耗时计算放在一个子线程去调用,在onstart方法里面开辟子线程调用computeWave方法,
而且调用该方法是一直调用,声明一个bool为true,在computeWave里面如果为true就一直循环执行,ondestroy方法里面设为false。update执行函数也是过了一小段时间执行一次,所以在子线程中也要睡眠一段时间再循环执行一次,我们怎么知道一次update间隔多少毫秒呢?用下面方法得到间隔了sleepTime毫秒
然后在子线程中睡眠对应的时间,子线程睡眠的单位是毫秒
运行程序发现报错
意思是setPixel函数不能再子线程中运行,不仅仅是该函数tex_uv.Apply()也不能在子线程中运行,解决办法,由于是把一个颜色值交个pixel,通过缓冲区的方法解决
声明一个在onstart里面初始化
,把pixel那句话替换成
在update函数中调用
然后运行程序,发现帧速率提升到了76.5左右fps
另一种优化方法:
关闭垂直同步,在unity->edit->project settings->Quality在inspector的最下面选择Dont Sync,这样fps会上升到260fps左右
最快的优化方案:异构平台通用化计算(把cpu的计算移植到gpu上)也叫GPGPU,在unity中computer shader就是这种技术
垂直同步:
简单来说垂直同步的作用是防止画面撕裂。因为画面的渲染不是整个画面一起渲染的,是逐行或者逐列渲染。如果关闭垂直同步,而电脑配置不够,则画面在高速移动中会出现这一画面还没渲染完成就开始下一画面的撕裂情况。
打开与关闭垂直同步的主要区别在于那些高速运行的游戏,比如实况,FPS游戏,打开后能防止游戏画面高速移动时画面撕裂现象,当然打开后如果你的游戏画面FPS数能达到或超过你显示器的刷新率,这时你的游戏画面FPS数被限制为你显示器的刷新率。你会觉得原来移动时的游戏画面是如此舒服,如果达不到会出现不同程度的跳帧现象,FPS与刷新率差距越大跳帧越严重。关闭后除高速运动的游戏外其他游戏基本看不出画面撕裂现象。关闭此选项画面流畅程度会有一定的提高。
为什么是否关闭垂直同步信号会影响我们CS中的fps数值?道理一点都不复杂,首先我们平时运行操作系统一般屏幕刷新率是多少?大概一般都是在85上下吧,那么显卡就会每按照85的频率时间来发送一个垂直同步信号,信号和信号的时间间隔是85的分辨率所写一屏图像时间。
如果我们选择“等待垂直同步信号”(也就是我们平时所说的“垂直同步打开”),那么在游戏中,或许强劲的显卡迅速的绘制完一屏的图像,但是没有垂直同步信号的到达,显卡无法绘制下一屏,只有等85单位的信号到达,才可以绘制。这样fps自然要受到操作系统刷新率运行值的制约。
而如果我们选择“不等待垂直同步信号”(也就是我们平时所说“关闭垂直同步”),那么游戏中作完一屏画面,显卡和显示器无需等待垂直同步信号,就可以开始下一屏图像的绘制,自然可以完全发挥显卡的实力。
但是,不要忘记,正是因为垂直同步的存在,才能使得游戏进程和显示器刷新率同步,使得画面平滑,使得画面稳定。取消了垂直同步信号,固然可以换来更快的速度,但是在图像的连续性上,性能势必打折扣。这也正是很多朋友抱怨关闭垂直后发现画面不连续的理论原因!
摘自:http://www.dnpz.net/diannaozhishi/1565.html
Alpha和blend混合:
把一个物体弄成半透明:只需加上一句话
虽然两个物体对于地面都能呈现半透明的状态但是两个物体在一前一后,红色显示不出后面的蓝色,这和render Quene渲染队列有关,在渲染队列中有如下几种方式,Fackground是先渲染该物体,再渲染其他物体,最后的Overlay是所有物体都渲染完了再渲染该物体,默认的是Geonetry
Zwrite的作用:控制哪些像素放到深度缓冲队列,默认是On状态,如果要绘制一个实心物体,就on状态,如果绘制半透明状态就Zwrite off,对于Zwrite的理解是z轴(我们距离屏幕的轴)该点的颜色是否写入深度缓冲区,因为物体深度在近剪裁平面和远剪裁平面之间的z轴(Ztest通过(Ztest也叫深度测试))我们才要把颜色写入
将两个物体都渲染队列都设置为Transparent状态且Zwrite Off状态或者红色是Zwrite off,蓝色on
还要把两个shader重新设置(刷新)一下就出现了希望的样子
半透明着色:对于人物在墙里面也可以进行对人物进行高亮的颜色显示
案例:对于如下的物体,要想让蓝色胶囊体在前面的墙显示出来,在蓝色胶囊体的shader中alpha肯定是混合的,zwrite是on状态,ztest有lequal和状态,lequal是比当前写入的z轴帧缓冲的值小于或等于,那么就写入,很显然就把墙的那个写进来了,胶囊体没写进来,因此把ztest设成greater,结果发现成这样了,原因很简单,上面的部分只有胶囊体本身,但是大于上部分的z轴的才写进帧缓冲,所以最终没有写进来任何信息
解决方法:写多个pass通道
第一个pass: 第二个pass:
注意第二个ztest是less小于而不是lequal小于等于,第二个blend也可以不写
另一个问题:效果已经实现但是如果前面的墙是个半透明的墙,为什么显示出来的下面的胶囊体的颜色就不是蓝色而是红色的呢?
原因是如果是半透明的墙它的Zwrite为off因此按照第二个pass来处理第二个pass通道ztest 是less返回的颜色是个红色,第一个pass返回的是蓝色,因此最终返回的是红色。
解决方法,用renderType来替换,详细再看下72课时