115c1fe1136f3e6a7dc9f6f896d6bbb35942bca4
[carveJwlIkooP6JGAAIwe30JlM.git] / particle.c
1 #include "particle.h"
2
3 static void particle_spawn( particle_system *sys,
4 v3f co, v3f v, f32 lifetime, u32 colour ){
5 if( sys->alive == sys->max ) return;
6
7 particle *p = &sys->array[ sys->alive ++ ];
8 v3_copy( co, p->co );
9 v3_copy( v, p->v );
10 p->life = lifetime;
11 p->colour = colour;
12 }
13
14 static void particle_system_update( particle_system *sys, f32 dt ){
15 u32 i = 0;
16 iter: if( i == sys->alive ) return;
17
18 particle *p = &sys->array[i];
19 p->life -= dt;
20
21 if( p->life < 0.0f ){
22 *p = sys->array[ -- sys->alive ];
23 goto iter;
24 }
25
26 v3_muladds( p->co, p->v, dt, p->co );
27 p->v[1] += -9.8f * dt;
28
29 i ++;
30 goto iter;
31 }
32
33 static void particle_system_debug( particle_system *sys ){
34 for( u32 i=0; i<sys->alive; i ++ ){
35 particle *p = &sys->array[i];
36 v3f p1;
37 v3_muladds( p->co, p->v, 0.2f, p1 );
38 vg_line( p->co, p1, p->colour );
39 }
40 }
41
42 struct particle_init_args {
43 particle_system *sys;
44 u16 indices[];
45 };
46
47 static void async_particle_init( void *payload, u32 size ){
48 struct particle_init_args *args = payload;
49 particle_system *sys = args->sys;
50
51 glGenVertexArrays( 1, &sys->vao );
52 glGenBuffers( 1, &sys->vbo );
53 glGenBuffers( 1, &sys->ebo );
54 glBindVertexArray( sys->vao );
55
56 size_t stride = sizeof(particle_vert);
57
58 glBindBuffer( GL_ARRAY_BUFFER, sys->vbo );
59 glBufferData( GL_ARRAY_BUFFER, sys->max*stride*4, NULL, GL_DYNAMIC_DRAW );
60 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, sys->ebo );
61 glBufferData( GL_ELEMENT_ARRAY_BUFFER,
62 sys->max*sizeof(u16)*6, args->indices, GL_STATIC_DRAW );
63
64 /* 0: coordinates */
65 glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0 );
66 glEnableVertexAttribArray( 0 );
67
68 /* 3: colour */
69 glVertexAttribPointer( 1, 4, GL_UNSIGNED_BYTE, GL_TRUE,
70 stride, (void *)offsetof(particle_vert, colour) );
71 glEnableVertexAttribArray( 1 );
72
73 VG_CHECK_GL_ERR();
74 }
75
76 static void particle_init( particle_system *sys, u32 max ){
77 static int reg = 1;
78 if( reg ){
79 shader_particle_register();
80 reg = 0;
81 }
82
83 size_t stride = sizeof(particle_vert);
84
85 particles_grind.max = max;
86 particles_grind.array =
87 vg_linear_alloc( vg_mem.rtmemory, max*sizeof(particle) );
88 particles_grind.vertices =
89 vg_linear_alloc( vg_mem.rtmemory, max*stride*4 );
90
91 vg_async_item *call =
92 vg_async_alloc( sizeof(particle_system *) + max*sizeof(u16)*6 );
93 struct particle_init_args *init = call->payload;
94 init->sys = sys;
95
96 for( u32 i=0; i<max; i ++ ){
97 init->indices[i*6+0] = i*4;
98 init->indices[i*6+1] = i*4+1;
99 init->indices[i*6+2] = i*4+2;
100 init->indices[i*6+3] = i*4;
101 init->indices[i*6+4] = i*4+2;
102 init->indices[i*6+5] = i*4+3;
103 }
104
105 vg_async_dispatch( call, async_particle_init );
106 }
107
108 static void particle_system_prerender( particle_system *sys ){
109 for( u32 i=0; i<sys->alive; i ++ ){
110 particle *p = &sys->array[i];
111 particle_vert *vs = &sys->vertices[i*4];
112
113 v3f v, right;
114 v3_copy( p->v, v );
115 v3_normalize( v );
116 v3_cross( v, (v3f){0,1,0}, right );
117
118 f32 l = 0.3f, w = 0.025f;
119
120 v3f p0, p1;
121 v3_muladds( p->co, p->v, l, p0 );
122 v3_muladds( p->co, p->v, -l, p1 );
123
124 v3_muladds( p0, right, w, vs[0].co );
125 v3_muladds( p1, right, w, vs[1].co );
126 v3_muladds( p1, right, -w, vs[2].co );
127 v3_muladds( p0, right, -w, vs[3].co );
128
129 vs[0].colour = p->colour;
130 vs[1].colour = p->colour;
131 vs[2].colour = p->colour;
132 vs[3].colour = p->colour;
133 }
134
135 glBindVertexArray( sys->vao );
136
137 size_t stride = sizeof(particle_vert);
138 glBindBuffer( GL_ARRAY_BUFFER, sys->vbo );
139 glBufferSubData( GL_ARRAY_BUFFER, 0, sys->alive*stride*4, sys->vertices );
140 }
141
142 static void particle_system_render( particle_system *sys, camera *cam ){
143 glDisable( GL_CULL_FACE );
144 glDisable( GL_DEPTH_TEST );
145
146 shader_particle_use();
147 shader_particle_uPv( cam->mtx.pv );
148 shader_particle_uPvPrev( cam->mtx_prev.pv );
149
150 glBindVertexArray( sys->vao );
151 glDrawElements( GL_TRIANGLES, sys->alive*6, GL_UNSIGNED_SHORT, NULL );
152 }