# 前言
前些日子做了个水龙头流水的效果(当然跟高大上的流体之类的无关),所用到的无非就是粒子效果 + Shader + 部分代码而已。
不过,自己觉得看着还行,所以有此一记。
效果如下:
简答来说,就是开启水龙头 -> 流水,同时扰动水纹,关闭水龙头 -> 关闭水,同时慢慢将水纹渐隐掉。
(上面两个手柄是因为:这个是 VR 项目,开发机跟运行机是不同的,我的开发机上面什么都没,没办法之下只有模拟下了,不过只要接入 VR 就会自动转换了,没什么影响)
# 实现
先来看看 UE4 材质节点:
材质实例设置:
就是这样。
其中,主要就是通过 Sin 计算纹理扰动比较麻烦,但若是用代码来描述的话,也就是几句的事情 —— 实际上,在 UE4 中我拖出这些节点来了之后,自己都看着费劲,所以原本,这个效果我是先行在 Unity3D 中实现的:
主要代码如下:
float2 uv = i.uv; | |
uv -= float2(0.5,0.5); | |
float dis =sqrt( dot(uv,uv)); | |
uv =i.uv+ sin(100*dis - _Time.y*10)*i.uv*0.01*3; | |
fixed4 col = tex2D(_GrabTexture,uv); |
其原理就是首先将 UV 挪到中心,计算其与中心的距离,然后通过 sin 函数 + 时间等参数对 UV 进行扰动。
我这儿时抓取了屏幕纹理(_GrabTexture),所以看着就是这种效果了。
在 UE4 中,除此之外,还另外增加了使用发现进行扰动的效果,以及插值 “平静水面与扰动水面” 的功能。
代码中开关如下:
void ATriggerWaterTapActor::Tick(float DeltaTime) | |
{ | |
if (bCanOpen) | |
{ | |
WaterWaveValue = FMath::Lerp(WaterWaveValue, 0.0f, DeltaTime*0.35f); | |
} | |
else | |
{ | |
WaterWaveValue = FMath::Lerp(WaterWaveValue, 1.0f, DeltaTime); | |
} | |
GEngine->AddOnScreenDebugMessage(2, 3, FColor::Cyan, FString::SanitizeFloat(WaterWaveValue)); | |
WaterMesh->SetScalarParameterValueOnMaterials(FName("Wave"), WaterWaveValue); | |
} | |
void ATriggerWaterTapActor::OnTriggered_Implementation() | |
{ | |
Super::OnTriggered_Implementation(); | |
bCanOpen = !bCanOpen; | |
bool active = bCanOpen; | |
active ? _particleSystem->Deactivate() : _particleSystem->Activate(); | |
GEngine->AddOnScreenDebugMessage(-1, 1, FColor::Green, active ? TEXT("关闭") : TEXT("开启")); | |
} |