main.lua 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. -- Surround yourself with monkeys and efficiently move them with compute shaders
  2. ASSUME_FRAMERATE = 1/120
  3. function lovr.load()
  4. MONKEYS = 500
  5. -- Create some random transforms
  6. local random, randomNormal = lovr.math.random, lovr.math.randomNormal
  7. local transforms = {}
  8. for i = 1, MONKEYS do
  9. local position = vec3(randomNormal(8), randomNormal(8), randomNormal(8))
  10. local orientation = quat(random(2 * math.pi), random(), random(), random())
  11. local scale = vec3(.75)
  12. transforms[i] = mat4(position, scale, orientation)
  13. end
  14. -- More random transforms-- this will correspond to the transform applied to each monkey per frame
  15. local offsets = {}
  16. for i = 1, MONKEYS do
  17. local position = vec3(randomNormal(1), randomNormal(8), randomNormal(8)):mul(ASSUME_FRAMERATE)
  18. local radianSwing = ASSUME_FRAMERATE * math.pi / 2
  19. local orientation = quat(random(-radianSwing, radianSwing), random(), random(), random())
  20. local scale = vec3(1)
  21. offsets[i] = mat4(position, scale, orientation)
  22. end
  23. -- Create a Buffer to store positions for lots of models
  24. transformBuffer = lovr.graphics.newBuffer(transforms, 'mat4')
  25. offsetBuffer = lovr.graphics.newBuffer(offsets, 'mat4')
  26. -- Create the compute shader, we will run this once per frame
  27. computeShader = lovr.graphics.newShader([[
  28. layout(local_size_x = 32, local_size_y = 1, local_size_z = 1) in;
  29. layout(set = 0, binding = 0) buffer TransformBuffer { mat4 Transforms[]; };
  30. layout(set = 0, binding = 1) buffer OffsetBuffer { mat4 Offsets[]; };
  31. Constants {
  32. uint monkeyCount;
  33. };
  34. void lovrmain() {
  35. uint i = GlobalThreadID.x;
  36. if (i >= monkeyCount) return;
  37. Transforms[i] = Transforms[i] * Offsets[i];
  38. }
  39. ]])
  40. -- Create the display shader, injecting the shader code for the block
  41. shader = lovr.graphics.newShader([[
  42. layout(set = 2, binding = 0) buffer TransformBuffer { mat4 Transforms[]; };
  43. vec4 lovrmain() {
  44. return Projection * View * Transforms[InstanceIndex] * Transform * VertexPosition;
  45. }
  46. ]], 'normal')
  47. model = lovr.graphics.newModel('monkey.obj')
  48. end
  49. -- Draw many copies of the model using instancing, with transforms from a buffer
  50. function lovr.draw(pass)
  51. pass:setShader(computeShader)
  52. pass:send('monkeyCount', MONKEYS)
  53. pass:send('TransformBuffer', transformBuffer)
  54. pass:send('OffsetBuffer', offsetBuffer)
  55. pass:compute(math.ceil(MONKEYS / 32))
  56. pass:setShader(shader)
  57. pass:send('TransformBuffer', transformBuffer)
  58. pass:setCullMode('back')
  59. pass:setBlendMode(nil)
  60. pass:draw(model, mat4(), MONKEYS)
  61. end