You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			333 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			Plaintext
		
	
			
		
		
	
	
			333 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			Plaintext
		
	
| #pragma kernel AddVelocity
 | |
| #pragma kernel InitBoundaries
 | |
| #pragma kernel AdvectVelocity
 | |
| #pragma kernel Divergence
 | |
| #pragma kernel ClearBuffer
 | |
| #pragma kernel Poisson
 | |
| #pragma kernel SubstractGradient
 | |
| #pragma kernel CalcVorticity
 | |
| #pragma kernel ApplyVorticity
 | |
| #pragma kernel Viscosity
 | |
| #pragma kernel AddCircleObstacle
 | |
| #pragma kernel AddTriangleObstacle
 | |
| 
 | |
| #include "FLUID_DYNAMICS_MAIN.compute"
 | |
| 
 | |
| const uint2 _Size;
 | |
| RWStructuredBuffer<float2> _VelocityIn;
 | |
| RWStructuredBuffer<float2> _VelocityOut;
 | |
| RWStructuredBuffer<float2> _Obstacles;
 | |
| RWStructuredBuffer<float> _Divergence;
 | |
| RWStructuredBuffer<float> _PressureIn;
 | |
| RWStructuredBuffer<float> _PressureOut;
 | |
| RWStructuredBuffer<float> _Vorticity;
 | |
| 
 | |
| float _ElapsedTime;
 | |
| float _Speed;
 | |
| float _Radius;
 | |
| float2 _Position;
 | |
| float2 _Value;
 | |
| float _VorticityScale; 
 | |
| int _Static; 
 | |
| uint4 GetNeighbours(int2 pos, int2 size)
 | |
| {
 | |
| 	uint4 result;
 | |
| 	const int maxX = size.x - 1;
 | |
| 	const int maxY = size.y - 1; 
 | |
| 	
 | |
| 	result.x = pos.y*_Size.x + clamp(pos.x - 1, 0, maxX);
 | |
| 	result.y = pos.y*_Size.x + clamp(pos.x + 1, 0, maxX);
 | |
| 	result.z = clamp(pos.y - 1, 0, maxY)*size.x + pos.x;
 | |
| 	result.w = clamp(pos.y + 1, 0, maxY)*size.x + pos.x;
 | |
| 	return result;
 | |
| }
 | |
| // UTIL: Clear Buffer
 | |
| RWStructuredBuffer<float2> _Buffer;
 | |
| [numthreads(THREAD_COUNT, THREAD_COUNT, 1)]
 | |
| void ClearBuffer(uint3 id : SV_DispatchThreadID)
 | |
| {
 | |
| 	if (id.x >= _Size.x || id.y >= _Size.y) { return; }
 | |
| 	uint pos = id.y*_Size.x + id.x;
 | |
| 	_Buffer[pos].x = 0.0;
 | |
| }
 | |
| 
 | |
| [numthreads(THREAD_COUNT, THREAD_COUNT, 1)]
 | |
| void AddVelocity(uint3 id : SV_DispatchThreadID)
 | |
| {
 | |
| 	if (id.x >= _Size.x || id.y >= _Size.y) { return; }
 | |
| 
 | |
| 	const uint pos = id.y*_Size.x + id.x;
 | |
| 	const float2 splat_pos = _Position*_Size;
 | |
| 
 | |
| 	const float2 val = _VelocityIn[pos];
 | |
| 	float2 result = val;
 | |
| 
 | |
| 	float len = distance(splat_pos, (float2) id);
 | |
| 	if (len <= _Radius)
 | |
| 	{
 | |
| 		result = val + _Value*(_Radius - len) / _Radius;
 | |
| 	}
 | |
| 
 | |
| 	_VelocityOut[pos] = clamp(result, float2(-1.0, -1.0), float2(1.0, 1.0));
 | |
| }
 | |
| 
 | |
| [numthreads(THREAD_COUNT, THREAD_COUNT, 1)]
 | |
| void InitBoundaries(uint3 id : SV_DispatchThreadID)
 | |
| {
 | |
| 	if (id.x >= _Size.x || id.y >= _Size.y) { return; }
 | |
| 	uint pos = id.y*_Size.x + id.x;
 | |
| 
 | |
| 	if (id.x == 0)
 | |
| 	{
 | |
| 		_VelocityIn[pos] = float2(0.0,0.0);
 | |
| 	}
 | |
| 	else if (id.x == _Size.x - 1)
 | |
| 	{
 | |
| 		_VelocityIn[pos] = float2(0.0, 0.0);
 | |
| 	}
 | |
| 	else if (id.y == 0)
 | |
| 	{
 | |
| 		_VelocityIn[pos] = float2(0.0, 0.0);
 | |
| 	}
 | |
| 	else if (id.y == _Size.y - 1)
 | |
| 	{
 | |
| 		_VelocityIn[pos] = float2(0.0, 0.0);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| float _Dissipation;
 | |
| [numthreads(THREAD_COUNT, THREAD_COUNT, 1)]
 | |
| void AdvectVelocity(uint3 id : SV_DispatchThreadID)
 | |
| {
 | |
| 	if (id.x >= _Size.x || id.y >= _Size.y) { return; }
 | |
| 	const uint pos = id.y*_Size.x + id.x;
 | |
| 
 | |
| 	const float2 obstacle = _Obstacles[pos];
 | |
| 	if (obstacle.x > 0.0 || obstacle.y > 0.0)
 | |
| 	{
 | |
| 		_VelocityOut[pos] = float2(0, 0);
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		const float2 vel = _VelocityIn[pos];
 | |
| 		const float2 final_pos = float2(id.x - vel.x*_ElapsedTime*_Speed, id.y - vel.y*_ElapsedTime*_Speed);
 | |
| 
 | |
| 		const int2 zero = int2(0, 0);
 | |
| 		const int2 SizeBounds = int2(_Size.x - 1, _Size.y - 1);
 | |
| 		const int2 top_right = clamp(ceil(final_pos), zero, SizeBounds);
 | |
| 		const int2 bottom_left = clamp(floor(final_pos), zero, SizeBounds);
 | |
| 
 | |
| 		const float2 delta = final_pos - bottom_left;
 | |
| 
 | |
| 		const float2 lt = _VelocityIn[top_right.y*_Size.x + bottom_left.x];
 | |
| 		const float2 rt = _VelocityIn[top_right.y*_Size.x + top_right.x];
 | |
| 
 | |
| 		const float2 lb = _VelocityIn[bottom_left.y*_Size.x + bottom_left.x];
 | |
| 		const float2 rb = _VelocityIn[bottom_left.y*_Size.x + top_right.x];
 | |
| 
 | |
| 		const float2 h1 = lerp(lt, rt, delta.x);
 | |
| 		const float2 h2 = lerp(lb, rb, delta.x);
 | |
| 		
 | |
| 		_VelocityOut[pos] = clamp(lerp(h2, h1, delta.y)*_Dissipation, float2(-1.0, -1.0), float2(1.0, 1.0));
 | |
| 	}
 | |
| }
 | |
| 
 | |
| [numthreads(THREAD_COUNT, THREAD_COUNT, 1)]
 | |
| void Divergence(uint3 id : SV_DispatchThreadID)
 | |
| {
 | |
| 	if (id.x >= _Size.x || id.y >= _Size.y) { return; }
 | |
| 	const uint pos = id.y*_Size.x + id.x;
 | |
| 
 | |
| 	const uint4 n = GetNeighbours(id.xy, _Size);
 | |
| 
 | |
| 	float x1 = _VelocityIn[n.x].x;
 | |
| 	float x2 = _VelocityIn[n.y].x;
 | |
| 	float y1 = _VelocityIn[n.z].y;
 | |
| 	float y2 = _VelocityIn[n.w].y;
 | |
| 
 | |
| 	const float2 obsL = _Obstacles[n.x];
 | |
| 	const float2 obsR = _Obstacles[n.y];
 | |
| 	const float2 obsB = _Obstacles[n.z];
 | |
| 	const float2 obsT = _Obstacles[n.w];
 | |
| 
 | |
| 	if (obsL.x > 0.0 || obsL.y > 0.0) x1 = 0.0;
 | |
| 	if (obsR.x > 0.0 || obsR.y > 0.0) x2 = 0.0;
 | |
| 	if (obsB.x > 0.0 || obsB.y > 0.0) y1 = 0.0;
 | |
| 	if (obsT.x > 0.0 || obsT.y > 0.0) y2 = 0.0;
 | |
| 
 | |
| 	_Divergence[pos] = 0.5f * ((x2 - x1) + (y2 - y1));
 | |
| }
 | |
| 
 | |
| [numthreads(THREAD_COUNT, THREAD_COUNT, 1)]
 | |
| void Poisson(uint3 id : SV_DispatchThreadID)
 | |
| {
 | |
| 	if (id.x >= _Size.x || id.y >= _Size.y) { return; }
 | |
| 	const uint pos = id.y*_Size.x + id.x;
 | |
| 
 | |
| 	//const float alpha = -1.0f;
 | |
| 	const float rbeta = 0.25;
 | |
| 
 | |
| 	const uint4 n = GetNeighbours(id.xy, _Size);
 | |
| 
 | |
| 	float p = _PressureIn[pos];
 | |
| 
 | |
| 
 | |
| 	const float2 obsL = _Obstacles[n.x];
 | |
| 	const float2 obsR = _Obstacles[n.y];
 | |
| 	const float2 obsB = _Obstacles[n.z];
 | |
| 	const float2 obsT = _Obstacles[n.w];
 | |
| 
 | |
| 	const float x1 = (obsL.x > 0.0 || obsL.y > 0.0) ? p : _PressureIn[n.x];
 | |
| 	const float x2 = (obsR.x > 0.0 || obsR.y > 0.0) ? p : _PressureIn[n.y];
 | |
| 	const float y1 = (obsB.x > 0.0 || obsB.y > 0.0) ? p : _PressureIn[n.z];
 | |
| 	const float y2 = (obsT.x > 0.0 || obsT.y > 0.0) ? p : _PressureIn[n.w];
 | |
| 
 | |
| 	const float b = _Divergence[pos];
 | |
| 
 | |
| 	_PressureOut[pos] = (x1 + x2 + y1 + y2 - b) * rbeta;
 | |
| }
 | |
| 
 | |
| [numthreads(THREAD_COUNT, THREAD_COUNT, 1)]
 | |
| void SubstractGradient(uint3 id : SV_DispatchThreadID)
 | |
| {
 | |
| 	if (id.x >= _Size.x || id.y >= _Size.y) { return; }
 | |
| 
 | |
| 	const uint4 n = GetNeighbours(id.xy, _Size);
 | |
| 
 | |
| 	const uint pos = id.y*_Size.x + id.x;
 | |
| 	float x1 = _PressureIn[n.x];
 | |
| 	float x2 = _PressureIn[n.y];
 | |
| 	float y1 = _PressureIn[n.z];
 | |
| 	float y2 = _PressureIn[n.w];
 | |
| 	float p = _PressureIn[pos];
 | |
| 
 | |
| 	const float2 obsL = _Obstacles[n.x];
 | |
| 	const float2 obsR = _Obstacles[n.y];
 | |
| 	const float2 obsB = _Obstacles[n.z];
 | |
| 	const float2 obsT = _Obstacles[n.w];
 | |
| 
 | |
| 	if (obsL.x > 0.0 || obsL.y > 0.0) x1 = p;
 | |
| 	if (obsR.x > 0.0 || obsR.y > 0.0) x2 = p;
 | |
| 	if (obsB.x > 0.0 || obsB.y > 0.0) y1 = p;
 | |
| 	if (obsT.x > 0.0 || obsT.y > 0.0) y2 = p;
 | |
| 
 | |
| 	float2 velocity = _VelocityIn[pos];
 | |
| 	velocity.x -= 0.5f * (x2 - x1);
 | |
| 	velocity.y -= 0.5f * (y2 - y1);
 | |
| 	_VelocityOut[pos] = velocity;
 | |
| }
 | |
| 
 | |
| [numthreads(THREAD_COUNT, THREAD_COUNT, 1)]
 | |
| void CalcVorticity(uint3 id : SV_DispatchThreadID)
 | |
| {
 | |
| 	if (id.x >= _Size.x || id.y >= _Size.y) { return; }
 | |
| 	const uint pos = id.y*_Size.x + id.x;
 | |
| 	const uint4 n = GetNeighbours(id.xy, _Size);
 | |
| 
 | |
| 	const float2 vL = _VelocityIn[n.x];
 | |
| 	const float2 vR = _VelocityIn[n.y];
 | |
| 	const float2 vB = _VelocityIn[n.z];
 | |
| 	const float2 vT = _VelocityIn[n.w];
 | |
| 
 | |
| 	_Vorticity[pos] = 0.5 * ((vR.y - vL.y) - (vT.x - vB.x));
 | |
| }
 | |
| 
 | |
| [numthreads(THREAD_COUNT, THREAD_COUNT, 1)]
 | |
| void ApplyVorticity(uint3 id : SV_DispatchThreadID)
 | |
| {
 | |
| 	if (id.x >= _Size.x || id.y >= _Size.y) { return; }
 | |
| 	uint pos = id.y*_Size.x + id.x;
 | |
| 
 | |
| 	uint4 n = GetNeighbours(id.xy, _Size);
 | |
| 
 | |
| 	float vL = _Vorticity[n.x];
 | |
| 	float vR = _Vorticity[n.y];
 | |
| 	float vB = _Vorticity[n.z];
 | |
| 	float vT = _Vorticity[n.w];
 | |
| 	float vC = _Vorticity[pos];
 | |
| 
 | |
| 	float2 force = 0.5 * float2(abs(vT) - abs(vB), abs(vR) - abs(vL));
 | |
| 
 | |
| 	float EPSILON = 2.4414e-4;
 | |
| 	float magSqr = max(EPSILON, dot(force, force));
 | |
| 	force = force * rsqrt(magSqr);
 | |
| 
 | |
| 	force *= _VorticityScale * vC * float2(1, -1);
 | |
| 	float2 final_force = force * _ElapsedTime;
 | |
| 
 | |
| 	_VelocityOut[pos] = _VelocityIn[pos] + float2(final_force.x, final_force.y);
 | |
| }
 | |
| 
 | |
| float _Alpha;
 | |
| float _rBeta;
 | |
| [numthreads(THREAD_COUNT, THREAD_COUNT, 1)]
 | |
| void Viscosity(uint3 id : SV_DispatchThreadID)
 | |
| {
 | |
| 	if (id.x >= _Size.x || id.y >= _Size.y) { return; }
 | |
| 	const uint pos = id.y*_Size.x + id.x;
 | |
| 	const uint4 n = GetNeighbours(id.xy, _Size);
 | |
| 
 | |
| 	const float2 x1 = _VelocityIn[n.x];
 | |
| 	const float2 x2 = _VelocityIn[n.y];
 | |
| 	const float2 y1 = _VelocityIn[n.z];
 | |
| 	const float2 y2 = _VelocityIn[n.w];
 | |
| 	const float2 b = _VelocityIn[pos];
 | |
| 
 | |
| 	_VelocityOut[pos] = (x1 + x2 + y1 + y2 + b * _Alpha) * _rBeta;
 | |
| }
 | |
| 
 | |
| [numthreads(THREAD_COUNT, THREAD_COUNT, 1)]
 | |
| void AddCircleObstacle(uint3 id : SV_DispatchThreadID)
 | |
| {
 | |
| 	if (id.x >= _Size.x || id.y >= _Size.y) { return; }
 | |
| 
 | |
| 	const uint pos = id.y*_Size.x + id.x;
 | |
| 	const float2 splat_pos = _Position*_Size;
 | |
| 
 | |
| 	if (distance(splat_pos, (float2) id) <= _Radius)
 | |
| 	{
 | |
| 		if (_Static > 0)
 | |
| 		{
 | |
| 			_Obstacles[pos].y = 1.0;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			_Obstacles[pos].x = 1.0;
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| float2 _P1;
 | |
| float2 _P2;
 | |
| float2 _P3;
 | |
| float Sign(float2 p1, float2 p2, float2 p3)
 | |
| {
 | |
| 	return ((p1.x - p3.x) * (p2.y - p3.y)) - ((p2.x - p3.x) * (p1.y - p3.y));
 | |
| }
 | |
| 
 | |
| bool IsPointInTriangle(float2 pt, float2 v1, float2 v2, float2 v3)
 | |
| {
 | |
| 	const bool b1 = Sign(pt, v1, v2) < 0.0f;
 | |
| 	const bool b2 = Sign(pt, v2, v3) < 0.0f;
 | |
| 	const bool b3 = Sign(pt, v3, v1) < 0.0f;
 | |
| 	return (b1 == b2) && (b2 == b3);
 | |
| }
 | |
| 
 | |
| [numthreads(THREAD_COUNT, THREAD_COUNT, 1)]
 | |
| void AddTriangleObstacle(uint3 id : SV_DispatchThreadID)
 | |
| {
 | |
| 	if (id.x >= _Size.x || id.y >= _Size.y) { return; }
 | |
| 	const float2 pt = float2(id.x, id.y) / float2(_Size);
 | |
| 	if (IsPointInTriangle(pt, _P1, _P2, _P3))
 | |
| 	{
 | |
| 		const uint pos = id.y*_Size.x + id.x;
 | |
| 		if (_Static > 0)
 | |
| 		{
 | |
| 			_Obstacles[pos].y = 1.0;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			_Obstacles[pos].x = 1.0;
 | |
| 		}
 | |
| 	}
 | |
| } |