particles.odin 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. package particles
  2. import rl "vendor:raylib"
  3. import "core:math"
  4. import r3d "../r3d"
  5. MAX_PARTICLES :: 4096
  6. Particle :: struct {
  7. pos: rl.Vector3,
  8. vel: rl.Vector3,
  9. life: f32,
  10. }
  11. main :: proc() {
  12. // Initialize window
  13. rl.InitWindow(800, 450, "[r3d] - Particles example")
  14. defer rl.CloseWindow()
  15. rl.SetTargetFPS(60)
  16. // Initialize R3D
  17. r3d.Init(rl.GetScreenWidth(), rl.GetScreenHeight())
  18. defer r3d.Close()
  19. // Set environment
  20. env := r3d.GetEnvironment()
  21. env.background.color = {4, 4, 4, 255}
  22. env.bloom.mode = .ADDITIVE
  23. // Generate a gradient as emission texture for our particles
  24. image := rl.GenImageGradientRadial(64, 64, 0.0, rl.WHITE, rl.BLACK)
  25. texture := rl.LoadTextureFromImage(image)
  26. defer rl.UnloadTexture(texture)
  27. rl.UnloadImage(image)
  28. // Generate a quad mesh for our particles
  29. mesh := r3d.GenMeshQuad(0.25, 0.25, 1, 1, {0, 0, 1})
  30. defer r3d.UnloadMesh(mesh)
  31. // Setup particle material
  32. material := r3d.GetDefaultMaterial()
  33. defer r3d.UnloadMaterial(material)
  34. material.billboardMode = .FRONT
  35. material.blendMode = .ADDITIVE
  36. material.albedo.texture = r3d.GetBlackTexture()
  37. material.emission.color = {255, 0, 0, 255}
  38. material.emission.texture = texture
  39. material.emission.energy = 1.0
  40. // Create particle instance buffer
  41. instances := r3d.LoadInstanceBuffer(MAX_PARTICLES, {.POSITION})
  42. defer r3d.UnloadInstanceBuffer(instances)
  43. // Setup camera
  44. camera: rl.Camera3D = {
  45. position = {-7, 7, -7},
  46. target = {0, 1, 0},
  47. up = {0, 1, 0},
  48. fovy = 60.0,
  49. projection = .PERSPECTIVE,
  50. }
  51. // CPU buffer for storing particles
  52. particles: [MAX_PARTICLES]Particle
  53. positions: [MAX_PARTICLES]rl.Vector3
  54. particleCount: i32 = 0
  55. for !rl.WindowShouldClose()
  56. {
  57. dt := rl.GetFrameTime()
  58. rl.UpdateCamera(&camera, rl.CameraMode.ORBITAL)
  59. // Spawn particles
  60. for i in 0..<10 {
  61. if particleCount < MAX_PARTICLES {
  62. angle := f32(rl.GetRandomValue(0, 360)) * rl.DEG2RAD
  63. particles[particleCount].pos = {0, 0, 0}
  64. particles[particleCount].vel = {
  65. math.cos_f32(angle) * f32(rl.GetRandomValue(20, 40)) / 10.0,
  66. f32(rl.GetRandomValue(60, 80)) / 10.0,
  67. math.sin_f32(angle) * f32(rl.GetRandomValue(20, 40)) / 10.0,
  68. }
  69. particles[particleCount].life = 1.0
  70. particleCount += 1
  71. }
  72. }
  73. // Update particles
  74. alive: i32 = 0
  75. for i in 0..<particleCount {
  76. particles[i].vel.y -= 9.81 * dt
  77. particles[i].pos.x += particles[i].vel.x * dt
  78. particles[i].pos.y += particles[i].vel.y * dt
  79. particles[i].pos.z += particles[i].vel.z * dt
  80. particles[i].life -= dt * 0.5
  81. if particles[i].life > 0 {
  82. positions[alive] = particles[i].pos
  83. particles[alive] = particles[i]
  84. alive += 1
  85. }
  86. }
  87. particleCount = alive
  88. r3d.UploadInstances(instances, {.POSITION}, 0, particleCount, raw_data(positions[:]))
  89. rl.BeginDrawing()
  90. r3d.Begin(camera)
  91. r3d.DrawMeshInstanced(mesh, material, instances, particleCount)
  92. r3d.End()
  93. rl.DrawFPS(10, 10)
  94. rl.EndDrawing()
  95. }
  96. }