summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.c192
1 files changed, 120 insertions, 72 deletions
diff --git a/main.c b/main.c
index 49ca8e2..6f620b5 100644
--- a/main.c
+++ b/main.c
@@ -17,7 +17,13 @@
// custom SDL_USEREVENT code for timer
#define EVENT_CODE_TIMER 0
+// use compute shader to update particles?
+#define USE_COMPUTE_SHADER false
+
+// number of particles
#define NUM_PARTICLES 1000
+
+// number of compute shader workgroups
#define WORKGROUP_SIZE 1
typedef struct {
@@ -100,7 +106,8 @@ fs_src[] =
"uniform mediump float time;\n"
"\n"
"void main() {\n"
- " color = vec4(colors[instance_id].rgb, 1) * (0.5f + 0.5 * sin(time * 3.141));\n"
+ " mediump float alpha = 0.5f + 0.5f * (0.5f + 0.5 * sin(time * 3.141));\n"
+ " color = vec4(colors[instance_id].rgb, 1) * alpha;\n"
"}\n";
static const shader_t
@@ -183,6 +190,113 @@ link_program(
return r;
}
+static float
+color_map(uint8_t bits) {
+ switch (bits & 0x3) {
+ case 0x3:
+ return 1.0;
+ case 0x2:
+ return 0.75;
+ case 0x1:
+ return 0.5;
+ default:
+ return 0.25;
+ }
+}
+
+static GLuint
+init_particles(void) {
+ // create shader storage buffer
+ GLuint ssbo;
+ glGenBuffers(1, &ssbo);
+
+ // generate seed data
+ uint8_t seeds[5 * NUM_PARTICLES];
+ if (!RAND_bytes(seeds, 5 * NUM_PARTICLES)) {
+ SDL_Log("RAND_bytes() failed");
+ exit(EXIT_FAILURE);
+ }
+
+ // populate data
+ float data[3 * 4 * NUM_PARTICLES];
+ #pragma omp parallel for
+ for (int i = 0; i < NUM_PARTICLES; i++) {
+ float x = 2.0 * seeds[5 * i + 0] / 0xFF - 1.0,
+ y = 2.0 * seeds[5 * i + 1] / 0xFF - 1.0;
+
+ // SDL_Log("%f,%f", x, y);
+
+ // populate position
+ data[4 * i + 0] = x;
+ data[4 * i + 1] = y;
+ data[4 * i + 2] = 0.0;
+ data[4 * i + 3] = 1.0;
+
+ // populate random velocity
+ data[4 * (NUM_PARTICLES + i) + 0] = 2.0 * seeds[5 * i + 2] / 0xFF - 1.0;
+ data[4 * (NUM_PARTICLES + i) + 1] = 2.0 * seeds[5 * i + 3] / 0xFF - 1.0;
+
+ // populate colors
+ uint8_t cs = seeds[5 * i + 4];
+ data[4 * (2 * NUM_PARTICLES + i) + 0] = color_map(cs & 0x3);
+ data[4 * (2 * NUM_PARTICLES + i) + 1] = color_map((cs >> 2) & 0x3);
+ data[4 * (2 * NUM_PARTICLES + i) + 2] = color_map((cs >> 4) & 0x3);
+ data[4 * (2 * NUM_PARTICLES + i) + 3] = 1.0;
+ }
+
+ // populate buffer
+ glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
+ glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
+ glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
+
+ // return buffer
+ return ssbo;
+}
+
+static void
+update_particles(
+ const GLuint ssbo,
+ const GLuint compute_prog
+) {
+ if (USE_COMPUTE_SHADER) {
+ UNUSED(ssbo);
+ glUseProgram(compute_prog);
+ glDispatchCompute(NUM_PARTICLES / WORKGROUP_SIZE, 1, 1);
+ glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
+ } else {
+ UNUSED(compute_prog);
+ glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
+
+ // map buffer
+ float *data = glMapBufferRange(
+ GL_SHADER_STORAGE_BUFFER,
+ 0,
+ 3 * NUM_PARTICLES * 4 * sizeof(float),
+ GL_MAP_READ_BIT | GL_MAP_WRITE_BIT
+ );
+
+ #pragma omp parallel for
+ for (int i = 0; i < NUM_PARTICLES; i++) {
+ data[4 * i + 0] += 0.016 * data[4 * (NUM_PARTICLES + i) + 0];
+ if (data[4 * i + 0] < -1.1) {
+ data[4 * i + 0] += 2.2;
+ } else if (data[4 * i + 0] > 1.1) {
+ data[4 * i + 0] -= 2.2;
+ }
+
+ data[4 * i + 1] += 0.016 * data[4 * (NUM_PARTICLES + i) + 1];
+ if (data[4 * i + 1] < -1.1) {
+ data[4 * i + 1] += 2.2;
+ } else if (data[4 * i + 1] > 1.1) {
+ data[4 * i + 1] -= 2.2;
+ }
+ }
+
+ glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
+ glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
+ }
+}
+
static void
update_viewport(
SDL_Window *win
@@ -350,7 +464,8 @@ handle_events(
}
}
-static Uint32 timer_cb(
+static Uint32
+timer_cb(
Uint32 interval,
void *arg
) {
@@ -371,69 +486,6 @@ static Uint32 timer_cb(
return interval;
}
-static float
-color_map(uint8_t bits) {
- switch (bits & 0x3) {
- case 0x3:
- return 1.0;
- case 0x2:
- return 0.75;
- case 0x1:
- return 0.5;
- default:
- return 0.25;
- }
-}
-
-static GLuint
-init_particles(void) {
- // create shader storage buffer
- GLuint ssbo;
- glGenBuffers(1, &ssbo);
-
- // generate seed data
- uint8_t seeds[5 * NUM_PARTICLES];
- if (!RAND_bytes(seeds, 5 * NUM_PARTICLES)) {
- SDL_Log("RAND_bytes() failed");
- exit(EXIT_FAILURE);
- }
-
- // populate data
- float data[3 * 4 * NUM_PARTICLES];
- #pragma omp parallel for
- for (int i = 0; i < NUM_PARTICLES; i++) {
- float x = 2.0 * seeds[5 * i + 0] / 0xFF - 1.0,
- y = 2.0 * seeds[5 * i + 1] / 0xFF - 1.0;
-
- // SDL_Log("%f,%f", x, y);
-
- // populate position
- data[4 * i + 0] = x;
- data[4 * i + 1] = y;
- data[4 * i + 2] = 0.0;
- data[4 * i + 3] = 1.0;
-
- // populate random velocity
- data[4 * (NUM_PARTICLES + i) + 0] = 2.0 * seeds[5 * i + 2] / 0xFF - 1.0;
- data[4 * (NUM_PARTICLES + i) + 1] = 2.0 * seeds[5 * i + 3] / 0xFF - 1.0;
-
- // populate colors
- uint8_t cs = seeds[5 * i + 4];
- data[4 * (2 * NUM_PARTICLES + i) + 0] = color_map(cs & 0x3);
- data[4 * (2 * NUM_PARTICLES + i) + 1] = color_map((cs >> 2) & 0x3);
- data[4 * (2 * NUM_PARTICLES + i) + 2] = color_map((cs >> 4) & 0x3);
- data[4 * (2 * NUM_PARTICLES + i) + 3] = 1.0;
- }
-
- // populate buffer
- glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
- glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
- glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
-
- // return buffer
- return ssbo;
-}
-
int main(int argc, char *argv[]) {
UNUSED(argc);
UNUSED(argv);
@@ -466,7 +518,7 @@ int main(int argc, char *argv[]) {
// unbind vao
glBindVertexArray(0);
- // link compute program, get uniforms
+ // link compute program
GLuint compute_prog = link_program(1, COMPUTE_SHADERS);
// GLint u_delta = glGetUniformLocation(compute_prog, "delta");
@@ -482,12 +534,8 @@ int main(int argc, char *argv[]) {
// save start time
ctx.times[ctx.times_ofs].draw_start = now;
- // disabled, crashing
-/*
- * glUseProgram(compute_prog);
- * glDispatchCompute(NUM_PARTICLES / WORKGROUP_SIZE, 1, 1);
- * glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
- */
+ // update particles
+ update_particles(ssbo, compute_prog);
// clear screen
glClearColor(0, 0, 0, 1);