UE4透明粒子距离场碰撞随机分布解决方案

来源:互联网 发布:insar数据处理软件 编辑:程序博客网 时间:2024/06/14 03:08

由于景深碰撞不能应用于透明物体,因此试了一下UE4的距离场碰撞,效果还可以接受,但是发现发射器的Collision中Random Spread和Random Distribution参数都失效了,粒子只能按照法线做反弹。
这里写图片描述
检查源码发现CollideWithDepthBuffer函数中的一行ComputeCollidingVelocity函数在CollideWithDistanceField中被改写成过程了,而且里面没有随机分布的相关代码,把部分过程删掉换成NewVelocity = ComputeCollidingVelocity(MidVelocity, CollisionPlane.xyz, RelativeTime, Resilience);就可以解决问题了。

//C:\Program Files\Epic Games\UE_4.17\Engine\Shaders\Private\ParticleSimulationShader.usf/** * Compute collision with the global signed distance field */void CollideWithDistanceField(    out float3 NewPosition,    out float3 NewVelocity,    inout float RelativeTime,    in float3 InPosition,    in float3 InVelocity,    in float3 Acceleration,    in float CollisionRadius,    in float Resilience    ){    // Integration assuming no collision.    float3 MidVelocity = InVelocity.xyz + 0.5f * Acceleration;    float3 DeltaPosition = DeltaSeconds * MidVelocity;    NewPosition = InPosition.xyz + DeltaPosition;    NewVelocity = InVelocity.xyz + Acceleration;    float DistanceToNearestSurface = GetDistanceToNearestSurfaceGlobal(InPosition);    float MaxCollisionDistance = CollisionRadius + length(DeltaPosition.xyz);    if (DistanceToNearestSurface < MaxCollisionDistance)    {         float3 CollisionWorldNormal = normalize(GetDistanceFieldGradientGlobal(InPosition));        float3 CollisionWorldPosition = InPosition - CollisionWorldNormal * DistanceToNearestSurface;        float4 CollisionPlane = float4(CollisionWorldNormal.xyz, dot(CollisionWorldPosition.xyz, CollisionWorldNormal.xyz));        // Compute the portion of velocity normal to the collision plane.        float VelocityDot = dot(CollisionPlane.xyz, DeltaPosition.xyz);        float InvVelocityDot = rcp(VelocityDot + 0.0001f); // Add a small amount to avoid division by zero.        // Distance to the plane from the center of the particle.        float DistanceToPlane = dot(CollisionPlane.xyz, InPosition.xyz) - CollisionPlane.w;        // Find out the time of intersection for both the front and back of the sphere.        float t_back = -(DistanceToPlane + CollisionRadius) * InvVelocityDot;        float t_front = -(DistanceToPlane - CollisionRadius) * InvVelocityDot;        //if (t_back >= 0 && t_front <= 1 && DistanceToPlane >= 0)        if (step(0, t_back) * step(t_front, 1) * step(0, DistanceToPlane))        {            NewVelocity = ComputeCollidingVelocity(MidVelocity, CollisionPlane.xyz, RelativeTime, Resilience);            // If the particle lies approximately on the collision plane, don't jump to the point of collision.            t_front *= step(VelocityDot,-1);            // Integrate position taking the collision in to account.            NewPosition = InPosition + DeltaPosition * t_front + NewVelocity * (1.0f - t_front) * DeltaSeconds;            // Update the relative time. Usually this does nothing, but if the            // user has elected to kill the particle upon collision this will do            // so.            RelativeTime += Simulation.CollisionTimeBias;        }        //else if (t_front > 0 && t_back < 1 && DistanceToPlane < 0)        else if (step(0, t_front) * step(t_back, 1) * step(DistanceToPlane,0))        {            // The particle has collided against a backface, kill it by setting            // relative time to a value > 1.0.            RelativeTime = 1.1f;        }    }}

这里写图片描述

这里写图片描述

原创粉丝点击