Unity3d 使用Unity Compute着色器进行流体模拟时出现问题
为了进入计算着色器,我制作了这个带有动态地形的小型湖泊模拟器。我让它看起来是3D的,但实际的模拟是在2D高度地图上进行的,每个像素都包含水体的深度值和地形的高度。下面是一个屏幕截图: 乍一看,它看起来很好,但当水顺着斜坡流下时,你可以看到那些奇怪的水花落在后面。它们也倾向于从无到有地产生越来越多的水。我很确定我知道这些小故障是从哪里来的,但我对如何以GPU友好的方式解决这个问题束手无策 程序非常简单: 我使用一个结构化缓冲区,它为水的每个“像素”保存这些值:Unity3d 使用Unity Compute着色器进行流体模拟时出现问题,unity3d,simulation,game-physics,hlsl,compute-shader,Unity3d,Simulation,Game Physics,Hlsl,Compute Shader,为了进入计算着色器,我制作了这个带有动态地形的小型湖泊模拟器。我让它看起来是3D的,但实际的模拟是在2D高度地图上进行的,每个像素都包含水体的深度值和地形的高度。下面是一个屏幕截图: 乍一看,它看起来很好,但当水顺着斜坡流下时,你可以看到那些奇怪的水花落在后面。它们也倾向于从无到有地产生越来越多的水。我很确定我知道这些小故障是从哪里来的,但我对如何以GPU友好的方式解决这个问题束手无策 程序非常简单: 我使用一个结构化缓冲区,它为水的每个“像素”保存这些值: struct Pixel {
struct Pixel {
float terrainHeight,
float waterDepth,
float4 flowRate
}
每个像素根据其直接邻域(上、下、左、右)的水位差(waterlevel=terrainHeight+waterDepth
)。我将这四个值分别存储在流速
中,然后在稍后的过程中,取它们的总和并将其添加到水深
。现在,在某些情况下,如在倾斜地形上,这将导致负深度值。这就是为什么中间有另一个通道,以确保像素不会溢出更多的水:
If {sum of flowRate components + waterDepth} < 0:
float pos = sum of flowRate components > 0
float neg = sum of flowRate components < 0
float scale = (waterDepth + pos) / abs(neg); // scale will be < 1
for each component of flowRate < 0:
flowRate *= scale; // Decrease negative flowRates, so the summation ends up at exactly zero,
// instead of below.
如果{流量分量之和+水深}<0:
浮动位置=流量组件之和>0
float neg=流量分量之和<0
浮标=(水深+位置)/abs(负);//刻度将小于1
对于流量<0的各成分:
流量*=刻度;//减少负流量,使总和正好为零,
//而不是下面。
这就是我认为竞争条件发生的地方:与邻居共享流量的值,因此每个邻居可能使用或可能不使用修正值,从而从无到有地产生额外的水
不知道该怎么办。这甚至是一个可以在GPU上解决的问题吗?也许在像素从更高级别取水之前,它会检查该像素是否有足够的水,而不是计算像素本身的水