added some glitches...

This commit is contained in:
Andrei Alexeyev 2017-10-01 11:58:45 +03:00
parent 9d7bd0f7a1
commit 0343159260
No known key found for this signature in database
GPG key ID: 363707CD4C7FE8A4
10 changed files with 180 additions and 49 deletions

View file

@ -0,0 +1,32 @@
#version 110
void main(void) {
gl_Position = ftransform();
gl_FrontColor = gl_Color;
gl_TexCoord[0] = gl_MultiTexCoord0 * gl_TextureMatrix[0];
}
%% -- FRAG
#version 110
uniform sampler2D tex;
uniform int frames;
uniform float strength;
float f(float x) {
return cos(floor(20.0 * x) - cos((30.0 * x)) * sin(floor(4.0 * x)));
}
void main(void) {
vec2 p = gl_TexCoord[0].xy;
float t = float(frames) / 54.3;
float s = clamp(pow(cos(f(t/3.1 - p.y + 0.15 * f(p.x+t)) + f(t) + (floor(128.0 * sin(p.x * 0.01 + 0.3 * t)) / 128.0) * 53.2), 100.0), 0.0, 1.0);
float g = f(f(p.y + (float(frames) / 33.2)) + floor(float(frames) / 30.2));
p.x -= strength * 0.5 * g * s;
p = clamp(p, 0.0, 1.0);
gl_FragColor = texture2D(tex, p);
}

View file

@ -100,3 +100,9 @@ void draw_fbo_viewport(FBO *fbo) {
set_ortho_ex(VIEWPORT_W,VIEWPORT_H);
draw_fbo(fbo);
}
void swap_fbos(FBO **fbo1, FBO **fbo2) {
FBO *temp = *fbo1;
*fbo1 = *fbo2;
*fbo2 = temp;
}

View file

@ -24,5 +24,4 @@ void reinit_fbo(FBO *fbo, float scale);
void draw_fbo(FBO *fbo);
void draw_fbo_viewport(FBO *fbo);
void delete_fbo(FBO *fbo);
void swap_fbos(FBO **fbo1, FBO **fbo2);

View file

@ -25,14 +25,20 @@ static PostprocessShaderUniformFuncPtr get_uniform_func(PostprocessShaderUniform
return lists[type][size - 1];
}
typedef struct PostprocessLoadData {
PostprocessShader *list;
ResourceFlags resflags;
} PostprocessLoadData;
static void postprocess_load_callback(const char *key, const char *value, void *data) {
PostprocessShader **slist = data;
PostprocessLoadData *ldata = data;
PostprocessShader **slist = &ldata->list;
PostprocessShader *current = *slist;
if(!strcmp(key, "@shader")) {
current = create_element((void**)slist, sizeof(PostprocessShader));
current->uniforms = NULL;
current->shader = get_resource(RES_SHADER, value, RESF_PRELOAD | RESF_PERMANENT)->shader;
current->shader = get_resource(RES_SHADER, value, ldata->resflags)->shader;
log_debug("Shader added: %s (prog: %u)", value, current->shader->prog);
return;
}
@ -111,9 +117,13 @@ static void postprocess_load_callback(const char *key, const char *value, void *
}
}
PostprocessShader* postprocess_load(const char *path) {
PostprocessShader *list = NULL;
parse_keyvalue_file_cb(path, postprocess_load_callback, &list);
PostprocessShader* postprocess_load(const char *path, ResourceFlags flags) {
flags &= ~RESF_OPTIONAL;
PostprocessLoadData *ldata = calloc(1, sizeof(PostprocessLoadData));
ldata->resflags = flags;
parse_keyvalue_file_cb(path, postprocess_load_callback, ldata);
PostprocessShader *list = ldata->list;
free(ldata);
return list;
}
@ -133,30 +143,55 @@ void postprocess_unload(PostprocessShader **list) {
delete_all_elements((void**)list, delete_shader);
}
FBO* postprocess(PostprocessShader *ppshaders, FBO *primfbo, FBO *auxfbo, PostprocessPrepareFuncPtr prepare, PostprocessDrawFuncPtr draw) {
FBO *fbos[] = { primfbo, auxfbo };
void postprocess(PostprocessShader *ppshaders, FBO **primfbo, FBO **auxfbo, PostprocessPrepareFuncPtr prepare, PostprocessDrawFuncPtr draw) {
if(!ppshaders) {
return primfbo;
return;
}
int fbonum = 1;
swap_fbos(primfbo, auxfbo);
for(PostprocessShader *pps = ppshaders; pps; pps = pps->next) {
Shader *s = pps->shader;
glBindFramebuffer(GL_FRAMEBUFFER, fbos[fbonum]->fbo);
glBindFramebuffer(GL_FRAMEBUFFER, (*primfbo)->fbo);
glUseProgram(s->prog);
prepare(fbos[fbonum], s);
if(prepare) {
prepare(*primfbo, s);
}
for(PostprocessShaderUniform *u = pps->uniforms; u; u = u->next) {
u->func(u->loc, u->amount, u->values.v);
}
fbonum = !fbonum;
draw(fbos[fbonum]);
swap_fbos(primfbo, auxfbo);
draw(*primfbo);
glUseProgram(0);
}
fbonum = !fbonum;
return fbos[fbonum];
swap_fbos(primfbo, auxfbo);
}
/*
* Glue for resources api
*/
char* postprocess_path(const char *name) {
return strjoin(SHA_PATH_PREFIX, name, ".pp", NULL);
}
bool check_postprocess_path(const char *path) {
return strendswith(path, SHA_EXTENSION);
}
void* load_postprocess_begin(const char *path, unsigned int flags) {
return (void*)true;
}
void* load_postprocess_end(void *opaque, const char *path, unsigned int flags) {
return postprocess_load(path, flags);
}
void unload_postprocess(void *vlist) {
postprocess_unload((PostprocessShader**)&vlist);
}

View file

@ -52,8 +52,18 @@ struct PostprocessShaderUniform {
typedef void (*PostprocessDrawFuncPtr)(FBO*);
typedef void (*PostprocessPrepareFuncPtr)(FBO*, Shader*);
PostprocessShader* postprocess_load(const char *path);
char* postprocess_path(const char *path);
PostprocessShader* postprocess_load(const char *path, unsigned int flags);
void postprocess_unload(PostprocessShader **list);
FBO* postprocess(PostprocessShader *ppshaders, FBO *fbo1, FBO *fbo2, PostprocessPrepareFuncPtr prepare, PostprocessDrawFuncPtr draw);
void postprocess(PostprocessShader *ppshaders, FBO **primfbo, FBO **auxfbo, PostprocessPrepareFuncPtr prepare, PostprocessDrawFuncPtr draw);
/*
* Glue for resources api
*/
char* postprocess_path(const char *name);
bool check_postprocess_path(const char *path);
void* load_postprocess_begin(const char *path, unsigned int flags);
void* load_postprocess_end(void *opaque, const char *path, unsigned int flags);
void unload_postprocess(void*);

View file

@ -22,6 +22,7 @@ static const char *resource_type_names[] = {
"bgm",
"shader",
"model",
"postprocessing pipeline",
};
static inline ResourceHandler* get_handler(ResourceType type) {
@ -351,6 +352,10 @@ void init_resources(void) {
RES_BGM, BGM_PATH_PREFIX, load_music_begin, load_music_end, unload_music, NULL, music_path, check_music_path, HT_DYNAMIC_SIZE
);
register_handler(
RES_POSTPROCESS, SHA_PATH_PREFIX, load_postprocess_begin, load_postprocess_end, unload_postprocess, NULL, postprocess_path, check_postprocess_path, HT_DYNAMIC_SIZE
);
main_thread_id = SDL_ThreadID();
if(!getenvint("TAISEI_NOASYNC", 0)) {
@ -395,7 +400,7 @@ void load_resources(void) {
}
menu_preload();
resources.stage_postprocess = postprocess_load(SHA_PATH_PREFIX "postprocess.conf");
resources.stage_postprocess = postprocess_load(SHA_PATH_PREFIX "postprocess.conf", RESF_PERMANENT | RESF_PRELOAD);
}
void free_resources(bool all) {

View file

@ -27,6 +27,7 @@ typedef enum ResourceType {
RES_BGM,
RES_SHADER,
RES_MODEL,
RES_POSTPROCESS,
RES_NUMTYPES,
} ResourceType;
@ -90,6 +91,7 @@ typedef struct Resource {
Music *music;
Shader *shader;
Model *model;
PostprocessShader *postprocess;
};
} Resource;

View file

@ -77,6 +77,7 @@ struct StageProcs {
StageProc draw;
StageProc event;
ShaderRule *shader_rules;
ShaderRule *postprocess_rules;
StageProcs *spellpractice_procs;
};

View file

@ -11,14 +11,18 @@
#include "stagetext.h"
#include "video.h"
static int apply_shaderrules(ShaderRule *shaderrules, int fbonum) {
for(ShaderRule *rule = shaderrules; *rule; ++rule) {
glBindFramebuffer(GL_FRAMEBUFFER, resources.fbo.bg[!fbonum].fbo);
(*rule)(resources.fbo.bg + fbonum);
fbonum = !fbonum;
static void apply_shader_rules(ShaderRule *shaderrules, FBO **fbo0, FBO **fbo1) {
if(!shaderrules) {
return;
}
return fbonum;
for(ShaderRule *rule = shaderrules; *rule; ++rule) {
glBindFramebuffer(GL_FRAMEBUFFER, (*fbo1)->fbo);
(*rule)(*fbo0);
swap_fbos(fbo0, fbo1);
}
return;
}
static void draw_wall_of_text(float f, const char *txt) {
@ -89,29 +93,29 @@ static void draw_spellbg(int t) {
glPopMatrix();
}
static int apply_bg_shaders(ShaderRule *shaderrules, int fbonum) {
static void apply_bg_shaders(ShaderRule *shaderrules, FBO **fbo0, FBO **fbo1) {
Boss *b = global.boss;
if(b && b->current && b->current->draw_rule) {
int t = global.frames - b->current->starttime;
int o = fbonum;
FBO *fbo0_orig = *fbo0;
if(t < 4*ATTACK_START_DELAY || b->current->endtime) {
fbonum = apply_shaderrules(shaderrules, fbonum);
apply_shader_rules(shaderrules, fbo0, fbo1);
}
if(fbonum == o) {
glBindFramebuffer(GL_FRAMEBUFFER, resources.fbo.bg[!fbonum].fbo);
draw_fbo_viewport(resources.fbo.bg + fbonum);
fbonum = !fbonum;
if(*fbo0 == fbo0_orig) {
glBindFramebuffer(GL_FRAMEBUFFER, (*fbo1)->fbo);
draw_fbo_viewport(*fbo0);
swap_fbos(fbo0, fbo1);
}
glBindFramebuffer(GL_FRAMEBUFFER, resources.fbo.bg[!fbonum].fbo);
glBindFramebuffer(GL_FRAMEBUFFER, (*fbo1)->fbo);
draw_spellbg(t);
complex pos = b->pos;
float ratio = (float)VIEWPORT_H/VIEWPORT_W;
glBindFramebuffer(GL_FRAMEBUFFER, resources.fbo.bg[fbonum].fbo);
glBindFramebuffer(GL_FRAMEBUFFER, (*fbo0)->fbo);
if(t<4*ATTACK_START_DELAY) {
Shader *shader = get_shader("spellcard_intro");
glUseProgram(shader->prog);
@ -148,13 +152,12 @@ static int apply_bg_shaders(ShaderRule *shaderrules, int fbonum) {
glUseProgram(0);
}
draw_fbo_viewport(&resources.fbo.bg[!fbonum]);
draw_fbo_viewport(*fbo1);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glUseProgram(0);
} else
fbonum = apply_shaderrules(shaderrules, fbonum);
return fbonum;
} else {
apply_shader_rules(shaderrules, fbo0, fbo1);
}
}
static void apply_zoom_shader(void) {
@ -208,8 +211,11 @@ static FBO* stage_render_bg(StageInfo *stage) {
stage->procs->draw();
glPopMatrix();
int num = apply_bg_shaders(stage->procs->shader_rules, 0);
return &resources.fbo.bg[num];
FBO *fbo0 = resources.fbo.bg;
FBO *fbo1 = resources.fbo.bg + 1;
apply_bg_shaders(stage->procs->shader_rules, &fbo0, &fbo1);
return fbo0;
}
static void stage_draw_objects(void) {
@ -348,19 +354,25 @@ void stage_draw_scene(StageInfo *stage) {
set_ortho_ex(VIEWPORT_W,VIEWPORT_H);
stage_draw_objects();
// apply custom postprocessing shaders
FBO *ppfbo = postprocess(
// apply postprocessing shaders
FBO *fbo0 = resources.fbo.fg, *fbo1 = resources.fbo.fg+1;
// stage postprocessing
apply_shader_rules(global.stage->procs->postprocess_rules, &fbo0, &fbo1);
// custom postprocessing
postprocess(
resources.stage_postprocess,
resources.fbo.fg,
resources.fbo.fg+1,
&fbo0,
&fbo1,
postprocess_prepare,
draw_fbo_viewport
);
// update the primary foreground FBO if needed
if(ppfbo != resources.fbo.fg) {
if(fbo0 != resources.fbo.fg) {
glBindFramebuffer(GL_FRAMEBUFFER, resources.fbo.fg[0].fbo);
draw_fbo_viewport(ppfbo);
draw_fbo_viewport(fbo0);
}
// switch to main framebuffer

View file

@ -122,6 +122,31 @@ void stage3_fog(FBO *fbo) {
glUseProgram(0);
}
void stage3_glitch(FBO *fbo) {
Shader *shader = get_shader("glitch");
glColor4f(1,1,1,1);
float strength;
if(global.boss && global.boss->current && global.boss->current->type == AT_Spellcard && !strcmp(global.boss->name, "Scuttle")) {
strength = 0.05 * pow(max(0, (global.frames - global.boss->current->starttime) / (double)global.boss->current->timeout), 2.0);
log_debug("%f", strength);
} else {
strength = 0.0;
}
if(strength > 0) {
glUseProgram(shader->prog);
glUniform1f(uniloc(shader, "strength"), strength);
glUniform1i(uniloc(shader, "frames"), global.frames + tsrand() % 30);
} else {
glUseProgram(0);
}
draw_fbo_viewport(fbo);
glUseProgram(0);
}
void stage3_start(void) {
init_stage3d(&bgcontext);
@ -151,6 +176,7 @@ void stage3_preload(void) {
preload_resources(RES_SHADER, RESF_DEFAULT,
"tunnel",
"zbuf_fog",
"glitch",
NULL);
preload_resources(RES_ANIM, RESF_DEFAULT,
"scuttle",
@ -321,6 +347,7 @@ void stage3_spellpractice_events(void) {
}
ShaderRule stage3_shaders[] = { stage3_fog, stage3_tunnel, NULL };
ShaderRule stage3_postprocess[] = { stage3_glitch, NULL };
StageProcs stage3_procs = {
.begin = stage3_start,
@ -329,6 +356,7 @@ StageProcs stage3_procs = {
.draw = stage3_draw,
.event = stage3_events,
.shader_rules = stage3_shaders,
.postprocess_rules = stage3_postprocess,
.spellpractice_procs = &stage3_spell_procs,
};
@ -339,4 +367,5 @@ StageProcs stage3_spell_procs = {
.draw = stage3_draw,
.event = stage3_spellpractice_events,
.shader_rules = stage3_shaders,
.postprocess_rules = stage3_postprocess,
};