Search Unity

Cocuy - Fluid Simulation for Unity

Discussion in 'Assets and Asset Store' started by Musiu-Bar, Apr 6, 2015.

  1. RedVonix

    RedVonix

    Joined:
    Dec 13, 2011
    Posts:
    363
    Ok, so we fixed the turn off / turn on problem. Required some major editing of the Cocuy source (brought in a specialist who found a lot of bugs in there). So that's fixed, though not sure I could post the fix here as it would require posting modifications to lots of the main source file.

    Also discovered that Cocuy does NOT properly sort with particle effects (it clips them away). To fix that, just add ZWrite Off to the Cocuy/Material Renderer shader.
     
    FunkyFancy and hopeful like this.
  2. hopeful

    hopeful

    Joined:
    Nov 20, 2013
    Posts:
    5,028
    Would be great if you could submit your modified files to the plugin devs.
     
  3. RedVonix

    RedVonix

    Joined:
    Dec 13, 2011
    Posts:
    363
    We absolutely will if we can get a hold of them.
     
    FunkyFancy and hopeful like this.
  4. Musiu-Bar

    Musiu-Bar

    Joined:
    Apr 6, 2015
    Posts:
    58
    Hey all,

    Sorry for the abscence in the last couple of weeks. I am looking at all those issues reported. @RedVonix was kind enough to provide some really good feedback and has even sent me some fixes! Will try to integrate them soon.
     
    idavida, FunkyFancy and hopeful like this.
  5. noroaspe

    noroaspe

    Joined:
    Jan 2, 2018
    Posts:
    1
    Hi

    I would like some information about this asset.
    - I plan on using the asset for my research and would like to know if I may have permission to do so or if it would be possible for a small fee.
    - What kind of mechanism is used in your fluid simulation? (ex. Navier-Stokes equations)
    I’m not very familiar with the fluid simulation.
    So if you’d like, could you please tell me about references of the implementation (methods or papers, and so on).

    Regards.
     
  6. hawk-hawk-studio

    hawk-hawk-studio

    Joined:
    Mar 9, 2016
    Posts:
    6
    Hi! I am quite interested in this asset. But I have some doubts about it. Is it compatible with any Android device? And if not, is there any way to make it compatible.

    Thank you very much!
     
  7. Musiu-Bar

    Musiu-Bar

    Joined:
    Apr 6, 2015
    Posts:
    58
    Hi @noroaspe

    You can definitely use Cocuy for your research! As long as your research doesn't requiere to open source any tools you use, you may use Cocuy for it. If you want, email me at: info@musiubar.com and we can talk a bit more in detail about it.

    As for the simulation, Cocuy indeed uses an aproximation to the Navier-Stokes equations. The solver used is based of Jos Stam's work on real-time fluid simulation:

    Stable Fluids [http://www.dgp.toronto.edu/people/stam/reality/Research/pdf/ns.pdf]
    Real-Time Fluid Dynamics for Games [http://www.intpowertechcorp.com/GDC03.pdf]

    Those papers are based on a CPU bound solution which I then parallelized for the GPU.

    As reference, this solution is similar and also a good read:

    Fast Fluid Dynamics Simulations on the GPU [http://developer.download.nvidia.com/books/HTML/gpugems/gpugems_ch38.html]

    Hope that helps!
     
  8. Musiu-Bar

    Musiu-Bar

    Joined:
    Apr 6, 2015
    Posts:
    58
    Hey @hawk-hawk-studio

    Cocuy does run on Android devices. It uses compute shaders so you'd have to make sure your device is capable of running it. In general any good phone from the last couple of years should do, but make sure first, you can have a look at general Unity Compute Shaders support here: https://docs.unity3d.com/Manual/ComputeShaders.html

    Let me know if you have any other questions!
     
  9. FuzzyMeloxKhora

    FuzzyMeloxKhora

    Joined:
    Jul 13, 2017
    Posts:
    1
    Looking great! I'm having some trouble when i rotate my fluid plane tho, i want to use it in a 3D env on a floor - anyway to make it work?
     
  10. hawk-hawk-studio

    hawk-hawk-studio

    Joined:
    Mar 9, 2016
    Posts:
    6
    Thank you!!! And do you know if there is any way to replace the ComputeShader by any other element to use it in a mobile device? Could I substitute it by a normal Shader?
     
  11. idavida

    idavida

    Joined:
    Nov 12, 2012
    Posts:
    29
    Hi! So this asset looks good but I can't use in current project if I can't toggle enable gameobjects. Any progress on this?

    Also, if I could request dynamic fluid simulations with the field parented to a moving entity to have a smaller field in a very large environment? Ie, parent the area to Mario and thus using a 10x10 units large area instead of covering the whole mario 1-1 level in a super large field.
     
  12. Francking

    Francking

    Joined:
    Feb 12, 2014
    Posts:
    2
    djarcas said:
    I've got a similar question; all of the pictures show a single-colour fluid - is it possible to support multiple-coloured fluids that mix and fade together with this?

    Hello Musiu-Bar!

    I also want to blend different colors in the same Particles Area. What I envision is to move the Color Gradient ramp from the Particles Area to the Particles Area Manipulator.

    Did you provide guidelines to djarcas to achieve the feature? Do you have any updates on the feature (or if anyone had done it on their side) ?
     
    Last edited: Mar 14, 2018
  13. DoMath

    DoMath

    Joined:
    Oct 20, 2016
    Posts:
    1
    Hi

    could you explain how to configure and setting the editor in unity and cocuy in the best way to be able to compile for Android.
    The example of apk that you put in this forum works very well in my device , but when I try to compile the same from the code, I have a low performance on the same device.
    So I understand that there should be an optimal way to configure Unity settings and Cocuy for Android.

    Another thing, if unity editor set to compile for Android and press play, can not see the simulation, but if it is set on PC and press play, it work fine.

    Thank you

    Renzo
     
    Last edited: Apr 24, 2018
  14. johnle

    johnle

    Joined:
    Mar 14, 2013
    Posts:
    2
    Are you working on Super Starfish?


    Hope you're still supporting this package. Would be nice to have these:
    1. XZ plane support as well.
    2. Moving the camera certain distance from Fluid area will break fluid rendering due to maxDistance param too small:
    m_fluid.GetComponent<Collider>().Raycast(ray, out hitInfo, MAX_DISTANCE). I changed the value and all worked well. Had to tinker with the fluid area size but still ok.
     
    Lars-Steenhoff likes this.
  15. imaginaryhuman

    imaginaryhuman

    Joined:
    Mar 21, 2010
    Posts:
    5,678
    Love the fluid simulated visuals on that.
     
  16. nasos_333

    nasos_333

    Joined:
    Feb 13, 2013
    Posts:
    8,033
    Hi,

    Is it possible to get this effect with water fluid ?



    Thanks
     
  17. chdrvn

    chdrvn

    Joined:
    Dec 4, 2013
    Posts:
    23
    Hey just got your asset, loving the groovy fluidity. I'd just like to second the motion on the 'particle area follows camera' functionality. Itd be immensely helpful. cheers
     
  18. adriaanwormgoor

    adriaanwormgoor

    Joined:
    Nov 14, 2013
    Posts:
    7
    That's a lot of beautiful fluid sim, hope this was indeed made with Cocuy Fluid Sim. At 0:12 in de video I see a kind of two-pronged laser beam aiming and firing. On the moment of firing it has an instant effect on the fluid sim. How does one achieve something like this with Cocuy Fluid Sim? I'm looking for instant momentary effects like a raindrop splash or something following the contour of a given mesh. I've played around with this for a bit but didn't get pleasing results, it seemed like you'd need to already have an emitter actively feeding into the system in order to create a fluid 'puff'. Am I wrong?
     
  19. lhthai2010x

    lhthai2010x

    Joined:
    May 28, 2015
    Posts:
    3
    Hi Musiu-Bar!
    i import package and i build on android only Basic scene demo on project, i make FPS too low about 10 - 15 FPS.
    i just import and i do nothing on this scene. Am o wrong?
    and I Switch platform to android i received this message

    <CocuyError> It seems your target Hardware does not support Compute Shaders. Cocuy needs support for Compute Shaders to work

    when i play in editor.
    Thanks you!
     
  20. friuns3

    friuns3

    Joined:
    Oct 30, 2009
    Posts:
    279
    is there way to apply offset to whole simulation? so i can move everything relative to player without having insane hude canvas.
     
  21. SleepyAgapornis

    SleepyAgapornis

    Joined:
    Sep 7, 2018
    Posts:
    6
    Does this plugin still works on Unity 2018.2 ? I would like to use it for IOS, Android and WebGL, it looks great but I´m a bit scared because of the feedbacks..
     
  22. kalamtech

    kalamtech

    Joined:
    Oct 27, 2017
    Posts:
    8
    Guys what was the final settings you tweaked to manage it working with Metal? I've been trying to change the threads(Cocuy_Common.compute) to all values from 8 to 32 but on 32 it freezes the game playing a frame every 20 sec and bellow that I have:

    2019-03-18 15:44:59.397034+0000 hhcurie[1874:1077827] Execution of the command buffer was aborted due to an error during execution. Caused GPU Hang Error (IOAF code 3)

    2019-03-18 15:44:59.397238+0000 hhcurie[1874:1077827] Execution of the command buffer was aborted due to an error during execution. Discarded (victim of GPU error/recovery) (IOAF code 5)

    2019-03-18 15:44:59.433008+0000 hhcurie[1874:1077809] Execution of the command buffer was aborted due to an error during execution. Caused GPU Hang Error (IOAF code 3)

    2019-03-18 15:44:59.433219+0000 hhcurie[1874:1077809] Execution of the command buffer was aborted due to an error during execution. Discarded (victim of GPU error/recovery) (IOAF code 5)

    2019-03-18 15:44:59.439547+0000 hhcurie[1874:1077809] Execution of the command buffer was aborted due to an error during execution. Ignored (for causing prior/excessive GPU errors) (IOAF code 4)

    then repeats the code 4 forever...
     
    Last edited: Mar 19, 2019
  23. B0b

    B0b

    Joined:
    Sep 26, 2014
    Posts:
    5
    Hello are you willing to update this asset as I see there are plenty of bugs in it So I am afraid to buy it
     
  24. kalamtech

    kalamtech

    Joined:
    Oct 27, 2017
    Posts:
    8
    Hi Musiu-Bar,

    I have a bug fix for you! I finally got Cocuy working on iOS in the latest version of Metal.

    The error message we were seeing (mentioned above) was caused by the compute shader function "ClearBuffer" in Cocuy_Simulation.compute.

    It seems that the function was being called after the "_Buffer" had been populated with a ComputeBuffer containing a float array rather than a float2 array. When the array element was accessed and the ".x" property was supposed to be populated, it threw an error. Presumably because a float doesn't have a ".x" property? One of those cases where I wonder how it ever worked to begin with!

    Seems like older versions of Metal were ok with this, the current version... not so much.

    My fix was to duplicate the"ClearBuffer" function in the compute shader making one for a float array and one for a float2 array then using them as appropriate in FluidSimulator.cs.

    Let me know if you want to see my amended code. It would be great for people to be able to use Cocuy out of the box again on iOS. It's a great bit of code :)
     
  25. Mauri

    Mauri

    Joined:
    Dec 9, 2010
    Posts:
    1,688
    Just a heads-up:
    Musiu-Bar was last seen: Feb 18, 2018
    here. From the looks of it, this Asset seems discontinued.

    There's an email address on their Asset Store publisher profile - in case someone wants to try getting in touch with them: https://assetstore.unity.com/publishers/12305
     
  26. kalamtech

    kalamtech

    Joined:
    Oct 27, 2017
    Posts:
    8
    Fair point Mauri!

    I'll send them an email :)
     
  27. ArthurUS83

    ArthurUS83

    Joined:
    Jan 13, 2016
    Posts:
    21
    Hello Guys is this asset support on android?
    Thanks
     
  28. HEJlbCOH

    HEJlbCOH

    Joined:
    Jan 8, 2018
    Posts:
    2
    How can I change the shape of the particles? (for example, not a circle but a square, a triangle, etc.)
     
  29. JoshuaVaughan1978

    JoshuaVaughan1978

    Joined:
    Jul 30, 2018
    Posts:
    1
    I've hit the exact same error as you, if you could PM the code change it will probably save me a couple hours!
     
  30. chdrvn

    chdrvn

    Joined:
    Dec 4, 2013
    Posts:
    23
    Has anyone found a way to get it moving with the camera or parent object? Would it even be practical performance wise? Shaders are not my forte.
    I'd almost pay for a solution if it works.

    This asset seems ok for small single screen mobile games but kinda useless otherwise. Like not being able to just slap some smoke on a moving flame in your game is kinda lame
     
  31. viktorkoon

    viktorkoon

    Joined:
    Apr 5, 2019
    Posts:
    1
    Hey.
    Is it possible to determine the moment a stream collides with other objects?
    I will give an example. Is it possible to remove an object after touching the flow that object?
     
  32. nathanvog

    nathanvog

    Joined:
    Oct 19, 2015
    Posts:
    2
    Hi,
    Is there a way to actually slow down the simulation? Simulation speed only affects the size of the particles motion each frame, not the evolution of the vorticity, etc. so it gives completely different visual results for different "Simulation speed".
     
  33. kalamtech

    kalamtech

    Joined:
    Oct 27, 2017
    Posts:
    8
    the developer that did the changes left the company, but I'm adding his FluidSimulator.cs so you can compare with yours, for some strange reason I could only attach the FluidSimulator.cs file but I couldn't do the same for Cocuy_Simulation.compute, so I'm pasting the code bellow.

    We've manage to make it work properly and we release our game using it (https://play.google.com/store/apps/details?id=kalam.tech.curie&hl=en)

    Code (CSharp):
    1. #pragma kernel AddVelocity
    2. #pragma kernel InitBoundaries
    3. #pragma kernel AdvectVelocity
    4. #pragma kernel Divergence
    5. #pragma kernel ClearBuffer
    6. #pragma kernel ClearBufferDouble
    7. #pragma kernel Poisson
    8. #pragma kernel SubstractGradient
    9. #pragma kernel CalcVorticity
    10. #pragma kernel ApplyVorticity
    11. #pragma kernel Viscosity
    12. #pragma kernel AddCircleObstacle
    13. #pragma kernel AddTriangleObstacle
    14.  
    15. #include "Cocuy_Common.compute"
    16.  
    17. const uint2 _Size;
    18. const uint _Max;
    19. uniform RWStructuredBuffer<float2> _VelocityIn;
    20. uniform RWStructuredBuffer<float2> _VelocityOut;
    21. uniform RWStructuredBuffer<float2> _Obstacles;
    22. uniform RWStructuredBuffer<float> _Divergence;
    23. uniform RWStructuredBuffer<float> _PressureIn;
    24. uniform RWStructuredBuffer<float> _PressureOut;
    25. uniform RWStructuredBuffer<float> _Vorticity;
    26.  
    27. float _ElapsedTime;
    28. float _Speed;
    29. float _Radius;
    30. float2 _Position;
    31. float2 _Value;
    32. float _VorticityScale;
    33.  
    34. // For Obstacles
    35. int _Static;
    36.  
    37. uint4 GetNeighbours(int2 pos, int2 size)
    38. {
    39.     uint4 result;
    40.     const int maxX = size.x - 1;
    41.     const int maxY = size.y - 1;
    42.    
    43.     result.x = pos.y*_Size.x + clamp(pos.x - 1, 0, maxX);
    44.     result.y = pos.y*_Size.x + clamp(pos.x + 1, 0, maxX);
    45.     result.z = clamp(pos.y - 1, 0, maxY)*size.x + pos.x;
    46.     result.w = clamp(pos.y + 1, 0, maxY)*size.x + pos.x;
    47.     return result;
    48. }
    49.  
    50. ////////////////////////////////////////////////////////////////////////////
    51. // UTIL: Clear Buffer Double
    52. uniform RWStructuredBuffer<float2> _BufferDouble;
    53. [numthreads(THREAD_COUNT, THREAD_COUNT, 1)]
    54. void ClearBufferDouble(uint3 id : SV_DispatchThreadID)
    55. {
    56.     if ( id.x < 0 || id.x >= _Size.x || id.y < 0 || id.y >= _Size.y) { return; }
    57.     const uint pos = clamp(id.y*_Size.x + id.x, 0, _Max);
    58.     _BufferDouble[pos].x = 0.0;
    59. }
    60.  
    61. ////////////////////////////////////////////////////////////////////////////
    62. // UTIL: Clear Buffer
    63. uniform RWStructuredBuffer<float> _Buffer;
    64. [numthreads(THREAD_COUNT, THREAD_COUNT, 1)]
    65. void ClearBuffer(uint3 id : SV_DispatchThreadID)
    66. {
    67.     if ( id.x < 0 || id.x >= _Size.x || id.y < 0 || id.y >= _Size.y) { return; }
    68.     const uint pos = clamp(id.y*_Size.x + id.x, 0, _Max);
    69.     _Buffer[pos] = 0.0;
    70. }
    71.  
    72. ////////////////////////////////////////////////////////////////////////////
    73. [numthreads(THREAD_COUNT, THREAD_COUNT, 1)]
    74. void AddVelocity(uint3 id : SV_DispatchThreadID)
    75. {
    76.     if ( id.x < 0 || id.x >= _Size.x || id.y < 0 || id.y >= _Size.y) { return; }
    77.  
    78.     const uint pos = clamp(id.y*_Size.x + id.x, 0, _Max);
    79.     const float2 splat_pos = _Position*_Size;
    80.  
    81.     const float2 val = _VelocityIn[pos];
    82.    
    83.     const float len = distance(splat_pos, (float2) id);
    84.     if (len <= _Radius)
    85.     {
    86.         _VelocityOut[pos] = clamp( val + _Value*(_Radius - len) / _Radius, float2(-1.0, -1.0), float2(1.0, 1.0));
    87.     }
    88.     else
    89.     {
    90.         _VelocityOut[pos] = clamp(val, float2(-1.0, -1.0), float2(1.0, 1.0));
    91.     }  
    92. }
    93.  
    94. ////////////////////////////////////////////////////////////////////////////
    95. [numthreads(THREAD_COUNT, THREAD_COUNT, 1)]
    96. void InitBoundaries(uint3 id : SV_DispatchThreadID)
    97. {
    98.     if ( id.x < 0 || id.x >= _Size.x || id.y < 0 || id.y >= _Size.y) { return; }
    99.     const uint pos = clamp(id.y*_Size.x + id.x, 0, _Max);
    100.  
    101.     if (id.x == 0)
    102.     {
    103.         _VelocityIn[pos] = float2(0.0,0.0);
    104.     }
    105.     else if (id.x == _Size.x - 1)
    106.     {
    107.         _VelocityIn[pos] = float2(0.0, 0.0);
    108.     }
    109.     else if (id.y == 0)
    110.     {
    111.         _VelocityIn[pos] = float2(0.0, 0.0);
    112.     }
    113.     else if (id.y == _Size.y - 1)
    114.     {
    115.         _VelocityIn[pos] = float2(0.0, 0.0);
    116.     }
    117. }
    118.  
    119. ////////////////////////////////////////////////////////////////////////////
    120. float _Dissipation;
    121. [numthreads(THREAD_COUNT, THREAD_COUNT, 1)]
    122. void AdvectVelocity(uint3 id : SV_DispatchThreadID)
    123. {
    124.     if ( id.x < 0 || id.x >= _Size.x || id.y < 0 || id.y >= _Size.y) { return; }
    125.     const uint pos = clamp(id.y*_Size.x + id.x, 0, _Max);
    126.    
    127.     const float2 obstacle = _Obstacles[pos];
    128.     if (obstacle.x > 0.0 || obstacle.y > 0.0)
    129.     {
    130.         _VelocityOut[pos] = float2(0, 0);
    131.     }
    132.     else
    133.     {
    134.         const float2 vel = _VelocityIn[pos];
    135.         const float2 final_pos = float2(id.x - vel.x*_ElapsedTime*_Speed, id.y - vel.y*_ElapsedTime*_Speed);
    136.  
    137.         const int2 zero = int2(0, 0);
    138.         const int2 SizeBounds = int2(_Size.x - 1, _Size.y - 1);
    139.         const int2 top_right = clamp(ceil(final_pos), zero, SizeBounds);
    140.         const int2 bottom_left = clamp(floor(final_pos), zero, SizeBounds);
    141.  
    142.         const float2 delta = final_pos - bottom_left;
    143.  
    144.         const float2 lt = _VelocityIn[top_right.y*_Size.x + bottom_left.x];
    145.         const float2 rt = _VelocityIn[top_right.y*_Size.x + top_right.x];
    146.  
    147.         const float2 lb = _VelocityIn[bottom_left.y*_Size.x + bottom_left.x];
    148.         const float2 rb = _VelocityIn[bottom_left.y*_Size.x + top_right.x];
    149.  
    150.         const float2 h1 = lerp(lt, rt, delta.x);
    151.         const float2 h2 = lerp(lb, rb, delta.x);
    152.        
    153.         _VelocityOut[pos] = clamp(lerp(h2, h1, delta.y)*_Dissipation, float2(-1.0, -1.0), float2(1.0, 1.0));
    154.     }
    155. }
    156.  
    157. ////////////////////////////////////////////////////////////////////////////
    158. [numthreads(THREAD_COUNT, THREAD_COUNT, 1)]
    159. void Divergence(uint3 id : SV_DispatchThreadID)
    160. {
    161.     if ( id.x < 0 || id.x >= _Size.x || id.y < 0 || id.y >= _Size.y) { return; }
    162.     const uint pos = clamp(id.y*_Size.x + id.x, 0, _Max);
    163.  
    164.     const uint4 n = GetNeighbours(id.xy, _Size);
    165.  
    166.     const float2 obsL = _Obstacles[n.x];
    167.     const float2 obsR = _Obstacles[n.y];
    168.     const float2 obsB = _Obstacles[n.z];
    169.     const float2 obsT = _Obstacles[n.w];
    170.  
    171.     const float x1 = (obsL.x > 0.0 || obsL.y > 0.0) ? 0.0 : _VelocityIn[n.x].x;
    172.     const float x2 = (obsR.x > 0.0 || obsR.y > 0.0) ? 0.0 : _VelocityIn[n.y].x;
    173.     const float y1 = (obsB.x > 0.0 || obsB.y > 0.0) ? 0.0 : _VelocityIn[n.z].y;
    174.     const float y2 = (obsT.x > 0.0 || obsT.y > 0.0) ? 0.0 : _VelocityIn[n.w].y;
    175.  
    176.     _Divergence[pos] = 0.5f * ((x2 - x1) + (y2 - y1));
    177. }
    178.  
    179. ////////////////////////////////////////////////////////////////////////////
    180. [numthreads(THREAD_COUNT, THREAD_COUNT, 1)]
    181. void Poisson(uint3 id : SV_DispatchThreadID)
    182. {
    183.     if ( id.x < 0 || id.x >= _Size.x || id.y < 0 || id.y >= _Size.y) { return; }
    184.     const uint pos = clamp(id.y*_Size.x + id.x, 0, _Max);
    185.  
    186.     //const float alpha = -1.0f;
    187.     const float rbeta = 0.25;
    188.  
    189.     const uint4 n = GetNeighbours(id.xy, _Size);
    190.  
    191.     const float2 obsL = _Obstacles[n.x];
    192.     const float2 obsR = _Obstacles[n.y];
    193.     const float2 obsB = _Obstacles[n.z];
    194.     const float2 obsT = _Obstacles[n.w];
    195.  
    196.     const float x1 = (obsL.x > 0.0 || obsL.y > 0.0) ? _PressureIn[pos] : _PressureIn[n.x];
    197.     const float x2 = (obsR.x > 0.0 || obsR.y > 0.0) ? _PressureIn[pos] : _PressureIn[n.y];
    198.     const float y1 = (obsB.x > 0.0 || obsB.y > 0.0) ? _PressureIn[pos] : _PressureIn[n.z];
    199.     const float y2 = (obsT.x > 0.0 || obsT.y > 0.0) ? _PressureIn[pos] : _PressureIn[n.w];
    200.  
    201.     const float b = _Divergence[pos];
    202.  
    203.     _PressureOut[pos] = (x1 + x2 + y1 + y2 - b) * rbeta;
    204. }
    205.  
    206. ////////////////////////////////////////////////////////////////////////////
    207. [numthreads(THREAD_COUNT, THREAD_COUNT, 1)]
    208. void SubstractGradient(uint3 id : SV_DispatchThreadID)
    209. {
    210.     if ( id.x < 0 || id.x >= _Size.x || id.y < 0 || id.y >= _Size.y) { return; }
    211.  
    212.     const uint4 n = GetNeighbours(id.xy, _Size);
    213.  
    214.     const uint pos = clamp(id.y*_Size.x + id.x, 0, _Max);
    215.    
    216.     const float2 obsL = _Obstacles[n.x];
    217.     const float2 obsR = _Obstacles[n.y];
    218.     const float2 obsB = _Obstacles[n.z];
    219.     const float2 obsT = _Obstacles[n.w];
    220.    
    221.     const float x1 = (obsL.x > 0.0 || obsL.y > 0.0)? _PressureIn[pos] : _PressureIn[n.x];
    222.     const float x2 = (obsR.x > 0.0 || obsR.y > 0.0)? _PressureIn[pos] : _PressureIn[n.y];
    223.     const float y1 = (obsB.x > 0.0 || obsB.y > 0.0)? _PressureIn[pos] : _PressureIn[n.z];
    224.     const float y2 = (obsT.x > 0.0 || obsT.y > 0.0)? _PressureIn[pos] : _PressureIn[n.w];
    225.  
    226.     _VelocityOut[pos].x = _VelocityIn[pos].x - 0.5f * (x2 - x1);
    227.     _VelocityOut[pos].y = _VelocityIn[pos].y - 0.5f * (y2 - y1);
    228. }
    229.  
    230. ////////////////////////////////////////////////////////////////////////////
    231. [numthreads(THREAD_COUNT, THREAD_COUNT, 1)]
    232. void CalcVorticity(uint3 id : SV_DispatchThreadID)
    233. {
    234.     if ( id.x < 0 || id.x >= _Size.x || id.y < 0 || id.y >= _Size.y) { return; }
    235.     const uint pos = clamp(id.y*_Size.x + id.x, 0, _Max);
    236.     const uint4 n = GetNeighbours(id.xy, _Size);
    237.  
    238.     const float2 vL = _VelocityIn[n.x];
    239.     const float2 vR = _VelocityIn[n.y];
    240.     const float2 vB = _VelocityIn[n.z];
    241.     const float2 vT = _VelocityIn[n.w];
    242.  
    243.     _Vorticity[pos] = 0.5 * ((vR.y - vL.y) - (vT.x - vB.x));
    244. }
    245.  
    246. ////////////////////////////////////////////////////////////////////////////
    247. [numthreads(THREAD_COUNT, THREAD_COUNT, 1)]
    248. void ApplyVorticity(uint3 id : SV_DispatchThreadID)
    249. {
    250.     if ( id.x < 0 || id.x >= _Size.x || id.y < 0 || id.y >= _Size.y) { return; }
    251.     const uint pos = clamp(id.y*_Size.x + id.x, 0, _Max);
    252.  
    253.     const uint4 n = GetNeighbours(id.xy, _Size);
    254.  
    255.     const float vL = _Vorticity[n.x];
    256.     const float vR = _Vorticity[n.y];
    257.     const float vB = _Vorticity[n.z];
    258.     const float vT = _Vorticity[n.w];
    259.     const float vC = _Vorticity[pos];
    260.  
    261.     float2 force = 0.5 * float2(abs(vT) - abs(vB), abs(vR) - abs(vL));
    262.  
    263.     const float EPSILON = 2.4414e-4;
    264.     const float magSqr = max(EPSILON, dot(force, force));
    265.    
    266.     force = force * rsqrt(magSqr);
    267.     force *= _VorticityScale * vC * float2(1, -1);
    268.    
    269.     const float2 final_force = force * _ElapsedTime;
    270.  
    271.     _VelocityOut[pos] = _VelocityIn[pos] + float2(final_force.x, final_force.y);
    272. }
    273.  
    274. ////////////////////////////////////////////////////////////////////////////
    275. float _Alpha;
    276. float _rBeta;
    277. [numthreads(THREAD_COUNT, THREAD_COUNT, 1)]
    278. void Viscosity(uint3 id : SV_DispatchThreadID)
    279. {
    280.     if ( id.x < 0 || id.x >= _Size.x || id.y < 0 || id.y >= _Size.y) { return; }
    281.     const uint pos = clamp(id.y*_Size.x + id.x, 0, _Max);
    282.     const uint4 n = GetNeighbours(id.xy, _Size);
    283.  
    284.     const float2 x1 = _VelocityIn[n.x];
    285.     const float2 x2 = _VelocityIn[n.y];
    286.     const float2 y1 = _VelocityIn[n.z];
    287.     const float2 y2 = _VelocityIn[n.w];
    288.     const float2 b = _VelocityIn[pos];
    289.  
    290.     _VelocityOut[pos] = (x1 + x2 + y1 + y2 + b * _Alpha) * _rBeta;
    291. }
    292.  
    293.  
    294. ////////////////////////////////////////////////////////////////////////////
    295. [numthreads(THREAD_COUNT, THREAD_COUNT, 1)]
    296. void AddCircleObstacle(uint3 id : SV_DispatchThreadID)
    297. {
    298.     if ( id.x < 0 || id.x >= _Size.x || id.y < 0 || id.y >= _Size.y) { return; }
    299.  
    300.     const uint pos = clamp(id.y*_Size.x + id.x, 0, _Max);
    301.     const float2 splat_pos = _Position*_Size;
    302.  
    303.     if (distance(splat_pos, (float2) id) <= _Radius)
    304.     {
    305.         if (_Static > 0)
    306.         {
    307.             _Obstacles[pos].y = 1.0;
    308.         }
    309.         else
    310.         {
    311.             _Obstacles[pos].x = 1.0;
    312.         }
    313.     }
    314. }
    315.  
    316.  
    317. ////////////////////////////////////////////////////////////////////////////
    318. float2 _P1;
    319. float2 _P2;
    320. float2 _P3;
    321. float Sign(float2 p1, float2 p2, float2 p3)
    322. {
    323.     return ((p1.x - p3.x) * (p2.y - p3.y)) - ((p2.x - p3.x) * (p1.y - p3.y));
    324. }
    325.  
    326. bool IsPointInTriangle(float2 pt, float2 v1, float2 v2, float2 v3)
    327. {
    328.     const bool b1 = Sign(pt, v1, v2) < 0.0f;
    329.     const bool b2 = Sign(pt, v2, v3) < 0.0f;
    330.     const bool b3 = Sign(pt, v3, v1) < 0.0f;
    331.     return (b1 == b2) && (b2 == b3);
    332. }
    333.  
    334. [numthreads(THREAD_COUNT, THREAD_COUNT, 1)]
    335. void AddTriangleObstacle(uint3 id : SV_DispatchThreadID)
    336. {
    337.     if ( id.x < 0 || id.x >= _Size.x || id.y < 0 || id.y >= _Size.y) { return; }
    338.     const float2 pt = float2(id.x, id.y) / float2(_Size);
    339.     if (IsPointInTriangle(pt, _P1, _P2, _P3))
    340.     {
    341.         const uint pos = clamp(id.y*_Size.x + id.x, 0, _Max);
    342.         if (_Static > 0)
    343.         {
    344.             _Obstacles[pos].y = 1.0;
    345.         }
    346.         else
    347.         {
    348.             _Obstacles[pos].x = 1.0;
    349.         }
    350.     }
    351. }
    352.  
    353.  
     

    Attached Files:

    milkywong likes this.
unityunity