Unity_Shader高级篇_12.3_后处理_屏幕水波效果
2018-03-29 11:28
573 查看
水波纹的原理其实比较简单,与其他后处理效果一样,vertex shader千篇一律,所有操作都有fragment shader完成。我们仔细观察一下上图中的效果,其实这种波纹并不是叠加上去的,而是波纹位置的图像被向外拉伸了,而这种拉伸的强度是按照类似sin函数的波形进行拉伸的。
(1)新建场景(Scene_12_8)。
(2)新建一个脚本(WaterWave .cs)。并拖拽到摄像机上。
(3)新建一个Unity Shader(Chapter12-WaterWave )。
PS:关于点击屏幕会出现水波位置Y轴反向的问题已经修正。在DX下由于uv纹理坐标与GL下Y轴反向,Unity会为我们处理大部分情况,但是当开启后处理,并且使用了抗锯齿的时候,直接从外界传来的屏幕空间坐标转化到输入的RT中时,Unity自然不会为我们处理得这么详尽,就可能出现想要的效果Y方向上反向的问题。所以Unity提供了一个#if UNITY_UV_STARTS_AT_TOP宏,我们在shader中增加这个编译宏,就可以了。关于#if UNITY_UV_STARTS_AT_TOP宏,上篇文章已经给了完美的解释了。。
(1)新建场景(Scene_12_8)。
(2)新建一个脚本(WaterWave .cs)。并拖拽到摄像机上。
(3)新建一个Unity Shader(Chapter12-WaterWave )。
using UnityEngine; using System.Collections; public class WaterWave : PostEffectsBase { public Shader bloomShader; private Material bloomMaterial = null; public Material material { get { bloomMaterial = CheckShaderAndCreateMaterial(bloomShader, bloomMaterial); return bloomMaterial; } } //距离系数 public float distanceFactor = 60.0f; //时间系数 public float timeFactor = -30.0f; //sin函数结果系数 public float totalFactor = 1.0f; //波纹宽度 public float waveWidth = 0.3f; //波纹扩散的速度 public float waveSpeed = 0.3f; private float waveStartTime; private Vector4 startPos = new Vector4(0.5f, 0.5f, 0, 0); void OnRenderImage(RenderTexture source, RenderTexture destination) { //计算波纹移动的距离,根据enable到目前的时间*速度求解 float curWaveDistance = (Time.time - waveStartTime) * waveSpeed; //设置一系列参数 material.SetFloat("_distanceFactor", distanceFactor); material.SetFloat("_timeFactor", timeFactor); material.SetFloat("_totalFactor", totalFactor); material.SetFloat("_waveWidth", waveWidth); material.SetFloat("_curWaveDis", curWaveDistance); material.SetVector("_startPos", startPos); Graphics.Blit(source, destination, material); } void Update() { if (Input.GetMouseButton(0)) { Vector2 mousePos = Input.mousePosition; //将mousePos转化为(0,1)区间 startPos = new Vector4(mousePos.x / Screen.width, mousePos.y / Screen.height, 0, 0); waveStartTime = Time.time; } } }
Shader "Custom/Chapter12-WaterWave" { Properties { _MainTex("Base (RGB)", 2D) = "white" {} } CGINCLUDE #include "UnityCG.cginc" uniform sampler2D _MainTex; float4 _MainTex_TexelSize; uniform float _distanceFactor; uniform float _timeFactor; uniform float _totalFactor; uniform float _waveWidth; uniform float _curWaveDis; uniform float4 _startPos; fixed4 frag(v2f_img i) : SV_Target { //DX下纹理坐标反向问题 #if UNITY_UV_STARTS_AT_TOP if (_MainTex_TexelSize.y < 0) _startPos.y = 1 - _startPos.y; #endif //计算uv到中间点的向量(向外扩,反过来就是向里缩) float2 dv = _startPos.xy - i.uv; //按照屏幕长宽比进行缩放 dv = dv * float2(_ScreenParams.x / _ScreenParams.y, 1); //计算像素点距中点的距离 float dis = sqrt(dv.x * dv.x + dv.y * dv.y); //用sin函数计算出波形的偏移值factor //dis在这里都是小于1的,所以我们需要乘以一个比较大的数,比如60,这样就有多个波峰波谷 //sin函数是(-1,1)的值域,我们希望偏移值很小,所以这里我们缩小100倍,据说乘法比较快,so... float sinFactor = sin(dis * _distanceFactor + _Time.y * _timeFactor) * _totalFactor * 0.01; //距离当前波纹运动点的距离,如果小于waveWidth才予以保留,否则已经出了波纹范围,factor通过clamp设置为0 float discardFactor = clamp(_waveWidth - abs(_curWaveDis - dis), 0, 1) / _waveWidth; //归一化 float2 dv1 = normalize(dv); //计算每个像素uv的偏移值 float2 offset = dv1 * sinFactor * discardFactor; //像素采样时偏移offset float2 uv = offset + i.uv; return tex2D(_MainTex, uv); } ENDCG SubShader { Pass { ZTest Always Cull Off ZWrite Off Fog{ Mode off } CGPROGRAM #pragma vertex vert_img #pragma fragment f 4000 rag #pragma fragmentoption ARB_precision_hint_fastest ENDCG } } Fallback off }
PS:关于点击屏幕会出现水波位置Y轴反向的问题已经修正。在DX下由于uv纹理坐标与GL下Y轴反向,Unity会为我们处理大部分情况,但是当开启后处理,并且使用了抗锯齿的时候,直接从外界传来的屏幕空间坐标转化到输入的RT中时,Unity自然不会为我们处理得这么详尽,就可能出现想要的效果Y方向上反向的问题。所以Unity提供了一个#if UNITY_UV_STARTS_AT_TOP宏,我们在shader中增加这个编译宏,就可以了。关于#if UNITY_UV_STARTS_AT_TOP宏,上篇文章已经给了完美的解释了。。
相关文章推荐
- Unity Shader-后处理:屏幕水波效果
- Unity Shader入门精要学习笔记 - 第12章 屏幕后处理效果
- Unity_Shader高级篇_15_Unity Shader入门精要_水波效果
- UnityShader屏幕后处理-Bloom效果(朦胧模糊)
- Unity shader学习之屏幕后期处理效果之边缘检测
- UnityShader高级篇——Bloom效果
- 在Unity的后处理shader中通过屏幕像素坐标和深度贴图反推世界坐标
- unity使用屏幕后处理实现闪烁特效,创建新的shader文件过程
- UnityShader高级篇——调整屏幕亮度、饱和度、对比度
- UnityShader屏幕后处理-边缘检测,经典的插值lerp
- Unity中基于屏幕后处理的彩色与黑白渐变效果
- UnityShader屏幕后处理
- Unity&Shader案例篇—屏幕渐暗效果
- Unity&Shader案例篇—屏幕渐暗效果
- UnityShader屏幕后处理-高斯模糊
- Unity Shader 学习笔记(28) 噪声纹理、消融效果、水波效果、噪声雾效
- Unity Shader-后处理:时空扭曲效果
- Unity Shader-后处理:径向模糊效果
- Unity_Shader高级篇_15_Unity Shader入门精要_消融效果
- unity shader 固定管线实例(六) 透明度测试剔除尖锐边缘的模糊处理