ParticleUpdateCS.hlsl 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. // RUN: %dxc -E main -T cs_6_0 %s | FileCheck %s
  2. // CHECK: threadId
  3. // CHECK: FMin
  4. // CHECK: dot3
  5. // CHECK: bufferUpdateCounter
  6. // CHECK: bufferUpdateCounter
  7. //
  8. // Copyright (c) Microsoft. All rights reserved.
  9. // This code is licensed under the MIT License (MIT).
  10. // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
  11. // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
  12. // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
  13. // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
  14. //
  15. // Developed by Minigraph
  16. //
  17. // Author: James Stanard
  18. // Julia Careaga
  19. //
  20. #include "ParticleUpdateCommon.hlsli"
  21. #include "ParticleUtility.hlsli"
  22. cbuffer CB : register(b0)
  23. {
  24. float gElapsedTime;
  25. };
  26. StructuredBuffer< ParticleSpawnData > g_ResetData : register( t0 );
  27. StructuredBuffer< ParticleMotion > g_InputBuffer : register( t1 );
  28. RWStructuredBuffer< ParticleVertex > g_VertexBuffer : register( u0 );
  29. RWStructuredBuffer< ParticleMotion > g_OutputBuffer : register( u2 );
  30. [RootSignature(Particle_RootSig)]
  31. [numthreads(64, 1, 1)]
  32. void main( uint3 DTid : SV_DispatchThreadID )
  33. {
  34. if (DTid.x >= MaxParticles)
  35. return;
  36. ParticleMotion ParticleState = g_InputBuffer[ DTid.x ];
  37. ParticleSpawnData rd = g_ResetData[ ParticleState.ResetDataIndex ];
  38. // Update age. If normalized age exceeds 1, the particle does not renew its lease on life.
  39. ParticleState.Age += gElapsedTime * rd.AgeRate;
  40. if (ParticleState.Age >= 1.0)
  41. return;
  42. // Update position. Compute two deltas to support rebounding off the ground plane.
  43. float StepSize = (ParticleState.Position.y > 0.0 && ParticleState.Velocity.y < 0.0) ?
  44. min(gElapsedTime, ParticleState.Position.y / -ParticleState.Velocity.y) : gElapsedTime;
  45. ParticleState.Position += ParticleState.Velocity * StepSize;
  46. ParticleState.Velocity += Gravity * ParticleState.Mass * StepSize;
  47. // Rebound off the ground if we didn't consume all of the elapsed time
  48. StepSize = gElapsedTime - StepSize;
  49. if (StepSize > 0.0)
  50. {
  51. ParticleState.Velocity = reflect(ParticleState.Velocity, float3(0, 1, 0)) * Restitution;
  52. ParticleState.Position += ParticleState.Velocity * StepSize;
  53. ParticleState.Velocity += Gravity * ParticleState.Mass * StepSize;
  54. }
  55. // The spawn dispatch will be simultaneously adding particles as well. It's possible to overflow.
  56. uint index = g_OutputBuffer.IncrementCounter();
  57. if (index >= MaxParticles)
  58. return;
  59. g_OutputBuffer[index] = ParticleState;
  60. //
  61. // Generate a sprite vertex
  62. //
  63. ParticleVertex Sprite;
  64. Sprite.Position = ParticleState.Position;
  65. Sprite.TextureID = TextureID;
  66. // Update size and color
  67. Sprite.Size = lerp(rd.StartSize, rd.EndSize, ParticleState.Age);
  68. Sprite.Color = lerp(rd.StartColor, rd.EndColor, ParticleState.Age);
  69. // ...Originally from Reflex...
  70. // Use a trinomial to smoothly fade in a particle at birth and fade it out at death.
  71. Sprite.Color *= ParticleState.Age * (1.0 - ParticleState.Age) * (1.0 - ParticleState.Age) * 6.7;
  72. g_VertexBuffer[ g_VertexBuffer.IncrementCounter() ] = Sprite;
  73. }