diff options
author | Vito Caputo <vcaputo@pengaru.com> | 2022-12-29 17:14:38 -0800 |
---|---|---|
committer | Vito Caputo <vcaputo@pengaru.com> | 2022-12-29 17:14:38 -0800 |
commit | 4cde73239ee3a7cfa4a83a3f9d8a20effdb115ed (patch) | |
tree | dcf7ea64487fa40ec08c984abd729f597300e857 | |
parent | 79a1c4c1295328cc59e9b8643d2125f38fb11038 (diff) |
plasma-node,shader-node: break out maga plasma shaderrev4
Performing the maga branch in the shader slows things down
considerably.
This commit gets rid of the in-shader branch by splitting the
plasma fragment shader into maga and non-maga variants.
This required adding shader vector support to shader-node so
multiple shaders could be supplied, with a selector index pointer
used to pick which is used by the render function.
-rw-r--r-- | src/game.c | 2 | ||||
-rw-r--r-- | src/plasma-node.c | 137 | ||||
-rw-r--r-- | src/plasma-node.h | 2 | ||||
-rw-r--r-- | src/shader-node.c | 106 | ||||
-rw-r--r-- | src/shader-node.h | 23 |
5 files changed, 209 insertions, 61 deletions
@@ -227,7 +227,7 @@ typedef struct game_t { mask_t *mask; teepee_t *teepee; entity_t *new_infections; - int is_maga; + unsigned is_maga; float infections_rate, infections_rate_smoothed; /* 0-1 for none-max */ virus_t *viruses[GAME_NUM_VIRUSES]; m4f_t score_digits_x[10]; diff --git a/src/plasma-node.c b/src/plasma-node.c index 8afdb75..24b799a 100644 --- a/src/plasma-node.c +++ b/src/plasma-node.c @@ -26,7 +26,7 @@ #include "m4f.h" typedef struct plasma_node_t { - int *maga; + unsigned *maga; float *gloom; } plasma_node_t; @@ -74,7 +74,6 @@ static const char *plasma_fs = "" "uniform float alpha;" "uniform float time;" "uniform float gloom;" - "uniform int maga;" " float dostar(vec2 uv, float size) {" " uv.x = abs(uv.x);" @@ -98,6 +97,7 @@ static const char *plasma_fs = "" "void main() {" " float v;" " float stime = sin(time * .01) * 100.0;" + " vec3 col;" #ifdef __EMSCRIPTEN__ " vec2 c = UV;" @@ -118,24 +118,84 @@ static const char *plasma_fs = "" " v += sin(sqrt(c.x * c.x + c.y * c.y + 1.0) + stime);" - " if (maga == 1) {" - " float r, g, b;" - " float star = dostar(mod(cc, .2) - .1, (sin(time + c.x + c.y) * .5 + .5) * .01 + .01);" - " b = smoothstep(.25, .8, cos(2.666 * PI + PI * v + sin(time)));" - " star *= b;" - " b = max(star, b);" - " r = max(smoothstep(.25, .8, cos(PI * v + sin(time))), star);" - " g = max(smoothstep(.25, .8, cos(1.333 * PI + PI * v + sin(time))), star);" - - " gl_FragColor = vec4(max(r, g), g, max(b, g), 1.);" - " } else {" - " vec3 col = vec3(cos(PI * v + sin(time)), sin(PI * v + cos(time * .33)), cos(PI * v + sin(time * .66)));" - " gl_FragColor = vec4((col * .5 + .5) * (1. - gloom), alpha);" - " }" + " col = vec3(cos(PI * v + sin(time)), sin(PI * v + cos(time * .33)), cos(PI * v + sin(time * .66)));" + " gl_FragColor = vec4((col * .5 + .5) * (1. - gloom), alpha);" "}" ""; +static const char *plasma_maga_fs = "" +#ifdef __EMSCRIPTEN__ + "#version 100\n" +#else + "#version 120\n" +#endif + + "#define PI 3.1415926535897932384626433832795\n" + +#ifdef __EMSCRIPTEN__ + "precision mediump float;" + "varying vec2 UV;" +#endif + + "uniform float alpha;" + "uniform float time;" + "uniform float gloom;" + +" float dostar(vec2 uv, float size) {" +" uv.x = abs(uv.x);" +" float a = 6.2832/5.;" +" float d1 = dot(uv, vec2(sin(a), cos(a)));" +" a = 3. * 6.2832/5.;" +" float d2 = dot(uv, vec2(sin(a), cos(a)));" +" a = 2. * 6.2832/5.;" +" float d4 = dot(uv, vec2(sin(a), cos(a)));" +" float d = min(max(d1, d2), max(uv.y, d4));" +#ifdef __EMSCRIPTEN__ + /* GLSL 1.0 lacks fwidth() */ +" float w = .001;" +#else +" float w = fwidth(d);" +#endif + +" return smoothstep(w, -w, d - size);" +" }" + + "void main() {" + " float v;" + " float stime = sin(time * .01) * 100.0;" + " float star, r, g, b;" + +#ifdef __EMSCRIPTEN__ + " vec2 c = UV;" +#else + " vec2 c = gl_TexCoord[0].st;" +#endif + " vec2 cc = c;" + + // this zooms the texture coords in and out a bit with time + " c *= (sin(stime * .01) *.5 + .5) * 3.0 + 1.0;" + + // plasma calculations, stime instead of time directly to vary directions and speed + " v = sin((c.x + stime));" + " v += sin((c.y + stime) * .5);" + " v += sin((c.x + c.y +stime) * .5);" + + " c += vec2(sin(stime * .33), cos(stime * .5)) * 3.0;" + + " v += sin(sqrt(c.x * c.x + c.y * c.y + 1.0) + stime);" + + " star = dostar(mod(cc, .2) - .1, (sin(time + c.x + c.y) * .5 + .5) * .01 + .01);" + " b = smoothstep(.25, .8, cos(2.666 * PI + PI * v + sin(time)));" + " star *= b;" + " b = max(star, b);" + " r = max(smoothstep(.25, .8, cos(PI * v + sin(time))), star);" + " g = max(smoothstep(.25, .8, cos(1.333 * PI + PI * v + sin(time))), star);" + + " gl_FragColor = vec4(max(r, g), g, max(b, g), 1.);" + "}" +""; + static void plasma_uniforms(void *uniforms_ctxt, void *render_ctxt, unsigned n_uniforms, const int *uniforms, const m4f_t *model_x, float alpha) { plasma_node_t *plasma = uniforms_ctxt; @@ -145,12 +205,11 @@ static void plasma_uniforms(void *uniforms_ctxt, void *render_ctxt, unsigned n_u glUniform1f(uniforms[1], play_ticks(play, PLAY_TICKS_TIMER0) * .001f); // FIXME KLUDGE ALERT glUniformMatrix4fv(uniforms[2], 1, GL_FALSE, &model_x->m[0][0]); glUniform1f(uniforms[3], *(plasma->gloom)); - glUniform1i(uniforms[4], *(plasma->maga)); } /* create plasma rendering stage */ -stage_t * plasma_node_new(const stage_conf_t *conf, m4f_t *projection_x, float *gloom, int *maga) +stage_t * plasma_node_new(const stage_conf_t *conf, m4f_t *projection_x, float *gloom, unsigned *maga) { plasma_node_t *ctxt; @@ -170,15 +229,37 @@ stage_t * plasma_node_new(const stage_conf_t *conf, m4f_t *projection_x, float * fatal_if(!ctxt, "unable to allocate plasma_node_t"); ctxt->gloom = gloom; - ctxt->maga = maga; - - return shader_node_new_src(conf, plasma_vs, plasma_fs, projection_x, plasma_uniforms, ctxt, 5, - (const char *[]){ - "alpha", - "time", - "projection_x", - "gloom", - "maga", - } + + return shader_node_new_srcv(conf, 2, + (shader_src_conf_t[]){ + { + .vs_src = plasma_vs, + .fs_src = plasma_fs, + .transform = projection_x, + .uniforms_func = plasma_uniforms, + .uniforms_ctxt = ctxt, + .n_uniforms = 4, + .uniforms = (const char *[]){ + "alpha", + "time", + "projection_x", + "gloom", + }, + }, { + .vs_src = plasma_vs, + .fs_src = plasma_maga_fs, + .transform = projection_x, + .uniforms_func = plasma_uniforms, + .uniforms_ctxt = ctxt, + .n_uniforms = 4, + .uniforms = (const char *[]){ + "alpha", + "time", + "projection_x", + "gloom", + }, + }, + }, + maga ); } diff --git a/src/plasma-node.h b/src/plasma-node.h index 8db8664..6094207 100644 --- a/src/plasma-node.h +++ b/src/plasma-node.h @@ -21,6 +21,6 @@ typedef struct m4f_t m4f_t; typedef struct stage_t stage_t; typedef struct stage_conf_t stage_conf_t; -stage_t * plasma_node_new(const stage_conf_t *conf, m4f_t *projection_x, float *gloom, int *maga); +stage_t * plasma_node_new(const stage_conf_t *conf, m4f_t *projection_x, float *gloom, unsigned *maga); #endif diff --git a/src/shader-node.c b/src/shader-node.c index 5ac8c47..ef49807 100644 --- a/src/shader-node.c +++ b/src/shader-node.c @@ -26,11 +26,16 @@ #include "shader-node.h" #include "v2f.h" + typedef struct shader_node_t { - shader_t *shader; - shader_node_uniforms_func_t *uniforms_func; - void *uniforms_ctxt; - const m4f_t *transform; + unsigned *index_ptr; + unsigned n_shaders; + struct { + shader_t *shader; + shader_node_uniforms_func_t *uniforms_func; + void *uniforms_ctxt; + const m4f_t *transform; + } shaders[]; } shader_node_t; static unsigned vbo, tcbo; @@ -65,14 +70,20 @@ static stage_render_func_ret_t shader_node_render(const stage_t *stage, void *ob shader_node_t *shader_node = object; unsigned n_uniforms; int *uniforms, *attributes; + unsigned idx = 0; assert(stage); assert(shader_node); - shader_use(shader_node->shader, &n_uniforms, &uniforms, NULL, &attributes); + if (shader_node->index_ptr) + idx = *(shader_node->index_ptr); + + assert(idx < shader_node->n_shaders); + + shader_use(shader_node->shaders[idx].shader, &n_uniforms, &uniforms, NULL, &attributes); - if (shader_node->uniforms_func) - shader_node->uniforms_func(shader_node->uniforms_ctxt, render_ctxt, n_uniforms, uniforms, shader_node->transform, alpha); + if (shader_node->shaders[idx].uniforms_func) + shader_node->shaders[idx].uniforms_func(shader_node->shaders[idx].uniforms_ctxt, render_ctxt, n_uniforms, uniforms, shader_node->shaders[idx].transform, alpha); glBindBuffer(GL_ARRAY_BUFFER, vbo); glVertexAttribPointer(attributes[0], 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); @@ -106,7 +117,8 @@ static void shader_node_free(const stage_t *stage, void *object) assert(shader_node); /* XXX FIXME: hmm, maybe the caller should supply a shader_t ** instead */ - (void) shader_free(shader_node->shader); + for (unsigned i = 0; i < shader_node->n_shaders; i++) + (void) shader_free(shader_node->shaders[i].shader); free(shader_node); } @@ -117,14 +129,20 @@ static const stage_ops_t shader_node_ops = { }; -/* return a new shader stage node from an already compiled and linked shader program */ -stage_t * shader_node_new_shader(const stage_conf_t *conf, shader_t *shader, const m4f_t *transform, shader_node_uniforms_func_t *uniforms_func, void *uniforms_ctxt) +/* return a new shader stage node from a vector of already compiled and linked shader programs. + * When n_shader_confs is > 1, index_ptr must point somewhere valid for the lifetime of this node, + * and serves as the index into the vector for selecting which shader_conf to use @ render time. + * When n_shader_confs is 1, index_ptr may be NULL. + */ +stage_t * shader_node_new_shaderv(const stage_conf_t *conf, unsigned n_shader_confs, const shader_conf_t *shader_confs, unsigned *index_ptr) { shader_node_t *shader_node; stage_t *stage; assert(conf); - assert(shader); + assert(shader_confs); + assert(n_shader_confs > 0); + assert(index_ptr || n_shader_confs == 1); if (!vbo) { /* common to all shader nodes */ @@ -138,13 +156,17 @@ stage_t * shader_node_new_shader(const stage_conf_t *conf, shader_t *shader, con glBindBuffer(GL_ARRAY_BUFFER, 0); } - shader_node = calloc(1, sizeof(shader_node_t)); + shader_node = calloc(1, sizeof(shader_node_t) + n_shader_confs * sizeof(shader_node->shaders[0])); fatal_if(!shader_node, "Unable to allocate shader_node"); - shader_node->shader = shader_ref(shader); - shader_node->uniforms_func = uniforms_func; - shader_node->uniforms_ctxt = uniforms_ctxt; - shader_node->transform = transform; + shader_node->index_ptr = index_ptr; + shader_node->n_shaders = n_shader_confs; + for (unsigned i = 0; i < n_shader_confs; i++) { + shader_node->shaders[i].shader = shader_ref(shader_confs[i].shader); + shader_node->shaders[i].uniforms_func = shader_confs[i].uniforms_func; + shader_node->shaders[i].uniforms_ctxt = shader_confs[i].uniforms_ctxt; + shader_node->shaders[i].transform = shader_confs[i].transform; + } stage = stage_new(conf, &shader_node_ops, shader_node); fatal_if(!stage, "Unable to create stage \"%s\"", conf->name); @@ -153,23 +175,49 @@ stage_t * shader_node_new_shader(const stage_conf_t *conf, shader_t *shader, con } -/* return a new shader stage node from source */ -stage_t * shader_node_new_src(const stage_conf_t *conf, const char *vs_src, const char *fs_src, const m4f_t *transform, shader_node_uniforms_func_t *uniforms_func, void *uniforms_ctxt, unsigned n_uniforms, const char **uniforms) +/* return a new shader stage node from an already compiled and linked shader program */ +stage_t * shader_node_new_shader(const stage_conf_t *conf, const shader_conf_t *shader_conf) +{ + return shader_node_new_shaderv(conf, 1, shader_conf, NULL); +} + + +/* return a new shader stage node from source vector, see shader_node_new_shaderv() comment */ +stage_t * shader_node_new_srcv(const stage_conf_t *conf, unsigned n_shader_src_confs, const shader_src_conf_t *shader_src_confs, unsigned *index_ptr) { + shader_conf_t shader_confs[n_shader_src_confs]; stage_t *stage; - shader_t *shader; - assert(vs_src); - assert(fs_src); + assert(n_shader_src_confs > 0); + assert(shader_src_confs); + + for (unsigned i = 0; i < n_shader_src_confs; i++) { + shader_confs[i].shader = shader_pair_new( + shader_src_confs[i].vs_src, + shader_src_confs[i].fs_src, + shader_src_confs[i].n_uniforms, + shader_src_confs[i].uniforms, + 2, + (const char *[]) { + "vertex", + "texcoord", + } + ); + shader_confs[i].transform = shader_src_confs[i].transform; + shader_confs[i].uniforms_func = shader_src_confs[i].uniforms_func; + shader_confs[i].uniforms_ctxt = shader_src_confs[i].uniforms_ctxt; + } - shader = shader_pair_new(vs_src, fs_src, n_uniforms, uniforms, - 2, - (const char *[]) { - "vertex", - "texcoord", - }); - stage = shader_node_new_shader(conf, shader, transform, uniforms_func, uniforms_ctxt); - shader_free(shader); + stage = shader_node_new_shaderv(conf, n_shader_src_confs, shader_confs, index_ptr); + for (unsigned i = 0; i < n_shader_src_confs; i++) + shader_free(shader_confs[i].shader); return stage; } + + +/* return a new shader stage node from source */ +stage_t * shader_node_new_src(const stage_conf_t *conf, const shader_src_conf_t *shader_src_conf) +{ + return shader_node_new_srcv(conf, 1, shader_src_conf, NULL); +} diff --git a/src/shader-node.h b/src/shader-node.h index 34fccc2..7c93c81 100644 --- a/src/shader-node.h +++ b/src/shader-node.h @@ -24,7 +24,26 @@ typedef struct m4f_t m4f_t; typedef void (shader_node_uniforms_func_t)(void *uniforms_ctxt, void *render_ctxt, unsigned n_uniforms, const int *uniforms, const m4f_t *transform, float alpha); -stage_t * shader_node_new_shader(const stage_conf_t *conf, shader_t *shader, const m4f_t *transform, shader_node_uniforms_func_t *uniforms_func, void *uniforms_ctxt); -stage_t * shader_node_new_src(const stage_conf_t *conf, const char *vs_src, const char *fs_src, const m4f_t *transform, shader_node_uniforms_func_t *uniforms_func, void *uniforms_ctxt, unsigned n_uniforms, const char **uniforms); +typedef struct shader_conf_t { + shader_t *shader; + const m4f_t *transform; + shader_node_uniforms_func_t *uniforms_func; + void *uniforms_ctxt; +} shader_conf_t; + +typedef struct shader_src_conf_t { + const char *vs_src, *fs_src; + const m4f_t *transform; + shader_node_uniforms_func_t *uniforms_func; + void *uniforms_ctxt; + unsigned n_uniforms; + const char **uniforms; +} shader_src_conf_t; + +stage_t * shader_node_new_shaderv(const stage_conf_t *conf, unsigned n_shader_confs, const shader_conf_t *shader_confs, unsigned *index_ptr); +stage_t * shader_node_new_shader(const stage_conf_t *conf, const shader_conf_t *shader_conf); + +stage_t * shader_node_new_srcv(const stage_conf_t *conf, unsigned n_shader_src_confs, const shader_src_conf_t *shader_src_conf, unsigned *index_ptr); +stage_t * shader_node_new_src(const stage_conf_t *conf, const shader_src_conf_t *shader_src_conf); #endif |