当前位置: 首页 > news >正文

Unity制作下雨中的地面效果

Unity引擎制作下雨效果

  大家好,我是阿赵。
  之前介绍了Unity引擎里面通过UV偏移做序列帧动画的做法,这里再介绍一个进阶的用法,模拟地面下雨的雨点效果。

一、原理

在这里插入图片描述

  最基本的原理,还是基于这个序列帧动画的做法。不过这里做一点改变。我不再用网格的UV作为计算的UV,而是通过worldPosition的xz轴去计算,并且,我加上了一个frac方法。

float2 uv = frac(i.worldPos.xz*_tiling);
uv = GetSequenceAnimUV(uv,_cols,_rows,_speed, _startFrame);

  这样做的好处是,UV不再依赖网格模型,可以平均的铺在地面上,而且地面可以无限延伸,特别适合做地面雨滴效果。
这样做的效果是这样的:
在这里插入图片描述

  由于frac的效果是把数值只保留小数部分,所以之前的uv坐标,就被划分成很多个小的0-1之间的区域。于是UV序列帧动画,也变成了多个。
  接下来要做的事情,就是把这张1-9的数字图片,换成一张雨点扩散的序列帧图片。由于如果是真的水面,固有色部分还需要做其他效果,所以这个雨点的序列图最好是法线贴图。
  然后通过之前介绍过的法线贴图的用法,把序列帧动画的UV采样法线贴图,然后把法线的效果加强,就出现了雨点打地面的效果。
在这里插入图片描述

二、代码

  于这里只是介绍雨点的效果,所以固有色我就不去认真做了,只是做了个固有色,然后雨点的法线效果是通过高光来表现的。组合了一下之前介绍过的光照模型的代码,还有序列帧动画的代码,就得到了这么一个shader代码了。

Shader "azhao/Rain"
{Properties{_MainTex ("Texture", 2D) = "white" {}_color("Color",Color) = (1,1,1,1)_cols("Cols",int) = 1_rows("Rows",int) = 1_tiling("Tiling",int) = 1_speed("Speed",float) = 25_startFrame("startFrame",int) = 0_NormalTex("Normal Tex", 2D) = "black"{}_normalScale("normalScale", Range(0 , 1)) = 0_specColor("SpecColor",Color) = (1,1,1,1)_shininess("shininess", Range(1 , 100)) = 1_specIntensity("specIntensity",Range(0,1)) = 1}SubShader{Tags { "RenderType"="Opaque" }LOD 100Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;float3 normal:NORMAL;float3 tangent:TANGENT;};struct v2f{float4 vertex : SV_POSITION;float2 uv : TEXCOORD0;float3 worldPos:TEXCOORD1;float3 worldNormal : TEXCOORD2;float3 worldTangent :TEXCOORD3;float3 worldBitangent : TEXCOORD4;};sampler2D _MainTex;float4 _MainTex_ST;float4 _color;float _cols;float _rows;float _tiling;float _speed;float _startFrame;sampler2D _NormalTex;float4 _NormalTex_ST;float _normalScale;float4 _specColor;float _shininess;float _specIntensity;float _ambientIntensity;float2 GetSequenceAnimUV(float2 uv,float cols,float rows,float speed,float startFrame){float totalTiles = cols * rows;float colsOffset = 1.0f / cols;float rowsOffset = 1.0f / rows;float speedVal = _Time.y * speed;float2 offsetTiling = float2(colsOffset, rowsOffset);float currentIndex = round(fmod(speedVal + startFrame, totalTiles));currentIndex += (currentIndex < 0) ? totalTiles : 0;float lineNum = round(fmod(currentIndex, cols));float offsetX = lineNum * colsOffset;float rowCount = round(fmod((currentIndex - lineNum) / cols, rows));rowCount = (int)(rows - 1) - rowCount;float offsetY = rowCount * rowsOffset;float2 offsetXY = float2(offsetX, offsetY);float2 result = uv*offsetTiling +offsetXY;return result;}//简化版的转换法线并缩放的方法half3 UnpackScaleNormal(half4 packednormal, half bumpScale){half3 normal;//由于法线贴图代表的颜色是0到1,而法线向量的范围是-1到1//所以通过*2-1,把色值范围转换到-1到1normal = packednormal * 2 - 1;//对法线进行缩放normal.xy *= bumpScale;//向量标准化normal = normalize(normal);return normal;}//获取HalfLambert漫反射值float GetHalfLambertDiffuse(float3 worldPos, float3 worldNormal){float3 lightDir = UnityWorldSpaceLightDir(worldPos);float NDotL = saturate(dot(worldNormal, lightDir));float halfVal = NDotL * 0.5 + 0.5;return halfVal;}//获取BlinnPhong高光float GetBlinnPhongSpec(float3 worldPos, float3 worldNormal){float3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));float3 halfDir = normalize((viewDir + _WorldSpaceLightPos0.xyz));float specDir = max(dot(normalize(worldNormal), halfDir), 0);float specVal = pow(specDir, _shininess);return specVal;}v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.uv, _MainTex);o.worldPos = mul(unity_ObjectToWorld, v.vertex);o.worldNormal = UnityObjectToWorldNormal(v.normal);o.worldTangent = UnityObjectToWorldDir(v.tangent);o.worldBitangent = cross(o.worldNormal, o.worldTangent);return o;}half4 frag (v2f i) : SV_Target{float2 uv = frac(i.worldPos.xz*_tiling);float2 normalUV = GetSequenceAnimUV(uv,_cols,_rows,_speed, _startFrame);//采样法线贴图的颜色half4 normalCol = tex2D(_NormalTex, normalUV);//得到切线空间的法线方向half3 normalVal = UnpackScaleNormal(normalCol, _normalScale).rgb;//构建TBN矩阵float3 tanToWorld0 = float3(i.worldTangent.x, i.worldBitangent.x, i.worldNormal.x);float3 tanToWorld1 = float3(i.worldTangent.y, i.worldBitangent.y, i.worldNormal.y);float3 tanToWorld2 = float3(i.worldTangent.z, i.worldBitangent.z, i.worldNormal.z);//通过切线空间的法线方向和TBN矩阵,得出法线贴图代表的物体世界空间的法线方向float3 worldNormal = float3(dot(tanToWorld0, normalVal), dot(tanToWorld1, normalVal), dot(tanToWorld2, normalVal));//用法线贴图的世界空间法线,算漫反射half diffuseVal = GetHalfLambertDiffuse(i.worldPos, worldNormal);//用法线贴图的世界空间法线,算高光角度half3 specCol = _specColor * GetBlinnPhongSpec(i.worldPos, worldNormal)*_specIntensity;half4 col = tex2D(_MainTex,i.uv);col.rgb = col.rgb*_color.rgb + specCol;return col;}ENDCG}}
}
http://www.lryc.cn/news/154359.html

相关文章:

  • windows从0搭建python3开发环境与开发工具
  • centos中得一些命令 记录
  • Python实现Word、Excel、PPT批量转为PDF
  • LLM大模型推理加速 vLLM
  • Python|小游戏之猫捉老鼠!!!
  • 万里路,咫尺间:汽车与芯片的智能之遇
  • Ubuntu22.04.1上 mosquitto安装及mosquitto-auth-plug 认证插件配置
  • CCKS2023:基于企业数仓和大语言模型构建面向场景的智能应用
  • LeetCode 热题 100——无重复字符的最长子串(滑动窗口)
  • 【zookeeper】zookeeper的shell操作
  • R语言Meta分析核心技术
  • Oracle数据库尚硅谷学习笔记
  • CG MAGIC进行实体渲染后!分析渲染器CR和VR的区别之处!
  • Ubuntu下Python3与Python2相互切换
  • 【深度学习】实验07 使用TensorFlow完成逻辑回归
  • 2023-09-04 Linux 让shell编译脚本里面设置的环境变量改变kernel里面驱动文件的宏定义值方法,我这里用来做修改固件版本
  • Python操作Excel实战:Excel行转列
  • java实现迭代器模式
  • C++day7模板、异常、auto关键字、lambda表达式、数据类型转换、STL、list、文件操作
  • 【校招VIP】产品分析之活动策划宣传
  • node基础之一:fs 模块
  • 如何快速搭建母婴行业的微信小程序?
  • 【科普向】Jmeter 如何测试接口保姆式教程
  • 阿里云2核4G服务器5M带宽5年费用价格明细表
  • 【图解RabbitMQ-2】图解JMS规范与AMQP协议是什么
  • springboot整合mybatis实现增删改查(xml)--项目阶段1
  • springboot文件上传异步报错
  • error: unable to unlink old ‘.gitlab-ci.yml‘: Permission denied
  • AJAX学习笔记3练习
  • springboot实战(五)之sql业务日志输出,重要