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.
571 lines
28 KiB
C#
571 lines
28 KiB
C#
using UnityEngine;
|
|
namespace FluidDynamics
|
|
{
|
|
[AddComponentMenu("Fluid Dynamics/Fluid Simulator")]
|
|
public class Main_Fluid_Simulation : MonoBehaviour
|
|
{
|
|
|
|
#region Variables
|
|
[HideInInspector]
|
|
public ComputeShader m_simulationShader;
|
|
[HideInInspector]
|
|
public ComputeShader m_particleAreaShader;
|
|
public bool m_simulate = true;
|
|
[HideInInspector]
|
|
public float m_speed = 500f;
|
|
public float Speed { get { return m_speed; } set { m_speed = value; } }
|
|
[HideInInspector]
|
|
public int m_iterations = 50;
|
|
public int Iterations { get { return m_iterations; } set { m_iterations = value; } }
|
|
[HideInInspector]
|
|
public float m_velocityDissipation = 1f;
|
|
public float VelocityDissipation { get { return m_velocityDissipation; } set { m_velocityDissipation = value; } }
|
|
[HideInInspector]
|
|
public float m_vorticityScale = 0f;
|
|
public float Vorticity { get { return m_vorticityScale; } set { m_vorticityScale = value; } }
|
|
[HideInInspector]
|
|
public float m_viscosity = 0f;
|
|
public float Viscosity { get { return m_viscosity; } set { m_viscosity = value; } }
|
|
[HideInInspector]
|
|
public int m_nResolution = 512;
|
|
[HideInInspector]
|
|
public bool m_cacheVelocity = false;
|
|
public int Resolution { get { return m_nResolution; } set { m_nResolution = value; } }
|
|
public ComputeBuffer VelocityBuffer { get { return m_velocityBuffer[VELOCITY_READ]; } }
|
|
public ComputeBuffer DivergenceBuffer { get { return m_divergenceBuffer; } }
|
|
public ComputeBuffer PressureBuffer { get { return m_pressure[PRESSURE_READ]; } }
|
|
public ComputeBuffer ObstaclesBuffer { get { return m_obstaclesBuffer; } }
|
|
private ComputeBuffer m_obstaclesBuffer;
|
|
private ComputeBuffer[] m_velocityBuffer;
|
|
private ComputeBuffer m_divergenceBuffer;
|
|
private ComputeBuffer[] m_pressure;
|
|
private ComputeBuffer m_vorticityBuffer;
|
|
private Vector2[] m_currentVelocity;
|
|
private int m_nNumCells;
|
|
private int m_nNumGroupsX;
|
|
private int m_nNumGroupsY;
|
|
private int m_nWidth = 512;
|
|
private int m_nHeight = 512;
|
|
private int m_addVelocityKernel = 0;
|
|
private int m_initBoundariesKernel = 0;
|
|
private int m_advectVelocityKernel = 0;
|
|
private int m_divergenceKernel = 0;
|
|
private int m_poissonKernel = 0;
|
|
private int m_substractGradientKernel = 0;
|
|
private int m_calcVorticityKernel = 0;
|
|
private int m_applyVorticityKernel = 0;
|
|
private int m_viscosityKernel = 0;
|
|
private int m_addObstacleCircleKernel = 0;
|
|
private int m_addObstacleTriangleKernel = 0;
|
|
private int m_clearBufferKernel = 0;
|
|
private int VELOCITY_READ = 0;
|
|
private int VELOCITY_WRITE = 1;
|
|
private int PRESSURE_READ = 0;
|
|
private int PRESSURE_WRITE = 1;
|
|
#endregion
|
|
//
|
|
#region Variables2
|
|
[Tooltip("If m_ExposeParticles is true the value of the particles will be cached in memory for use by other systems")]
|
|
public bool m_CacheParticles = false;
|
|
public Gradient m_colourGradient;
|
|
public bool m_updateGradient = false;
|
|
[HideInInspector]
|
|
public float m_densityDissipation = 1f;
|
|
public float Dissipation { get { return m_densityDissipation; } set { m_densityDissipation = value; } }
|
|
public ComputeBuffer ParticlesBuffer { get { return m_particlesBuffer[READ]; } }
|
|
private ComputeBuffer m_colourRamp;
|
|
private int m_addParticlesKernel = 0;
|
|
private int m_advectKernel = 0;
|
|
[HideInInspector]
|
|
public int m_nParticlesResolution = 128;
|
|
public int ParticlesResolution
|
|
{
|
|
get
|
|
{
|
|
return m_nParticlesResolution;
|
|
}
|
|
set
|
|
{
|
|
if (value != m_nParticlesResolution)
|
|
{
|
|
m_nParticlesResolution = value;
|
|
if (Application.isPlaying && m_particlesBuffer[0] != null && m_particlesBuffer[1] != null)
|
|
{
|
|
int nOldHeight = m_nParticlesHeight;
|
|
int nOldWidth = m_nParticlesWidth;
|
|
float[] oldParticleData = new float[nOldWidth * nOldHeight];
|
|
m_particlesBuffer[READ].GetData(oldParticleData);
|
|
m_particlesBuffer[0].Dispose();
|
|
m_particlesBuffer[1].Dispose();
|
|
|
|
CalculateSize();
|
|
|
|
float[] newParticleData = new float[m_nParticlesWidth * m_nParticlesHeight];
|
|
for (int i = 0; i < m_nParticlesHeight; ++i)
|
|
{
|
|
for (int j = 0; j < m_nParticlesWidth; ++j)
|
|
{
|
|
float normX = (float)j / (float)m_nParticlesWidth;
|
|
float normY = (float)i / (float)m_nParticlesHeight;
|
|
int x = (int)(normX * (float)nOldWidth);
|
|
int y = (int)(normY * (float)nOldHeight);
|
|
newParticleData[i * m_nParticlesWidth + j] = oldParticleData[y * nOldWidth + x];
|
|
}
|
|
}
|
|
|
|
m_particlesBuffer = new ComputeBuffer[2];
|
|
for (int i = 0; i < 2; ++i)
|
|
{
|
|
m_particlesBuffer[i] = new ComputeBuffer(m_nParticlesWidth * m_nParticlesHeight, 4, ComputeBufferType.Default);
|
|
}
|
|
m_particlesBuffer[READ].SetData(newParticleData);
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
private int m_nColourRampSize = 256;
|
|
private ComputeBuffer[] m_particlesBuffer;
|
|
private int m_nParticlesNumGroupsX;
|
|
private int m_nParticlesNumGroupsY;
|
|
private int m_nParticlesWidth = 512;
|
|
private int m_nParticlesHeight = 512;
|
|
private int READ = 0;
|
|
private int WRITE = 1;
|
|
private float[] m_currentParticles;
|
|
private Renderer m_tempRend;
|
|
#endregion
|
|
//
|
|
#region Variables3
|
|
static readonly int _Size = Shader.PropertyToID("_Size");
|
|
static readonly int _VelocityIn = Shader.PropertyToID("_VelocityIn");
|
|
static readonly int _VelocityOut = Shader.PropertyToID("_VelocityOut");
|
|
static readonly int _Obstacles = Shader.PropertyToID("_Obstacles");
|
|
static readonly int _Divergence = Shader.PropertyToID("_Divergence");
|
|
static readonly int _PressureIn = Shader.PropertyToID("_PressureIn");
|
|
static readonly int _PressureOut = Shader.PropertyToID("_PressureOut");
|
|
static readonly int _Vorticity = Shader.PropertyToID("_Vorticity");
|
|
|
|
static readonly int _ElapsedTime = Shader.PropertyToID("_ElapsedTime");
|
|
static readonly int _Speed = Shader.PropertyToID("_Speed");
|
|
static readonly int _Radius = Shader.PropertyToID("_Radius");
|
|
static readonly int _Position = Shader.PropertyToID("_Position");
|
|
static readonly int _Value = Shader.PropertyToID("_Value");
|
|
static readonly int _VorticityScale = Shader.PropertyToID("_VorticityScale");
|
|
static readonly int _Static = Shader.PropertyToID("_Static");
|
|
static readonly int _P1 = Shader.PropertyToID("_P1");
|
|
static readonly int _P2 = Shader.PropertyToID("_P2");
|
|
static readonly int _P3 = Shader.PropertyToID("_P3");
|
|
static readonly int _ParticlesIn = Shader.PropertyToID("_ParticlesIn");
|
|
static readonly int _ParticlesOut = Shader.PropertyToID("_ParticlesOut");
|
|
|
|
static readonly int _ParticleSize = Shader.PropertyToID("_ParticleSize");
|
|
static readonly int _Velocity = Shader.PropertyToID("_Velocity");
|
|
|
|
static readonly int _VelocitySize = Shader.PropertyToID("_VelocitySize");
|
|
static readonly int _Dissipation = Shader.PropertyToID("_Dissipation");
|
|
|
|
static readonly int _Buffer = Shader.PropertyToID("_Buffer");
|
|
static readonly int _Particles = Shader.PropertyToID("_Particles");
|
|
static readonly int _ColourRamp = Shader.PropertyToID("_ColourRamp");
|
|
static readonly int _Alpha = Shader.PropertyToID("_Alpha");
|
|
static readonly int _rBeta = Shader.PropertyToID("_rBeta");
|
|
#endregion
|
|
|
|
private void Start()
|
|
{
|
|
m_simulationShader = (ComputeShader)Instantiate(Resources.Load("FLUID_DYNAMICS_SIMULATION"));
|
|
m_particleAreaShader = (ComputeShader)Instantiate(Resources.Load("FLUID_DYNAMICS_PARTICLES"));
|
|
m_tempRend = GetComponent<Renderer>();
|
|
if (SystemInfo.supportsComputeShaders)
|
|
{
|
|
m_nNumCells = m_nWidth * m_nHeight;
|
|
m_addVelocityKernel = m_simulationShader.FindKernel("AddVelocity");
|
|
m_initBoundariesKernel = m_simulationShader.FindKernel("InitBoundaries");
|
|
m_advectVelocityKernel = m_simulationShader.FindKernel("AdvectVelocity");
|
|
m_divergenceKernel = m_simulationShader.FindKernel("Divergence");
|
|
m_clearBufferKernel = m_simulationShader.FindKernel("ClearBuffer");
|
|
m_poissonKernel = m_simulationShader.FindKernel("Poisson");
|
|
m_substractGradientKernel = m_simulationShader.FindKernel("SubstractGradient");
|
|
m_calcVorticityKernel = m_simulationShader.FindKernel("CalcVorticity");
|
|
m_applyVorticityKernel = m_simulationShader.FindKernel("ApplyVorticity");
|
|
m_viscosityKernel = m_simulationShader.FindKernel("Viscosity");
|
|
m_addObstacleCircleKernel = m_simulationShader.FindKernel("AddCircleObstacle");
|
|
m_addObstacleTriangleKernel = m_simulationShader.FindKernel("AddTriangleObstacle");
|
|
CalculateSize();
|
|
LinkToFluidSimulation();
|
|
m_advectKernel = m_particleAreaShader.FindKernel("Advect");
|
|
m_addParticlesKernel = m_particleAreaShader.FindKernel("AddParticles");
|
|
}
|
|
else
|
|
{
|
|
m_simulate = false;
|
|
Debug.LogError("Seems like your target Hardware does not support Compute Shaders. 'Fluid Dynamics' needs support for Compute Shaders to work.");
|
|
}
|
|
}
|
|
private void Update()
|
|
{
|
|
if (m_simulate)
|
|
{
|
|
UpdateParameters();
|
|
CreateBuffersIfNeeded();
|
|
m_simulationShader.SetBuffer(m_initBoundariesKernel, _VelocityIn, m_velocityBuffer[VELOCITY_READ]);
|
|
m_simulationShader.Dispatch(m_initBoundariesKernel, m_nNumGroupsX, m_nNumGroupsY, 1);
|
|
m_simulationShader.SetBuffer(m_advectVelocityKernel, _Obstacles, m_obstaclesBuffer);
|
|
m_simulationShader.SetBuffer(m_advectVelocityKernel, _VelocityIn, m_velocityBuffer[VELOCITY_READ]);
|
|
m_simulationShader.SetBuffer(m_advectVelocityKernel, _VelocityOut, m_velocityBuffer[VELOCITY_WRITE]);
|
|
m_simulationShader.Dispatch(m_advectVelocityKernel, m_nNumGroupsX, m_nNumGroupsY, 1);
|
|
FlipVelocityBuffers();
|
|
m_simulationShader.SetBuffer(m_calcVorticityKernel, _VelocityIn, m_velocityBuffer[VELOCITY_READ]);
|
|
m_simulationShader.SetBuffer(m_calcVorticityKernel, _Vorticity, m_vorticityBuffer);
|
|
m_simulationShader.Dispatch(m_calcVorticityKernel, m_nNumGroupsX, m_nNumGroupsY, 1);
|
|
m_simulationShader.SetBuffer(m_applyVorticityKernel, _VelocityIn, m_velocityBuffer[VELOCITY_READ]);
|
|
m_simulationShader.SetBuffer(m_applyVorticityKernel, _Vorticity, m_vorticityBuffer);
|
|
m_simulationShader.SetBuffer(m_applyVorticityKernel, _VelocityOut, m_velocityBuffer[VELOCITY_WRITE]);
|
|
m_simulationShader.Dispatch(m_applyVorticityKernel, m_nNumGroupsX, m_nNumGroupsY, 1);
|
|
FlipVelocityBuffers();
|
|
if (m_viscosity > 0.0f)
|
|
{
|
|
for (int i = 0; i < m_iterations; ++i)
|
|
{
|
|
m_simulationShader.SetBuffer(m_viscosityKernel, _VelocityIn, m_velocityBuffer[VELOCITY_READ]);
|
|
m_simulationShader.SetBuffer(m_viscosityKernel, _VelocityOut, m_velocityBuffer[VELOCITY_WRITE]);
|
|
m_simulationShader.Dispatch(m_viscosityKernel, m_nNumGroupsX, m_nNumGroupsY, 1);
|
|
FlipVelocityBuffers();
|
|
}
|
|
}
|
|
m_simulationShader.SetBuffer(m_divergenceKernel, _VelocityIn, m_velocityBuffer[VELOCITY_READ]);
|
|
m_simulationShader.SetBuffer(m_divergenceKernel, _Obstacles, m_obstaclesBuffer);
|
|
m_simulationShader.SetBuffer(m_divergenceKernel, _Divergence, m_divergenceBuffer);
|
|
m_simulationShader.Dispatch(m_divergenceKernel, m_nNumGroupsX, m_nNumGroupsY, 1);
|
|
m_simulationShader.SetBuffer(m_clearBufferKernel, _Buffer, m_pressure[PRESSURE_READ]);
|
|
m_simulationShader.Dispatch(m_clearBufferKernel, m_nNumGroupsX, m_nNumGroupsY, 1);
|
|
m_simulationShader.SetBuffer(m_poissonKernel, _Divergence, m_divergenceBuffer);
|
|
m_simulationShader.SetBuffer(m_poissonKernel, _Obstacles, m_obstaclesBuffer);
|
|
for (int i = 0; i < m_iterations; ++i)
|
|
{
|
|
m_simulationShader.SetBuffer(m_poissonKernel, _PressureIn, m_pressure[PRESSURE_READ]);
|
|
m_simulationShader.SetBuffer(m_poissonKernel, _PressureOut, m_pressure[PRESSURE_WRITE]);
|
|
m_simulationShader.Dispatch(m_poissonKernel, m_nNumGroupsX, m_nNumGroupsY, 1);
|
|
FlipPressureBuffers();
|
|
}
|
|
m_simulationShader.SetBuffer(m_substractGradientKernel, _PressureIn, m_pressure[PRESSURE_READ]);
|
|
m_simulationShader.SetBuffer(m_substractGradientKernel, _VelocityIn, m_velocityBuffer[VELOCITY_READ]);
|
|
m_simulationShader.SetBuffer(m_substractGradientKernel, _VelocityOut, m_velocityBuffer[VELOCITY_WRITE]);
|
|
m_simulationShader.SetBuffer(m_substractGradientKernel, _Obstacles, m_obstaclesBuffer);
|
|
m_simulationShader.Dispatch(m_substractGradientKernel, m_nNumGroupsX, m_nNumGroupsY, 1);
|
|
FlipVelocityBuffers();
|
|
m_simulationShader.SetBuffer(m_clearBufferKernel, _Buffer, m_obstaclesBuffer);
|
|
m_simulationShader.Dispatch(m_clearBufferKernel, m_nNumGroupsX, m_nNumGroupsY, 1);
|
|
if (m_cacheVelocity)
|
|
{
|
|
m_velocityBuffer[VELOCITY_READ].GetData(m_currentVelocity);
|
|
}
|
|
}
|
|
if (m_particlesBuffer == null)
|
|
{
|
|
//Debug.Log( null );
|
|
m_particlesBuffer = new ComputeBuffer[2];
|
|
for (int i = 0; i < 2; ++i)
|
|
{
|
|
m_particlesBuffer[i] = new ComputeBuffer(m_nParticlesWidth * m_nParticlesHeight, 4, ComputeBufferType.Default);
|
|
}
|
|
}
|
|
m_particleAreaShader.SetFloat(_Dissipation, m_densityDissipation);
|
|
m_particleAreaShader.SetFloat(_ElapsedTime, Time.deltaTime);
|
|
m_particleAreaShader.SetFloat(_Speed, GetSimulationSpeed());
|
|
m_particleAreaShader.SetBuffer(m_advectKernel, _Obstacles, ObstaclesBuffer);
|
|
m_particleAreaShader.SetBuffer(m_advectKernel, _Velocity, VelocityBuffer);
|
|
m_particleAreaShader.SetBuffer(m_advectKernel, _ParticlesIn, m_particlesBuffer[READ]);
|
|
m_particleAreaShader.SetBuffer(m_advectKernel, _ParticlesOut, m_particlesBuffer[WRITE]);
|
|
m_particleAreaShader.Dispatch(m_advectKernel, m_nParticlesNumGroupsX, m_nParticlesNumGroupsY, 1);
|
|
FlipBuffers();
|
|
if (m_colourRamp == null)
|
|
{
|
|
m_colourRamp = new ComputeBuffer(m_nColourRampSize, 16, ComputeBufferType.Default);
|
|
UpdateGradient();
|
|
}
|
|
if (m_updateGradient)
|
|
{
|
|
UpdateGradient();
|
|
}
|
|
m_tempRend.material.SetBuffer(_Particles, m_particlesBuffer[READ]);
|
|
m_tempRend.material.SetBuffer(_ColourRamp, m_colourRamp);
|
|
m_tempRend.material.SetVector(_Size, new Vector2(m_nParticlesWidth, m_nParticlesHeight));
|
|
if (m_CacheParticles)
|
|
{
|
|
m_particlesBuffer[READ].GetData(m_currentParticles);
|
|
}
|
|
}
|
|
private void OnDisable()
|
|
{
|
|
if (m_velocityBuffer != null && m_velocityBuffer.Length == 2)
|
|
{
|
|
if (m_velocityBuffer[0] != null)
|
|
{
|
|
m_velocityBuffer[0].Dispose();
|
|
}
|
|
if (m_velocityBuffer[1] != null)
|
|
{
|
|
m_velocityBuffer[1].Dispose();
|
|
}
|
|
}
|
|
if (m_divergenceBuffer != null)
|
|
{
|
|
m_divergenceBuffer.Dispose();
|
|
}
|
|
if (m_pressure != null && m_pressure.Length == 2)
|
|
{
|
|
if (m_pressure[0] != null)
|
|
{
|
|
m_pressure[0].Dispose();
|
|
}
|
|
if (m_pressure[1] != null)
|
|
{
|
|
m_pressure[1].Dispose();
|
|
}
|
|
}
|
|
if (m_obstaclesBuffer != null)
|
|
{
|
|
m_obstaclesBuffer.Dispose();
|
|
}
|
|
if (m_vorticityBuffer != null)
|
|
{
|
|
m_vorticityBuffer.Dispose();
|
|
}
|
|
if (m_colourRamp != null)
|
|
{
|
|
m_colourRamp.Dispose();
|
|
}
|
|
if (m_particlesBuffer != null && m_particlesBuffer.Length == 2)
|
|
{
|
|
if (m_particlesBuffer[0] != null)
|
|
{
|
|
m_particlesBuffer[0].Dispose();
|
|
}
|
|
if (m_particlesBuffer[1] != null)
|
|
{
|
|
m_particlesBuffer[1].Dispose();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void SetSize(int nWidth, int nHeight)
|
|
{
|
|
uint groupSizeX = 8;
|
|
uint groupSizeY = 8;
|
|
uint groupSizeZ = 8;
|
|
m_simulationShader.GetKernelThreadGroupSizes(0, out groupSizeX, out groupSizeY, out groupSizeZ);
|
|
m_nWidth = nWidth;
|
|
m_nHeight = nHeight;
|
|
m_nNumCells = m_nWidth * m_nHeight;
|
|
m_nNumGroupsX = Mathf.CeilToInt((float)m_nWidth / (float)groupSizeX);
|
|
m_nNumGroupsY = Mathf.CeilToInt((float)m_nHeight / (float)groupSizeX);
|
|
}
|
|
public int GetWidth()
|
|
{
|
|
return m_nWidth;
|
|
}
|
|
public int GetHeight()
|
|
{
|
|
return m_nHeight;
|
|
}
|
|
public void AddVelocity(Vector2 position, Vector2 velocity, float fRadius)
|
|
{
|
|
if (m_simulationShader != null && m_velocityBuffer != null && m_velocityBuffer.Length >= 2)
|
|
{
|
|
float[] pos = { position.x, position.y };
|
|
m_simulationShader.SetFloats(_Position, pos);
|
|
float[] val = { velocity.x, velocity.y };
|
|
m_simulationShader.SetFloats(_Value, val);
|
|
m_simulationShader.SetFloat(_Radius, fRadius);
|
|
m_simulationShader.SetInts(_Size, new int[] { m_nWidth, m_nHeight });
|
|
m_simulationShader.SetBuffer(m_addVelocityKernel, _VelocityIn, m_velocityBuffer[VELOCITY_READ]);
|
|
m_simulationShader.SetBuffer(m_addVelocityKernel, _VelocityOut, m_velocityBuffer[VELOCITY_WRITE]);
|
|
m_simulationShader.Dispatch(m_addVelocityKernel, m_nNumGroupsX, m_nNumGroupsY, 1);
|
|
FlipVelocityBuffers();
|
|
}
|
|
}
|
|
public void AddObstacleCircle(Vector2 position, float fRadius, bool bStatic)
|
|
{
|
|
float[] pos = { position.x, position.y };
|
|
m_simulationShader.SetFloats(_Position, pos);
|
|
m_simulationShader.SetFloat(_Radius, fRadius);
|
|
m_simulationShader.SetInt(_Static, bStatic ? 1 : 0);
|
|
m_simulationShader.SetBuffer(m_addObstacleCircleKernel, _Obstacles, m_obstaclesBuffer);
|
|
m_simulationShader.Dispatch(m_addObstacleCircleKernel, m_nNumGroupsX, m_nNumGroupsY, 1);
|
|
}
|
|
public void AddObstacleTriangle(Vector2 p1, Vector2 p2, Vector2 p3, bool bStatic = false)
|
|
{
|
|
float[] pos1 = { p1.x, p1.y };
|
|
float[] pos2 = { p2.x, p2.y };
|
|
float[] pos3 = { p3.x, p3.y };
|
|
m_simulationShader.SetFloats(_P1, pos1);
|
|
m_simulationShader.SetFloats(_P2, pos2);
|
|
m_simulationShader.SetFloats(_P3, pos3);
|
|
m_simulationShader.SetInt(_Static, bStatic ? 1 : 0);
|
|
m_simulationShader.SetBuffer(m_addObstacleTriangleKernel, _Obstacles, m_obstaclesBuffer);
|
|
m_simulationShader.Dispatch(m_addObstacleTriangleKernel, m_nNumGroupsX, m_nNumGroupsY, 1);
|
|
}
|
|
public Vector2 GetVelocity(int x, int y)
|
|
{
|
|
return m_currentVelocity[y * m_nWidth + x] * m_speed;
|
|
}
|
|
public void InitShaders()
|
|
{
|
|
CreateBuffersIfNeeded();
|
|
UpdateParameters();
|
|
int[] size = new int[] { m_nWidth, m_nHeight };
|
|
m_simulationShader.SetInts(_Size, size);
|
|
m_currentVelocity = new Vector2[m_nNumCells];
|
|
}
|
|
public float GetSimulationSpeed()
|
|
{
|
|
return m_speed;
|
|
}
|
|
private void CreateBuffersIfNeeded()
|
|
{
|
|
if (m_velocityBuffer == null)
|
|
{
|
|
m_velocityBuffer = new ComputeBuffer[2];
|
|
for (int i = 0; i < 2; ++i)
|
|
{
|
|
m_velocityBuffer[i] = new ComputeBuffer(m_nNumCells, 8, ComputeBufferType.Default);
|
|
}
|
|
}
|
|
if (m_divergenceBuffer == null)
|
|
{
|
|
m_divergenceBuffer = new ComputeBuffer(m_nNumCells, 4, ComputeBufferType.Default);
|
|
}
|
|
if (m_pressure == null)
|
|
{
|
|
m_pressure = new ComputeBuffer[2];
|
|
for (int i = 0; i < 2; ++i)
|
|
{
|
|
m_pressure[i] = new ComputeBuffer(m_nNumCells, 4, ComputeBufferType.Default);
|
|
}
|
|
}
|
|
if (m_obstaclesBuffer == null)
|
|
{
|
|
m_obstaclesBuffer = new ComputeBuffer(m_nNumCells, 8, ComputeBufferType.Default);
|
|
}
|
|
if (m_vorticityBuffer == null)
|
|
{
|
|
m_vorticityBuffer = new ComputeBuffer(m_nNumCells, 4, ComputeBufferType.Default);
|
|
}
|
|
}
|
|
private void UpdateParameters()
|
|
{
|
|
m_simulationShader.SetFloat(_Dissipation, m_velocityDissipation);
|
|
m_simulationShader.SetFloat(_ElapsedTime, Time.deltaTime);
|
|
m_simulationShader.SetFloat(_Speed, m_speed);
|
|
m_simulationShader.SetFloat(_VorticityScale, m_vorticityScale);
|
|
|
|
float centreFactor = 1.0f / (m_viscosity);
|
|
float stencilFactor = 1.0f / (4.0f + centreFactor);
|
|
m_simulationShader.SetFloat(_Alpha, centreFactor);
|
|
m_simulationShader.SetFloat(_rBeta, stencilFactor);
|
|
}
|
|
private void FlipVelocityBuffers()
|
|
{
|
|
int aux = VELOCITY_READ;
|
|
VELOCITY_READ = VELOCITY_WRITE;
|
|
VELOCITY_WRITE = aux;
|
|
}
|
|
private void FlipPressureBuffers()
|
|
{
|
|
int aux = PRESSURE_READ;
|
|
PRESSURE_READ = PRESSURE_WRITE;
|
|
PRESSURE_WRITE = aux;
|
|
}
|
|
public float GetParticles(int x, int y)
|
|
{
|
|
return m_currentParticles[y * m_nParticlesWidth + x];
|
|
}
|
|
private void CalculateSize()
|
|
{
|
|
float x = gameObject.transform.lossyScale.x;
|
|
float y = gameObject.transform.lossyScale.z;
|
|
if (x > y)
|
|
{
|
|
float fHeight = (y / x) * m_nParticlesResolution;
|
|
m_nParticlesWidth = m_nParticlesResolution;
|
|
m_nParticlesHeight = (int)fHeight;
|
|
}
|
|
else
|
|
{
|
|
float fWidth = (x / y) * m_nParticlesResolution;
|
|
m_nParticlesWidth = (int)fWidth;
|
|
m_nParticlesHeight = m_nParticlesResolution;
|
|
}
|
|
SetSizeInShaders();
|
|
uint groupSizeX = 8;
|
|
uint groupSizeY = 8;
|
|
uint groupSizeZ = 8;
|
|
m_particleAreaShader.GetKernelThreadGroupSizes(0, out groupSizeX, out groupSizeY, out groupSizeZ);
|
|
m_nParticlesNumGroupsX = Mathf.CeilToInt((float)m_nParticlesWidth / (float)groupSizeX);
|
|
m_nParticlesNumGroupsY = Mathf.CeilToInt((float)m_nParticlesHeight / (float)groupSizeX);
|
|
m_currentParticles = new float[m_nParticlesWidth * m_nParticlesHeight];
|
|
}
|
|
private void LinkToFluidSimulation()
|
|
{
|
|
float fResolutionRatio = Resolution / (float)m_nParticlesResolution;
|
|
SetSize((int)(m_nParticlesWidth * fResolutionRatio), (int)(m_nParticlesHeight * fResolutionRatio));
|
|
|
|
InitShaders();
|
|
m_particleAreaShader.SetInts(_VelocitySize, new int[] { GetWidth(), GetHeight() });
|
|
}
|
|
private void FlipBuffers()
|
|
{
|
|
int aux = READ;
|
|
READ = WRITE;
|
|
WRITE = aux;
|
|
}
|
|
public Vector2 GetRenderScale()
|
|
{
|
|
return transform.lossyScale;
|
|
}
|
|
public Vector2 GetRenderSize()
|
|
{
|
|
return m_tempRend.bounds.size;
|
|
}
|
|
public int GetParticlesWidth()
|
|
{
|
|
return m_nParticlesWidth;
|
|
}
|
|
public int GetParticlesHeight()
|
|
{
|
|
return m_nParticlesHeight;
|
|
}
|
|
private void UpdateGradient()
|
|
{
|
|
Vector4[] colourData = new Vector4[m_nColourRampSize];
|
|
for (int i = 0; i < m_nColourRampSize; ++i)
|
|
{
|
|
colourData[i] = m_colourGradient.Evaluate(i / 255.0f);
|
|
}
|
|
m_colourRamp.SetData(colourData);
|
|
}
|
|
void SetSizeInShaders()
|
|
{
|
|
m_particleAreaShader.SetInts(_ParticleSize, new int[] { m_nParticlesWidth, m_nParticlesHeight });
|
|
m_tempRend.material.SetVector(_Size, new Vector2(m_nParticlesWidth, m_nParticlesHeight));
|
|
}
|
|
public void AddParticles(Vector2 position, float fRadius, float fStrength)
|
|
{
|
|
if (m_particleAreaShader != null && m_particlesBuffer != null && m_particlesBuffer.Length >= 2)
|
|
{
|
|
float[] pos = { position.x, position.y };
|
|
m_particleAreaShader.SetFloats(_Position, pos);
|
|
m_particleAreaShader.SetFloat(_Value, fStrength);
|
|
m_particleAreaShader.SetFloat(_Radius, fRadius);
|
|
m_particleAreaShader.SetInts(_Size, new int[] { m_nParticlesWidth, m_nParticlesHeight });
|
|
m_particleAreaShader.SetBuffer(m_addParticlesKernel, _ParticlesIn, m_particlesBuffer[READ]);
|
|
m_particleAreaShader.SetBuffer(m_addParticlesKernel, _ParticlesOut, m_particlesBuffer[WRITE]);
|
|
m_particleAreaShader.Dispatch(m_addParticlesKernel, m_nParticlesNumGroupsX, m_nParticlesNumGroupsY, 1);
|
|
FlipBuffers();
|
|
m_tempRend.material.SetBuffer("_Particles", m_particlesBuffer[READ]);
|
|
}
|
|
}
|
|
}
|
|
} |