added some glitches...
This commit is contained in:
parent
9d7bd0f7a1
commit
0343159260
10 changed files with 180 additions and 49 deletions
32
resources/shader/glitch.sha
Normal file
32
resources/shader/glitch.sha
Normal 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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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*);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -77,6 +77,7 @@ struct StageProcs {
|
|||
StageProc draw;
|
||||
StageProc event;
|
||||
ShaderRule *shader_rules;
|
||||
ShaderRule *postprocess_rules;
|
||||
StageProcs *spellpractice_procs;
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue