源码学习网 首页 编程学园 ue4教程 查看内容

UE4模拟流体水滴下雨

2019-7-16 21:59| 发布者: opiye| 查看: 75| 评论: 0

摘要: 首先来看看要实现的效果通过上图,可以把这个效果三个部分:(1)雨滑落时候雨痕迹(2)雨下滑的水滴(3)停留在玻璃上的雨滴当然,这里面最核心的效果是雨滴的滑落,雨滴下滑的时候,不同雨滴的速度不同,如果只是 ...
腾讯云服务器秒杀

首先来看看要实现的效果

通过上图,可以把这个效果三个部分:

(1)雨滑落时候雨痕迹

(2)雨下滑的水滴

(3)停留在玻璃上的雨滴

当然,这里面最核心的效果是雨滴的滑落,雨滴下滑的时候,不同雨滴的速度不同,如果只是用一张mask贴图,然后做UV移动,效果无法达到。所以想到能不能有办法来控制雨滴下滑的速度。我们自然想到定义一个数组SpeedScaleArray[]来存储一组数据,来控制雨滴下滑的速度。不同的雨滴在下滑时形状和拖尾的长短也不一样,但是我们只想用一张贴图来描述雨滴d形状,但是雨滴又要无规则分布。所以接着联想到用不同的UV来定位不同雨滴在UV坐标下的位置,所以有用一组数组 PointCenterArray[]c来存放一组UV坐标数据。以下是在Custom节点HLSL部分代码。

const int ArraySize = 13;const float2 PointCenterArray[ArraySize] ={float2(0.616431, 0.8110922),float2(0.9301831, 0.1473412),float2(0.02223931, 0.1184332),float2(0.8592911, 0.3553432),float2(0.4200671, 0.283112),float2(0.2996781, 0.3984312),float2(0.06235941, 0.5027822),float2(0.2488471, 0.7196162),float2(0.129141, 0.9047732),float2(0.4199991, 0.8350922),float2(0.8572431, 0.8587682),float2(0.7221561, 0.5682152),float2(0.596571, 0.1159342)};const float SpeedScaleArray[ArraySize] ={1.367651,0.8587561,1.01,0.8587561,1.01,0.6405531,0.6405531,0.5894141,0.7692751,0.5894141,1.522451,1.367651,1.01};

上面每个数组总共存储了13组数据,来分别描述雨滴下滑的速度以及位置。

接下来需要三张贴图如下。第一张贴图红色通道存储的是雨滴的形状,绿色通道雨滴的痕迹,法线贴图只需要红绿通道来对这些形状做叠加混合以此来使这些形状变得不规则。第三章贴图是雨滴的法线贴图。

 //Sample base distortion normal map and unpack it.float2 Distortion = (Texture2DSample(TexD, TexDSampler, LocalDistUV).rg * DistPower - 0.5) * 2.0;   //Sample second (smaller) distortion normal map and unpack it.float2 SmallDistortion = (Texture2DSample(TexD, TexDSampler, LocalDistUV * 3.0).rg * DistPower * 0.25 - 0.5) * 2.0;   //Add smaller distortion value to base distortion.Distortion.x += SmallDistortion.x;Distortion.y += SmallDistortion.y * 0.5;   //Local UVs for sampling droplets texture with array varitations.float2 LocalUV = UV + PointCenterArray[i] + Speed * SpeedScaleArray[i] * 4.0;

第一行和第二行代码使用Texture2DSample对第二张法线贴图进行了采样。然后提取RG两个通道,后面再通过DistPower变量对两张贴图强度进行控制,最终将两张贴图的RG两个贴图叠加。这里主要是为了满足美术效果是雨痕和雨滴的形状看起来不规整。最后一段代码,将数组不同的UV以及不同流动速度,做了相应的UV动画。

  //Adding distortion to UVs.LocalUV += Distortion;   //Sample normal map of droplets and unpack it.float3 NewNormal = (Texture2DSample(TexN, TexNSampler, LocalUV).rgb - 0.5) * 2.0;   //Blend normal maps together.NormalBlend.b += 1.0;NewNormal.rg *= -1.0;NormalBlend = NormalBlend * dot(NormalBlend, NewNormal) - NewNormal * NormalBlend.b;   //Colamp blended normal map.NormalBlend = clamp(NormalBlend, -1.0, 1.0);   //Add and mix droplets texture masks.Texture.b = max(Texture.b, Texture2DSample(TexM, TexMSampler, LocalUV).g);Texture.a = max(Texture.a, Texture2DSample(TexM, TexMSampler, LocalUV).r);}	//Combine resulting maps into one.return float4(NormalBlend.rg, Texture.ba);

接下来的第一段代码采样了雨滴法线贴图,接下来是一个法线融合算法。法线融合算法参考下面网页:

Blending in Detailblog.selfshadow.com图标

最终的代码:

	//Const variables from script.const int ArraySize = 13;const float2 PointCenterArray[ArraySize] ={float2(0.616431, 0.8110922),float2(0.9301831, 0.1473412),float2(0.02223931, 0.1184332),float2(0.8592911, 0.3553432),float2(0.4200671, 0.283112),float2(0.2996781, 0.3984312),float2(0.06235941, 0.5027822),float2(0.2488471, 0.7196162),float2(0.129141, 0.9047732),float2(0.4199991, 0.8350922),float2(0.8572431, 0.8587682),float2(0.7221561, 0.5682152),float2(0.596571, 0.1159342)};const float SpeedScaleArray[ArraySize] ={1.367651,0.8587561,1.01,0.8587561,1.01,0.6405531,0.6405531,0.5894141,0.7692751,0.5894141,1.522451,1.367651,1.01};	//Clamp amount of droplets to array count.Count = (int) (clamp(Count, 0.0, ArraySize));	//Resulting texture.float4 Texture = float4(0.0, 0.0, 0.0, 0.0);	//Resulting normal map.float3 NormalBlend = float3(0.0, 0.0, 1.0);	//Lopp for droplets custom tile and animation.for (int i = 0; i < Count; i++){   //Local distortion UVs for each tile.float2 LocalDistUV = DistUV;   //Sample base distortion normal map and unpack it.float2 Distortion = (Texture2DSample(TexD, TexDSampler, LocalDistUV).rg * DistPower - 0.5) * 2.0;   //Sample second (smaller) distortion normal map and unpack it.float2 SmallDistortion = (Texture2DSample(TexD, TexDSampler, LocalDistUV * 3.0).rg * DistPower * 0.25 - 0.5) * 2.0;   //Add smaller distortion value to base distortion.Distortion.x += SmallDistortion.x;Distortion.y += SmallDistortion.y * 0.5;   //Local UVs for sampling droplets texture with array varitations.float2 LocalUV = UV + PointCenterArray[i] + Speed * SpeedScaleArray[i] * 4.0;   //Adding distortion to UVs.LocalUV += Distortion;   //Sample normal map of droplets and unpack it.float3 NewNormal = (Texture2DSample(TexN, TexNSampler, LocalUV).rgb - 0.5) * 2.0;   //Blend normal maps together.NormalBlend.b += 1.0;NewNormal.rg *= -1.0;NormalBlend = NormalBlend * dot(NormalBlend, NewNormal) - NewNormal * NormalBlend.b;   //Colamp blended normal map.NormalBlend = clamp(NormalBlend, -1.0, 1.0);   //Add and mix droplets texture masks.Texture.b = max(Texture.b, Texture2DSample(TexM, TexMSampler, LocalUV).g);Texture.a = max(Texture.a, Texture2DSample(TexM, TexMSampler, LocalUV).r);}	//Combine resulting maps into one.return float4(NormalBlend.rg, Texture.ba);

材质截图:

最终效果:




来源网址:https://zhuanlan.zhihu.com/p/73854479

鲜花

握手

雷人

路过

鸡蛋