Unity Shader - 水体交互_unity 水体-程序员宅基地

技术标签: Unity Shader  unity  Water Shader  水体交互  

水体交互

水体交互效果在游戏中是一个很常见的需求,这里简单实现一个可交互的水体。
本篇文章主要是介绍水体交互的实现思路,水体的渲染这里就不再详细介绍,网上很多关于水体的渲染方法很多,可以自己百度、Google了解一下,这里不会过多提及。

效果图。

先放一张最终的GIF效果图!

TePdxK.gif

实现思路

原理其实非常简单,就是通过粒子系统不断发射带有波纹法线贴图的面片,然后把这些法线渲染一张RenderTexture传输到Water Shader中,然后和Water Normal 叠加即可形成水波效果。

实现步骤可以简单分为:

  1. 简单的水体渲染
  2. 渲染水波法线RT
  3. 叠加法线

一、简单的水体渲染

这里的水体渲染采用简单的法线干扰实现,参考冯乐乐女神的《Unity Shader入门精要》里的水体渲染。

水的效果:
Teovg1.gif

这里深水和潜水区的过渡是直接用场景深度值水面深度值差值, 差值越接近0,就越接近浅滩区。
获取场景深度图需要开启 DepthModel: GetComponent<Camera>().depthTextureMode = DepthTextureMode.Depth;

Shader代码:

//frag:

float2 screenPos = i.screenPos.xy/i.screenPos.w;
// 获取屏幕深度
half existingDepth01 = tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(i.screenPos)).r;
half existingDepthLinear = LinearEyeDepth(existingDepth01);
half depthDifference = existingDepthLinear - i.screenPos.w;
// 深水和潜水颜色做插值
half waterDepthDifference01 = saturate(depthDifference / _DepthMaxDistance);
float4 waterColor = lerp(_ShallowColor, _DeepColor, waterDepthDifference01);

二、渲染水波法线的RenderTexture

1.首先在场景创建一个Camera,该Camera只渲染特定的Layer,即水波法线,Culling Mask 设置为WaterWave,Clear Flags设置为Slid Color,Background设置为黑色,并且位置旋转都设置为和MainCamer一致。并且创建一个RenderTexture,拖拽到Target Texture上。

TZTDYj.png

2.创建一个Shader,命名为WaterRing,该Shader用于渲染水波法线。

3.继续创建一个粒子系统,材质Shader设置为刚才创建的WaterRing Shader,并且该粒子的Layer需要修改为WaterWave

水波法线渲染:

水波法线的Shader可以非常简单,直接渲染一张环状的法线贴图即可。

但是这里为了可以更方便的调整水波法线的一些细节就采用动态计算的方式来渲染。

这里计算法线是通过ddx ddy的方式来计算,为了得到法线首先肯定需要知道高度差,那么我们可以先渲染一个环状的高度图,
这里就可以通过两个smoothstep相减得到一个较为平滑的环状高度。

效果如下:
TZbX7T.png

Shader代码:

fixed doubleSmoothstep(float4 uv)
{
    float dis = distance(uv, 0.5);
    float halfWidth = _RingWidth * 0.5;
    float range = _RingRange;
    float smoothness = _RingSmoothness;
    float threshold1 = range - halfWidth;
    float threshold2 = range + halfWidth;

    float value = smoothstep(threshold1, threshold1 + smoothness, dis);
    float value2 = smoothstep(threshold2, threshold2 + smoothness, dis);
    
    return value - value2;
}

fixed4 frag(v2f i) : SV_Target
{
    fixed normalCenter = doubleSmoothstep(i.uv);
	return fixed4(normalCenter,normalCenter,normalCenter,1);
}

有了高度差就可以计算出法线了:

TZqyUU.png

Shader代码:

float normalCenter = doubleSmoothstep(i.uv);
// 波纹法线
float color0 = doubleSmoothstep(i.uv + half4(-1, 0, 0, 0) * 0.004);
float color1 = doubleSmoothstep(i.uv + half4(1, 0, 0, 0) * 0.004);
float color2 = doubleSmoothstep(i.uv + half4(0, -1, 0, 0) * 0.004);
float color3 = doubleSmoothstep(i.uv + half4(0, 1, 0, 0) * 0.004);

float2 ddxy = float2(color0 - color1, color2 - color3);
float3 normal = float3((ddxy * _BumpPower), 1.0);
normal = normalize(normal);
float4 finalColor = float4((normal * 0.5 + 0.5) * normalCenter * i.color.a, normalCenter * i.color.a);
return finalColor;

这里通过ddx ddy得到了法线后,需要把法线从[-1,1]映射到[0,1]范围(normal * 0.5 + 0.5)。

此时我们就可以通过参数动态调整该环状法线的宽度、强度、范围。

最后把该材质赋值给粒子,并且通过调整粒子参数使粒子随着生命周期逐渐变大、顶点色的A通道也跟随生命周期变化来控制透明度和强度。

此时如果不出意外的话可以看到RT是这样的。

TZjVsA.png

三、叠加法线

最后一步就是把之前渲染得到的RT传递到Water Shader中,通过屏幕坐标采样得到水波法线,然后把值从[0,1]映射到[-1,1]范围(normal * 2-1),然后和水的法线叠加即可。

屏幕坐标可以由ComputeGrabScreenPos计算得到。

Shader代码:

float4 ringColor = tex2D(_RingTex, screenPos);
float3 ringNormal = UnpackNormal(ringColor).rgb;
ringNormal = mul(float3x3(i.TtoW0.xyz,i.TtoW1.xyz,i.TtoW2.xyz),ringNormal);
ringNormal = normalize(ringNormal) * ringColor.a * _RingPower;
// float3 normal = BlendNormals(ringNormal,waterNormal);
float3 normal = normalize(waterNormal+ringNormal);

效果如下:

TZxluj.png

最后再结合粒子即可实现一个动态的水波扩散的效果。

TeP0KO.gif
TePdxK.gif

完整工程源码: https://github.com/csdjk/LearnUnityShader

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_28299311/article/details/122026679

智能推荐

jQuery 个人之前的笔记_jquery详细笔记-程序员宅基地

文章浏览阅读2.7k次,点赞3次,收藏5次。jQuery 基础篇概述jQuery是一款优秀的JavaScript库 ,从命名可以看出jQuery最主要的用途是用来做查询(iQuery=js+Query) ,正如jQuery官方Logo副标题所说(write less, domore)使用jQuery能 上我们对HTML文档遍历和操作、事件处理、动画以及Ajax变得更加简单入门和原生JS区别1、原生JS: 等DOM元素加载完毕,并且图片也加载完毕才会执行 编写多个入口函数,后面会覆盖前面2、jQuery 等Dom元素加载完毕,但_jquery详细笔记

C++实现Delaunay三角网生长算法_增量法生成delaunay三角网-程序员宅基地

文章浏览阅读8.4k次,点赞25次,收藏142次。一、概述1.1 三角网的介绍三角网是由一系列连续三角形构成的网状的平面控制图形,是三角测量中布设连续三角形的两种主要扩展形式,同时向各方向扩展而构成网状.适用于地势起伏大,通视条件比较好的场地。三角网是实现地形三维可视化,数字地面模型(Digital Terrain Model,简称DTM)是一种很有效的途径。DTM主要是由栅格和不规则三角网(Triangulated Irregular Network,简称TIN)两种数据格式来表示,相比于栅格TIN具有许多..._增量法生成delaunay三角网

TCGA数据下载和整理工具----GDCRNATools_gdcrnatools软件包进行差异基因分析-程序员宅基地

文章浏览阅读1.9w次,点赞7次,收藏62次。TCGA数据下载和整理的网站及软件发表很多了,比如Broad GDAC Firehose, Oncomine, TCGAbiolinks,TCGA-Assembler, TCGA2STAT,RTCGAToolbox等等,这些网站或软件要么使用的是TCGA更新前的数据,要么运行起来比较繁琐。当然各个工具都有其优势所在。之前在论坛里分享了自己下载和整理TCGA数据的Python代码。最近忙里偷_gdcrnatools软件包进行差异基因分析

win7更改计算机时间,win7系统自动更改日期时间是怎么回事-程序员宅基地

文章浏览阅读1.9k次。工具/原料硬件:计算机操作系统:Windows7方法/步骤1.Windows7系统不能更改日期和时间的解决方法2.在本地组策略编辑器窗口,展开Windows设置 - 安全设置 - 本地策略;3.在本地策略中找到:用户权限分配,左键点击:用户权限分配,在用户权限分配对应的右侧窗口找到:更改系统时间,并左键双击:更改系统时间;4.在打开的更改系统时间 属性窗口,我们点击:添加用户或组(U);5.在选择..._win7系统时间老是自己跳变

Python-Django-模型_pycharm怎么创建orm模型-程序员宅基地

文章浏览阅读1k次。一、ORM 模型介绍1 、 ORM 模型对象关系映射(英语:(Object Relational Mapping,简称ORM,或ORM,或OR mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。面向对象是从软件工程基本原则(如耦合、聚合、封装)的基础上发展起来的,而关系数据库则是从数学理论发展而来的,两套理论存在显著的区别。为了解决这个不匹配的现象,对象关系映射技术应运而生。对象关系映射(Object-Relational Mapping)提供了概念性的、_pycharm怎么创建orm模型

如何搭建一套完整的智能安防视频监控平台?关于设备与软件选型的几点建议_前端摄像头的选型依据-程序员宅基地

文章浏览阅读250次。球机摄像头:球机为一体化设备,可以通过云台控制进行转动、变倍和自动聚焦等操作,若需要对设备周边切换场景监控,如大门口、户外活动场所等,可以选择球机。_前端摄像头的选型依据

随便推点

华为p8升级android8系统资源,华为新系统广受好评 目前EMUI10升级用户数已破亿-程序员宅基地

文章浏览阅读844次。华为消费者BG软件部总裁王成录昨日宣布,升级EMUI10的用户数已经突破1亿,涵盖35款机型。该数据不但充分展现了华为手机庞大的用户基数,也体现了华为在系统升级方面所付出的努力,正得到众多用户的肯定与支持。确定 时延引擎 与方舟编译器,解决安卓卡顿问题安卓手机曾经为人所诟病的一点要数“卡顿”,手机越用越慢,严重影响着安卓用户的用机体验。四年前,随着提出“天生快、一生快”标语的EMUI5.0发布,华..._华为p8最新系统

微服务架构,这一篇就够了!-程序员宅基地

文章浏览阅读1.9k次。所有的微服务都是独立的Java进程跑在独立的虚拟机上,所以服务间的通信就是IPC(inter process communication),已经有很多成熟的方案。原来的Monolithic方式开发,所有的服务都是本地的,UI可以直接调用,现在按功能拆分成独立的服务,跑在独立的一般都在独立的虚拟机上的 Java进程了。它通常不依赖其他服务。后台有N个服务,前台就需要记住管理N个服务,一个服务下线/更新/升级,前台就要重新部署,这明显不服务我们 拆分的理念,特别当前台是移动应用的时候,通常业务变化的节奏更快。_微服务架构

主键索引和非主键索引的区别-程序员宅基地

文章浏览阅读871次。总的来说,主键索引是表的唯一标识索引,具有唯一性和快速访问的特点;而非主键索引可以提供更多的灵活性和覆盖更多的查询场景,但可能性能略低于主键索引。_主键索引和非主键索引的区别

linux启动进入bios设置密码,通过bios怎么设置开机密码-程序员宅基地

文章浏览阅读1.2k次。电脑不想被他人乱动,来设置下BIOS管理员密码和开机密码,就让学习啦小编来告诉大家通过bios怎么设置开机密码的方法吧,希望对大家有所帮助。通过bios设置开机密码方法计算机开机以后,按键盘的Delete键进入BIOS的设置画面,如下图所示。因为开机可以按Delete键进入设置画面的时间很短,您可以在计算机一开机就慢慢的重复按Delete键,以免错过进入设置画面又要重新再开机。按键盘向下箭头键移到..._bios开机密码 画面

批处理获取所有文件、文件夹名字_bat获取文件夹下所有文件名和文件夹名称-程序员宅基地

文章浏览阅读1.6w次,点赞14次,收藏45次。已收藏下面这个链接的方法也不错excel批处理技巧:如何制作文件档案管理系统excel批处理技巧:如何制作文件档案管理系统http://www.360doc.com/content/18/0913/13/18781560_786337463.shtml有时候我们整理文件的时候需要列出文件夹里面所有的文件名或者文件夹名,生成一个文件目录,一个个重命名然后复制到word或者记事本的方法显示有点太繁琐了。网上有一些自动生成文件目录的程序,比如我之前一直在用的DirIndex.exe。但最近我发现_bat获取文件夹下所有文件名和文件夹名称

计算机视觉图像检测之从EasyDL到BML_easydl paddlex bml-程序员宅基地

文章浏览阅读914次,点赞18次,收藏18次。部署方式选择公有云部署,训练方式均可。增量训练的意思是在之前训练的模型基础上再次进行训练,如果事先没有进行过训练,这一项为不可选中状态。回到Postman,参数栏按如下方式填写,其中第一个KEY-VALUE值直接照写,client_id和client_secret的VALUE值分别为上一步获取的AK、SK。如果数据集质量够高,每种标签标注效果都很好,也可以在模型训练时再进行数据增强,或者直接跳过这一步。在导入界面配置导入信息,选择本地导入,导入压缩包(其他导入方式请自行测试),如图1.1.2。_easydl paddlex bml