]>
Witch of Git - lovr-particles/blob - main.lua
1 local vec3
= lovr
.math
.vec3
2 local mat4
= lovr
.math
.mat4
3 local quat
= lovr
.math
.quat
5 local nParticles
= 2 ^
14
7 local batches
= nParticles
/ batchSize
18 features
= lovr
.graphics
.getFeatures()
19 shaders
.particles
= lovr
.graphics
.newShader("shaders/particles.vert", "shaders/particles.frag")
21 blocks
.particles
= lovr
.graphics
.newShaderBlock("compute", {
22 -- Reading a value seems to work around whatever the rendering glitch
23 -- was. So we include this flag so we only have to ask for a single
24 -- value, instead of having to copy a large array. Still, annoying :(
25 -- For reference, see issue comment at:
26 -- https://github.com/bjornbytes/lovr/issues/211#issuecomment-580985010
28 particles
= {"mat4", nParticles
},
29 }, { readable
= true })
30 shaders
.particles
:sendBlock('particleData', blocks
.particles
)
31 shaders
.particles
:send("batchSize", batchSize
)
33 meshes
.particle
= makeParticleMesh(batchSize
)
35 compute
.particles
= lovr
.graphics
.newComputeShader("shaders/particles.comp")
36 compute
.particles
:sendBlock('particleData', blocks
.particles
)
37 compute
.particles
:send("dt", dt
)
39 local xr
, yr
, zr
= range(-1, 1), range(1, 3), range(-1, -0.5)
40 local sr
, vr
= range(0.005, 0.01), range(-0.05, 0.05)
41 local initial
= initialParticleData(nParticles
, xr
, yr
, zr
, sr
, vr
)
42 blocks
.particles
:send("particles", initial
)
44 for _
, hand
in ipairs(lovr
.headset
.getHands()) do
45 local x
, y
, z
= lovr
.headset
.getPose(hand
)
47 pos
= lovr
.math
.newVec3(x
, y
, z
),
48 vel
= lovr
.math
.newVec3(0, 0, 0),
49 rot
= lovr
.math
.newQuat(),
56 local x
, y
, z
= lovr
.headset
.getPose("head")
57 shaders
.particles
:send("headPos", vec3(x
, y
, z
))
60 for _
, hand
in ipairs(lovr
.headset
.getHands()) do
61 local x
, y
, z
, a
, ax
, ay
, az
= lovr
.headset
.getPose(hand
)
62 local pos
= vec3(x
, y
, z
)
63 hands
[hand
].vel
:set((pos
- hands
[hand
].pos
) / dt
)
64 hands
[hand
].pos
:set(pos
)
65 hands
[hand
].rot
:set(a
, ax
, ay
, az
)
66 table.insert(positions
, pos
)
67 table.insert(velocities
, hands
[hand
].vel
)
69 compute
.particles
:send("handPos", positions
)
70 compute
.particles
:send("handVel", velocities
)
72 lovr
.graphics
.compute(compute
.particles
, batches
)
73 -- Read the buffer to force SSBO synch of some sort.
74 blocks
.particles
:read("reloadFlag")
76 lovr
.graphics
.setColor(0.6, 0.1, 0)
77 lovr
.graphics
.setShader(nil)
78 for _
, hand
in pairs(hands
) do
79 -- local x, y, z = hand.pos:unpack()
80 lovr
.graphics
.cube("fill", hand
.pos
, 0.1, hand
.rot
)
83 withDepthTest("lequal", false, function()
84 lovr
.graphics
.setColor(1, 1, 1)
85 lovr
.graphics
.setShader(shaders
.particles
)
86 meshes
.particle
:draw(mat4(), batches
)
90 function makeParticleMesh(size
)
91 local format = { {'vertPosition', 'float', 2}, }
94 local insert
= table.insert
95 for chunk
= 1, size
do
96 insert(verts
, { 1, 1})
97 insert(verts
, { 1, -1})
98 insert(verts
, {-1, -1})
99 insert(verts
, {-1, 1})
100 local base
= 4 * (chunk
- 1)
101 insert(vertMap
, 3 + base
)
102 insert(vertMap
, 2 + base
)
103 insert(vertMap
, 1 + base
)
104 insert(vertMap
, 4 + base
)
105 insert(vertMap
, 3 + base
)
106 insert(vertMap
, 1 + base
)
108 local mesh
= lovr
.graphics
.newMesh(format, verts
, "triangles", "static")
109 mesh
:setVertexMap(vertMap
)
113 function range(min, max)
114 local scale
= max - min
116 return min + lovr
.math
.random() * scale
120 function initialParticleData(size
, xRange
, yRange
, zRange
, sRange
, vRange
)
122 local insert
= table.insert
125 xRange(), yRange(), zRange(), sRange(),
126 vRange(), vRange(), vRange(), 1,
134 function withDepthTest(compareMode
, write, callback
)
135 local oldComp
, oldWrite
= lovr
.graphics
.getDepthTest()
136 lovr
.graphics
.setDepthTest(compareMode
, write)
138 lovr
.graphics
.setDepthTest(oldComp
, oldWrite
)