unity屏幕shader之水屏幕
2016-03-09 20:55
453 查看
本篇博客仅仅供本人参考学习,转载自浅墨shader。
首先创建一个顶点片段shader,将内容修改如下:
首先创建一个顶点片段shader,将内容修改如下:
Shader "Custom/waterCamera" { Properties { //主纹理 _MainTex("Base (RGB)",2D)="white"{} //屏幕水滴的素材图 _ScreenWaterDropTex("Base (RGB)",2D)="white"{} //当前时间 _CurTime("Time",Range(0.0,1.0))=1.0 //X坐标上的水滴尺寸 _SizeX("SizeX",Range(0.0,1.0))=1.0 //Y坐标上的水滴尺寸 _SizeY("SizeY",Range(0.0,1.0))=1.0 //水滴的流动速度 _DropSpeed("Speed",Range(0.0,10.0))=1.0 //溶解度 _Distortion("_Distortion",Range(0.0,1.0))=0.87 } SubShader { Pass { //设置深度测试模式:渲染所有像素.等同于关闭透明度测试(AlphaTest Off) ZTest Always //===========开启CG着色器语言编写模块=========== CGPROGRAM //编译指令:告知编译器顶点和片段着色函数的名称 #pragma vertex vert #pragma fragment frag //添加选项到编译的OpenGL 片段程序。 #pragma fragmentoption ARB_precision_hint_fastest //编译指令: 指定着色器编译目标为Shader Model 3.0 #pragma target 3.0 //包含辅助CG头文件 #include "UnityCG.cginc" //外部变量的声明 uniform sampler2D _MainTex; uniform sampler2D _ScreenWaterDropTex; uniform float _CurTime; uniform float _DropSpeed; uniform float _SizeX; uniform float _SizeY; uniform float _Distortion; uniform float2 _MainTex_TexelSize; //顶点输入结构 struct vertexInput { float4 vertex : POSITION;//顶点位置 float4 color : COLOR;//颜色值 float2 texcoord : TEXCOORD0;//一级纹理坐标 }; //顶点输出结构 struct vertexOutput { half2 texcoord:TEXCOORD0; //一级纹理坐标 float4 vertex : SV_POSITION; //像素位置 fixed4 color:COLOR; //颜色值 }; //--------------------------------【顶点着色函数】----------------------------- // 输入:顶点输入结构体 // 输出:顶点输出结构体 //--------------------------------------------------------------------------------- vertexOutput vert(vertexInput Input) { //【1】声明一个输出结构对象 vertexOutput Output; //【2】填充此输出结构 //输出的顶点位置为模型视图投影矩阵乘以顶点位置,也就是将三维空间中的坐标投影到了二维窗口 Output.vertex=mul(UNITY_MATRIX_MVP,Input.vertex); //输出的纹理坐标也就是输入的纹理坐标 Output.texcoord=Input.texcoord; //输出的颜色值也就是输入的颜色值 Output.color=Input.color; //【3】返回此输出结构对象 return Output; } //--------------------------------【片段着色函数】----------------------------- // 输入:顶点输出结构体 // 输出:float4型的颜色值 //--------------------------------------------------------------------------------- fixed4 frag(vertexOutput Input):COLOR { //【1】获取顶点的坐标值 float2 uv = Input.texcoord.xy; //【2】解决平台差异的问题。校正方向,若和规定方向相反,则将速度反向并加1 #if UNITY_UV_STARTS_AT_TOP if (_MainTex_TexelSize.y < 0) _DropSpeed = 1 - _DropSpeed; #endif //【3】设置三层水流效果,按照一定的规律在水滴纹理上分别进行取样 float3 rainTex1 = tex2D(_ScreenWaterDropTex,float2(uv.x * 1.15 * _SizeX,(uv.y*_SizeY * 1.1)+_CurTime*_DropSpeed*0.15)).rgb/_Distortion; float3 rainTex2 = tex2D(_ScreenWaterDropTex,float2(uv.x*1.25*_SizeX-0.1,(uv.y*_SizeY*1.2)+_CurTime*_DropSpeed*0.2)).rgb/_Distortion; float3 rainTex3=tex2D(_ScreenWaterDropTex,float2(uv.x*0.9*_SizeX,(uv.y*_SizeY*1.25)+_CurTime*_DropSpeed*0.032)).rgb/_Distortion; //【4】整合三层水流效果的颜色信息,存于finalRainTex中 float2 finalRainTex=uv.xy-(rainTex1.xy-rainTex2.xy-rainTex3.xy)/3; //【5】按照finalRainTex的坐标信息,在主纹理上进行采样 float3 finalColor = tex2D(_MainTex, float2(finalRainTex.x, finalRainTex.y)).rgb; //【6】返回加上alpha分量的最终颜色值 return fixed4(finalColor, 1.0); } //===========结束CG着色器语言编写模块=========== ENDCG } } FallBack "Diffuse" }接着创建一个脚本挂在摄像机上,如下:
using UnityEngine; using System.Collections; [ExecuteInEditMode] public class WaterScreen : MonoBehaviour { //-------------------变量声明部分------------------- #region Variables //着色器和材质实例 public Shader CurShader; // 着色器实例 private Material CurMaterial; //当前的材质 //时间变量和素材图的定义 private float TimeX = 1.0f; //时间变量 private Texture2D ScreenWaterDropTex; //屏幕水滴的素材图 //可以再编辑器中调整的参数值 [Range(5, 64), Tooltip("溶解度")] public float Distortion = 8.0f; [Range(0, 7), Tooltip("水滴在X坐标上的尺寸")] public float SizeX = 1f; [Range(0, 7), Tooltip("水滴在Y坐标上的尺寸")] public float SizeY = 0.5f; [Range(0, 10), Tooltip("水滴的流动速度")] public float DropSpeed = 3.6f; //用于参数调节的中间变量 public static float ChangeDistortion; public static float ChangeSizeX; public static float ChangeSizeY; public static float ChangeDropSpeed; #endregion //-------------------------材质的get&set---------------------------- #region MaterialGetAndSet Material material { get { if (CurMaterial == null) { CurMaterial = new Material(CurShader); CurMaterial.hideFlags = HideFlags.HideAndDontSave; } return CurMaterial; } } #endregion //-----------------------------------------【Start()函数】--------------------------------------------- // 说明:此函数仅在Update函数第一次被调用前被调用 //-------------------------------------------------------------------------------------------------------- void Start() { //依次赋值 ChangeDistortion = Distortion; ChangeSizeX = SizeX; ChangeSizeY = SizeY; ChangeDropSpeed = DropSpeed; //载入素材图 ScreenWaterDropTex = Resources.Load("ScreenWaterDrop") as Texture2D; //找到当前的Shader文件 CurShader = Shader.Find("Custom/waterCamera"); //判断是否支持屏幕特效 if (!SystemInfo.supportsImageEffects) { enabled = false; return; } } //-------------------------------------【OnRenderImage()函数】------------------------------------ // 说明:此函数在当完成所有渲染图片后被调用,用来渲染图片后期效果 //-------------------------------------------------------------------------------------------------------- void OnRenderImage(RenderTexture sourceTexture, RenderTexture destTexture) { //着色器实例不为空,就进行参数设置 if (CurShader != null) { //时间的变化 TimeX += Time.deltaTime; //时间大于100,便置0,保证可以循环 if (TimeX > 100) TimeX = 0; //设置Shader中其他的外部变量 material.SetFloat("_CurTime", TimeX); material.SetFloat("_Distortion", Distortion); material.SetFloat("_SizeX", SizeX); material.SetFloat("_SizeY", SizeY); material.SetFloat("_DropSpeed", DropSpeed); material.SetTexture("_ScreenWaterDropTex", ScreenWaterDropTex); //拷贝源纹理到目标渲染纹理,加上我们的材质效果 Graphics.Blit(sourceTexture, destTexture, material); } //着色器实例为空,直接拷贝屏幕上的效果。此情况下是没有实现屏幕特效的 else { //直接拷贝源纹理到目标渲染纹理 Graphics.Blit(sourceTexture, destTexture); } } //-----------------------------------------【OnValidate()函数】-------------------------------------- // 说明:此函数在编辑器中该脚本的某个值发生了改变后被调用 //-------------------------------------------------------------------------------------------------------- void OnValidate() { ChangeDistortion = Distortion; ChangeSizeX = SizeX; ChangeSizeY = SizeY; ChangeDropSpeed = DropSpeed; } //-----------------------------------------【Update()函数】------------------------------------------ // 说明:此函数在每一帧中都会被调用 //-------------------------------------------------------------------------------------------------------- void Update() { //若程序在运行,进行赋值 if (Application.isPlaying) { //赋值 Distortion = ChangeDistortion; SizeX = ChangeSizeX; SizeY = ChangeSizeY; DropSpeed = ChangeDropSpeed; } //找到对应的Shader文件,和纹理素材 #if UNITY_EDITOR if (Application.isPlaying != true) { CurShader = Shader.Find("Custom/waterCamera"); ScreenWaterDropTex = Resources.Load("ScreenWaterDrop") as Texture2D; } #endif } //-----------------------------------------【OnDisable()函数】--------------------------------------- // 说明:当对象变为不可用或非激活状态时此函数便被调用 //-------------------------------------------------------------------------------------------------------- void OnDisable() { if (CurMaterial) { //立即销毁材质实例 DestroyImmediate(CurMaterial); } } }
相关文章推荐
- Unity3d 游戏汉化之IL注入文本替换--木石世纪
- U3D游戏开发—程序员转型篇(二)unity界面认识
- unity C#预处理器指令
- Unity + SourceTree
- unity3d引擎程序员养成
- [置顶] unity中关于图形学基础知识—矩阵与转换(三)
- 回应UE4 Unity将很快让开发者在虚拟现实里构建虚拟现实
- unity3d调用jar类中的方法和属性
- Unity 依赖注入知识点
- 【Unity开发】NGUI动态刷新ScrollView
- [置顶] unity调用外部摄像头
- 【和我一起学习Unity3D】Unity3D的坐标控制
- Unity3D资源目录及资源读取
- unity 初次制作
- unity选择关卡的跑马灯效果
- 【Unity3D】 面试 笔试题目(一)
- 使用Unity发布第一个程序时遇到的问题
- Unity 你以为SetParent()是个很简单的API???!!
- Unity5新的AssetBundle系统使用心得
- Unity3D ----- 代码控制shader的自发光参数(摄像机黑白特效下)