这个泡沫效果来自远古时代的Unity官方海岛Demo, 原效果直接复制3个材质球在js脚本中做UV动画偏移,这里尝试在shader中做动画并且一个pass中完成:

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

//岸边浪花泡沫
//CloudLty 2016-9-6
Shader "Custom/foams2"
{
Properties//标记所以外部变量,让该变量按标记显示在编辑器中
{
_TintColor ("Tint Color (RGBA)", Color) = (1,1,1,1)
_MainTex ("Texture (RGB)", 2D) = "white" {}
_Mask ("Mask", 2D) = "white" {}
_AlphaDelay ("Alpha Delay", Range(-1,1)) = 0
_Speed ("Time Scale", Range(0,1)) = 0.25
_WaveRange ("Wave Range", Range(-1,1)) = 0.6
_Layer1OffsetX ("Layer1 Offset X", Range(-2,2)) = 0
_Layer2OffsetX ("Layer2 Offset X", Range(-2,2)) = 0
_Layer3OffsetX ("Layer3 Offset X", Range(-2,2)) = 0
_Layer1OffsetY ("Layer1 Offset Y", Range(-2,2)) = 0
_Layer2OffsetY ("Layer2 Offset Y", Range(-2,2)) = 0
_Layer3OffsetY ("Layer3 Offset Y",Range(-2,2)) = 0 }
SubShader
{
Tags
{
"Queue" = "Transparent"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
}
LOD 100 Pass
{
ZWrite off
Blend srcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert //顶点着色器 类似于宏定义,告诉Unity这个函数名是顶点做色器函数
#pragma fragment frag //片段着色器 #include "UnityCG.cginc" //类似头文件?主要是Untiy提供的一些常用函数 貌似不写编译时也会自动包含进来 //顶点着色器输入结构体
struct appdata
{
float4 vertex : POSITION; //POSITION输入语义,Unity将顶点坐标提交于此变量
float4 uv : TEXCOORD0; //TEXCOORD0,Unity将模型第一套UV提交于此变量
}; //顶点着色器输出结构体 (反正会给片段做色器使用)
struct v2f
{
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;//输出语义
float4 uv1 : TEXCOORD0;
float4 uv2 : TEXCOORD1;
float4 uv3 : TEXCOORD2;
float2 uv4 : TEXCOORD3;
}; //外部变量声明
uniform sampler2D _MainTex;
uniform float4 _MainTex_ST;
uniform sampler2D _Mask;
uniform float4 _Mask_ST;
uniform half4 _TintColor;
uniform float _AlphaDelay;
uniform float _Speed;
uniform float _WaveRange;
uniform float _Layer1OffsetX;
uniform float _Layer2OffsetX;
uniform float _Layer3OffsetX;
uniform float _Layer1OffsetY;
uniform float _Layer2OffsetY;
uniform float _Layer3OffsetY; //UV动画函数
float2 DelayOffsetUV(float2 uv, float offset, float offset_y)//输入UV 和偏移量(x,y),外部变量控制速度,范围
{
float pi = 3.1415926536f;
float sintime = sin(_Time.y * _Speed * pi + offset * 0.5f * pi);//余弦函数使UV来回移动,
float u = (sintime + 1) * 0.5f * _WaveRange + (1 - _WaveRange);
uv.x += u;
uv.y += offset_y;
return uv;
} //顶点着色器
v2f vert(appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex); //逐层偏移
float2 inuv = v.uv;
// layer1 uv offset
float2 uv_tex1 = DelayOffsetUV(inuv, _Layer1OffsetX, _Layer1OffsetY);
o.uv1.xy = TRANSFORM_TEX(uv_tex1, _MainTex); // layer1 uv offset
float2 uv_tex2 = DelayOffsetUV(inuv, _Layer2OffsetX, _Layer2OffsetY);
o.uv1.zw = TRANSFORM_TEX(uv_tex2, _MainTex); // layer1 uv offset
float2 uv_tex3 = DelayOffsetUV(inuv, _Layer3OffsetX, _Layer3OffsetY);
o.uv2.xy = TRANSFORM_TEX(uv_tex3, _MainTex); //每一层的Mask(透贴)偏移,偏移量与tex一致,并可以用_AlphaDelay微调
// mask1 uv offset
float2 uv_mask1 = DelayOffsetUV(inuv, _Layer1OffsetX - _AlphaDelay, _Layer1OffsetY);
o.uv2.zw = TRANSFORM_TEX(uv_mask1, _Mask); // mask2 uv offset
float2 uv_mask2 = DelayOffsetUV(inuv, _Layer2OffsetX - _AlphaDelay, _Layer2OffsetY);
o.uv3.xy = TRANSFORM_TEX(uv_mask2, _Mask); // mask3 uv offset
float2 uv_mask3 = DelayOffsetUV(inuv, _Layer3OffsetX - _AlphaDelay, _Layer3OffsetY);
o.uv3.zw = TRANSFORM_TEX(uv_mask3, _Mask); UNITY_TRANSFER_FOG(o,o.vertex); o.uv4 = inuv;
return o;
} //获取泡沫逐渐出现,向岸边移动,开始折返并逐渐消失的透明度值
fixed GetDisappearAlpha(float delay)
{
float PI = 3.1415926536f;
float t = _Time.y *_Speed * PI + delay * 0.5* PI + 1.2 * PI;
fixed a = (sin(t)+1)*0.5;
return a*a;
} //将两层半透明的颜色合并,获取合并后的RGBA
fixed4 TwoColorBlend(fixed4 c1, fixed4 c2)
{
fixed4 c12;
c12.a = c1.a + c2.a - c1.a * c2.a;
c12.rgb = (c1.rgb * c1.a * (1 - c2.a) + c2.rgb * c2.a) / c12.a;
return c12;
} //片段着色器
fixed4 frag(v2f i) : SV_Target //参数为输入结构体,语义就是输出到什么地方
{
fixed pi = 3.1415926536f; //get rgb
fixed4 c1 = tex2D(_MainTex, i.uv1.xy);
fixed4 c2 = tex2D(_MainTex, i.uv1.zw);
fixed4 c3 = tex2D(_MainTex, i.uv2.xy); //get alpha
c1.a = tex2D(_Mask, i.uv2.zw) * GetDisappearAlpha(_Layer1OffsetX);
c2.a = tex2D(_Mask, i.uv3.xy) * GetDisappearAlpha(_Layer2OffsetX);
c3.a = tex2D(_Mask, i.uv3.zw) * GetDisappearAlpha(_Layer3OffsetX); //layer1 + layer2
fixed4 c12 = TwoColorBlend(c1,c2);
//layer12 + layer3
fixed4 c123 = TwoColorBlend(c12,c3); return c123 * _TintColor;
}
ENDCG
}
}
}

Unity Shader学习笔记 - 用UV动画实现沙滩上的泡沫的更多相关文章

  1. Unity Shader学习笔记-1

    本篇文章是对Unity Shader入门精要的学习笔记,插图大部分来自冯乐乐女神的github 如果有什么说的不正确的请批评指正 目录 渲染流水线 流程图 Shader作用 屏幕映射 三角形遍历 两大 ...

  2. 【Unity Shader学习笔记】Unity基础纹理-法线贴图

    1 高度纹理 使用一张纹理改变物体表面法线,为模型提供更多细节. 有两种主要方法: 1.高度映射:使用一张高度纹理(height map)来模拟表面位移(displacement).得到一个修改后的法 ...

  3. 【Unity Shader学习笔记】Unity基础纹理-单张纹理

    1 单张纹理 1.1 纹理 使用纹理映射(Texture Mapping)技术,我们把一张图片逐纹素(Texel)地控制模型的颜色. 美术人员建模时,会在建模软件中利用纹理展开技术把纹理映射坐标(Te ...

  4. 【Unity Shader学习笔记】Unity基础纹理-渐变纹理

    纹理可以用来存储任何表面属性. 可以通过使用渐变纹理来实现插画风格的渲染效果. 这项技术是由Valve公司提出的.Valve使用它来渲染游戏中具有插画风格的角色. 我们使用半兰伯特模型计算漫反射. 因 ...

  5. Unity Shader 学习笔记(一)

    _MainTex_ST (1)简单来说,TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)主要作用是拿顶点的uv去和材质球的t ...

  6. 【Unity Shader学习笔记】Unity光照基础-高光反射

    1.原理 1.1.Phong模型 计算高光反射需要表面法线.视角方向.光源方向.反射方向等. 在这四个矢量中,我们实际上只需要知道其中3个矢量即可,而第4个矢量(反射方向r)可以通过其他信息计算得到: ...

  7. 【Unity Shader学习笔记】Unity光照基础-半兰伯特光照

    在光照无法达到的区域,模型的外观通常是全黑的,没有任何明暗变化,这会使模型的背光区域看起来就像一个平面. 使用半兰伯特光照可以解决这个问题. 逐顶点光照技术也被称为兰伯特光照模型.因为它符合兰伯特定律 ...

  8. 【Unity Shader学习笔记】Unity光照基础-漫反射光照

    本代码只适用于平行光. 1.逐顶点漫反射光照 1.1漫反射光照原理 1.2代码实现 在Properties语义块中声明一个漫反射颜色属性 Properties { //漫反射参数,用于调整漫反射效果 ...

  9. unity shader学习笔记(1) shader基础结构以及Properties面板

    首先是shader的基础结构: Shader "Custom/Example { Properties//变量属性面板 { } SubShader { Tags { "Render ...

随机推荐

  1. STC12LE5620AD RAM问题

    1.此款单片机内部有 sram:768B=512B(aux)+256B(Internal) 2.内部RAM解析 2. 3.内部扩展RAM 4.keil中可以选择内存类型 5. 网上摘抄的一段话: 在S ...

  2. LeetCode21.合并两个有序链表 JavaScript

    将两个有序链表合并为一个新的有序链表并返回.新链表是通过拼接给定的两个链表的所有节点组成的. 示例: 输入:1->2->4, 1->3->4 输出:1->1->2- ...

  3. Python书单

    gitbook.jb51 1.Python基础教程 2.流畅的Python:总有论坛的人吐槽它翻译的还是不太友好,其实真正的差别没有那么大,重要的还是有所收获 3.<Python进阶>译本 ...

  4. JavaScript变量声明及赋值

    1.变量声明 var a; //声明一个变量 a var b,c,d; //同时申明多个变量时,变量名之间用逗号隔开 console.log(a); //在控制台显示变量a的值,输出为undefine ...

  5. 二维码生成(QRCode.js)

    什么是 QRCode.js? QRCode.js 是一个用于生成二维码的 JavaScript 库.主要是通过获取 DOM 的标签,再通过 HTML5 Canvas 绘制而成,不依赖任何库. 基本用法 ...

  6. webuploader实现上传视频

    之前有人让我做一个webuploader上传视频,但是一直没有时间,现在抽出了时间来.来完成以下这个简单的demo 第一步,上传视频和上传 图片有什么区别么? 其实是没有的,因为执行的操作都是上传,所 ...

  7. 红帽RHEL6.8离线环境下升级到RHEL7.3

    Red Hat Enterprise Linux 7 (RHEL 7) 是第一个支持从前一个 RHEL 主发行版本(RHEL 6)进行原位(in-place)升级的 RHEL 主版本.原位升级(in- ...

  8. jQuery实现简单的拼图游戏

    一,实现拼图的搭建: <div class="box"> <table id="table1" class="mytable&quo ...

  9. Linux中Elasticsearch集群部署

    1.下载安装包elasticsearch-6.3.1  安装包自己下载,网上很多 2.安装位置在cd /usr/local/elasticsearch/目录下 3.因为ES使用root权限运行会报错, ...

  10. redis之闪电内幕

    一.简介和应用 二.Redis的对象redisObject 三.String 四.List 4.1 linkedlist(双端链表) 4.2 ziplist(压缩列表) 五.Hash 六.Set 七. ...