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]);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| } |