UnityShader水体渲染
水体渲染
简单水体
- 贴图+UV动画
- 使用一张噪声纹理,采样结果作为UV的偏移值,从而模拟水流动的效果
// sample the texture
fixed4 noise_col = tex2D(_NoiseTex, i.uv + fixed2(_Time.y*_XSpeed, 0));
fixed uOffset = noise_col.r;
fixed vOffset = noise_col.r;
fixed4 col = tex2D(_MainTex, i.uv +_Intensity*fixed2(uOffset, vOffset));
_Intensity
为水流动的强度_XSpeed
为水流动的速度完整代码:https://github.com/kb824999404/Unity_Shader/blob/master/Shader/Test/Water/SimpleWater.shader
水波
- 波纹内部有拉伸效果,随时间变化:用距离中心的长度和时间作为输入,通过三角函数计算拉伸值,
_distanceFactor
为波峰波谷数量,_totalFactor
为最大拉伸强度,_timeFactor
为拉伸强度变化速度float sinFactor = sin(dis * _distanceFactor + _Time.x * _timeFactor) * _totalFactor;
- 波纹从内向外扩散:波纹半径随时间递增,不超过最大半径
_maxWaveDis
,waveWidth
为波纹宽度,如果纹理坐标距离当前波纹运动点的距离超过该值则不拉伸float curWaveDis = frac(_Time.x *_waveSpeed)*_maxWaveDis; //距离当前波纹运动点的距离,如果小于waveWidth才予以保留,否则已经出了波纹范围,factor通过clamp设置为0 float discardFactor = clamp(_waveWidth - abs(curWaveDis - dis), 0, 1);
- 将纹理坐标进行网格细分,使水波随机出现在各个网格内,并且一个扩散周期后再次随机出现,
_GridNum
为细分网格数量,_RippleDensity
为水波密度float2 st=frac(i.uv*_GridNum); //网格内坐标 float2 grid=floor(i.uv*_GridNum); //网格坐标 float2 dv=float2(st.x-0.5,st.y-0.5); float dis=length(dv); //距网格中心距离//使用floor取整,一个水波扩散周期内不变 float flag_change=floor(_Time.x *_waveSpeed); //用网格坐标和flag_change生成随机值,大于_RippleDensity为1,用于判断该网格是否有水波 //这样水波随机出现在各个网格内,且一个水波扩散周期内不消失 float flag_ripple=step(random(grid+flag_change),_RippleDensity);
- 最后综合计算结果,得到偏移值
//归一化 float2 dv1 = normalize(dv); //计算每个像素uv的偏移值 float2 offset = dv1 * sinFactor*discardFactor*flag_ripple;
- 水波可能不太明显,可以加上水波的颜色(效果好像不太明显)
- 完整代码:https://github.com/kb824999404/Unity_Shader/blob/master/Shader/Test/Water/RippleWater.shader
波浪
- 顶点动画,这里采用线性波形叠加方法,
_WaveScale
为波浪数量,_WaveStrength
为波浪强度 - 需要注意的是,如果使用Unity中自带的模型,顶点数过少,会产生整个模型上下摇动的效果,而不是出现波浪,因此可以在Blender里建一个平面,细分到有足够多的顶点
float calculateSurface(float x, float z, float scale) {float y = 0.0;y += (sin(x * 1.0 / scale + _Time.y * 1.0) + sin(x * 2.3 / scale + _Time.y * 1.5) + sin(x * 3.3 / scale + _Time.y * 0.4)) / 3.0;y += (sin(z * 0.2 / scale + _Time.y * 1.8) + sin(z * 1.8 / scale + _Time.y * 1.8) + sin(z * 2.8 / scale + _Time.y * 0.8)) / 3.0;return y; } v2f vert (appdata v) {v2f o;v.vertex.z += _WaveStrength * calculateSurface(v.vertex.x, v.vertex.y, _WaveScale);o.vertex = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.uv, _MainTex);UNITY_TRANSFER_FOG(o,o.vertex);return o; }
- 完整代码:https://github.com/kb824999404/Unity_Shader/blob/master/Shader/Test/Water/WaveWater.shader
折射反射
- 折射:使用
GrabPass{}
在渲染水面前获取屏幕图像,作为水下贴图,在此基础上渲染水面 - 反射:创建一个相机捕获从水面出发捕获到的景象,建立一个
RenderTexture
将RenderTexture
赋给相机的Render Target
存储获取的图像,再将RenderTexture
赋给水体material
的_ReflectTex
- 菲涅尔反射:使用菲涅尔等式计算反射光和折射光的比例
Fschlick(v,n)=F0+(1−F0)(1−v⋅n)5F_{schlick}(v,n)=F_{0}+(1-F_{0})(1-v\cdot n)^{5}Fschlick(v,n)=F0+(1−F0)(1−v⋅n)5
然后按比例混合反射光和折射光//反射纹理采样 fixed3 reflectColor=tex2D(_ReflectTex,coord);//水下纹理采样 fixed3 refractColor=tex2D(_GrabTex, (i.scrPos.xy+offset)/i.scrPos.w).rgb; //菲涅尔等式计算反射和折射比例 fixed fresnel=_FresnelScale+(1-_FresnelScale)*pow(1-dot(worldViewDir,worldNormal),5);//混合反射光和折射光 fixed3 fresnelColor=lerp(refractColor, reflectColor, saturate(fresnel));
- 水贴图采样,添加高光和阴影,结果:
fixed3 color = ambient+(waterColor +specular+fresnelColor ) * atten;
- 完整代码:https://github.com/kb824999404/Unity_Shader/blob/master/Shader/Test/Water/AllWater.shader
本文代码: https://github.com/kb824999404/Unity_Shader/blob/master/Shader/Test/Water
参考: Unity Shader-后处理:屏幕水波效果 真实感水体渲染技术总结 Unityshader水体笔记 《Unity Shader入门精要》
【Unity Shader实例】 水体WaterEffect(二) 用贴图和uv动画模拟水效
【Unity Shader实例】 水体WaterEffect(五) 水的折射
个人博客传送门: 十七小栈
UnityShader水体渲染相关推荐
- UnityShader水墨渲染的尝试
UnityShader水墨渲染的尝试 描边 混合纹理 先上一张原图,模型素材之类的可以在这里 下载 描边 使用最基本的dot(n,v)来计算边缘,根据需要给控制项,这里我使用了pow来使明暗对比更强烈 ...
- cocos脏话过滤_Cocos Creator 卡通水体渲染教程
原标题:Cocos Creator 卡通水体渲染教程 本篇教程转载自 Cocos 中文社区,作者:regocxy.通过本篇教程你将学到如何做风格化水体的渲染,包含的知识点有如何使用天空立方体贴图作反射 ...
- [Unity/URP学习]风格化水体渲染(一)
风格化水体的实现内容 文章目录 风格化水体的实现内容 风格化水体实现过程 1.水体颜色 1.1风格化水体颜色渐变 1.2水体深浅区域 1.2.1开启深度纹理 1.2.2深度纹理采样 1.3水体透明度 ...
- UnityShader RenderTypeQueue 渲染顺序
整理自这两篇博文 https://blog.csdn.net/u013477973/article/details/80607989?depth_1-utm_source=distribute.pc_ ...
- UnityShader崩坏渲染解析系列(3)--高光、Dither效果、Rim、特殊状态
身体渲染 高光 Dither效果 Rim 特殊状态 小结 高光 前面介绍了暗面的计算方式,接下来是高光的计算效果.高光计算比较简单,采用了Blinn-Phong的光照模型,明暗计算的时候采用了lamb ...
- UnityShader崩坏渲染解析系列(2)--明暗计算
身体渲染 什么是明暗 处理明暗 崩坏处理 资源解析 总结 什么是明暗 与实时渲染不一样的地方在于,日式卡通渲染阴影过度有明显的分界线. 没错,左边的明暗变化有一条很明显的交界线,而右边的是有过渡效果的 ...
- Unity Shader - 水体交互
水体交互 水体交互效果在游戏中是一个很常见的需求,这里简单实现一个可交互的水体. 本篇文章主要是介绍水体交互的实现思路,水体的渲染这里就不再详细介绍,网上很多关于水体的渲染方法很多,可以自己百度.Go ...
- 3D渲染技术分享:实时3D水面渲染(反射、折射、水深与水岸柔边)
一.开篇 自从上次写了**<用实时反射Shader增强画面颜值>** 后,不少开发者开始尝试用它来渲染水面,但效果都差强人意. 这是因为,水面除了反射,还有许多细节需要考虑. 在此之前,也 ...
- 【Unity 风格化】水墨风渲染01:从总结实现方法开始
写在前面 一直比较迷风格化的东西,之前写PBR其实也是为了后面尝试PBR+NRP做铺垫,毕竟了解写实向才能进一步学习奇奇怪怪的NPR方式!话不多说,从水墨渲染开始,正式进入风格化的世界!! 无论是什么 ...
最新文章
- 【硅谷牛仔】Facebook最初的CEO肖恩帕克
- NSArray,NSSet,NSDictionary总结 (转)
- 从数值、玩法、社交模块入手谈MMORPG手游设计
- vue 怎么样不重复往数组里插入数据_前端数据结构与算法(1) -二分查找vs二叉树...
- 写给小白的WordPress详细安装步骤
- nginx安装与项目发布
- 回顾之前易忘记的知识
- mysql一对一关系_sql-MySQL-一对一关系?
- 诺基亚PC套件在windows 2003安装的方法
- 罗技无法使用计算机上的配置文件,罗技游戏软件检测不到游戏启动,导致无法自动切换配置文件...
- 机器码、序列号、认证码、注册码的生成算法(四)
- 多标签分类问题中的评价指标:准确率,交叉熵代价函数
- HDMI线、DP线、DVI线、VGA线
- --TEXT()函数与TEXT()有什么区别
- 「入门运维必看」一篇让小白彻底搞懂性能调优!
- 《Redis设计与实现》笔记
- 安卓机更新系统会卡吗_安卓手机系统“越更新越卡”?或许和这4个原因有关,早看早知道...
- NVIDIA GeForce GTX 950M 新出驱动程序
- 德邦维新:如何打赢“未来之战”?
- 因为一句话,爱上一部电影
热门文章
- 抱抱脸:ChatGPT背后的算法——RLHF | 附12篇RLHF必刷论文
- 特斯拉Model3车主称无法开启;传高通开发首款笔记本处理器;Dfinity挑战亚马逊 | 雷锋早报...
- jc机制是什么_单片机中jc指令表示什么?有什么用?
- js获取今日,昨日,本周,上周,本月,上月,的0点及24点的时间及时间戳,
- seo建设者_网站优化之SEO开发标准
- 严打“霸座”“扒车门”!去年12月以来已有12人被行拘
- 克隆远程仓库#180804
- LC76 Minimum Window Substring
- 为何非得选择旧金山测试?通用Cruise讲述无人车炼成记
- python撤销_Python 实现还原已撤回的微信消息