more efficient FBO handling
This commit is contained in:
parent
a5ebcd692c
commit
f8cf13bdf3
9 changed files with 107 additions and 91 deletions
42
src/fbo.c
42
src/fbo.c
|
@ -12,7 +12,7 @@
|
|||
#include "global.h"
|
||||
#include "util.h"
|
||||
|
||||
void init_fbo(FBO *fbo, float scale, int type) {
|
||||
static void init_fbo(FBO *fbo, float scale, int type) {
|
||||
glGenTextures(1, &fbo->tex);
|
||||
glBindTexture(GL_TEXTURE_2D, fbo->tex);
|
||||
|
||||
|
@ -45,10 +45,17 @@ void init_fbo(FBO *fbo, float scale, int type) {
|
|||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,fbo->depth, 0);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void reinit_fbo(FBO *fbo, float scale, int type) {
|
||||
static void delete_fbo(FBO *fbo) {
|
||||
glDeleteFramebuffers(1, &fbo->fbo);
|
||||
glDeleteTextures(1, &fbo->depth);
|
||||
glDeleteTextures(1, &fbo->tex);
|
||||
}
|
||||
|
||||
static void reinit_fbo(FBO *fbo, float scale, int type) {
|
||||
if(!fbo->scale) {
|
||||
// fbo was never initialized
|
||||
init_fbo(fbo, scale, type);
|
||||
|
@ -61,10 +68,27 @@ void reinit_fbo(FBO *fbo, float scale, int type) {
|
|||
}
|
||||
}
|
||||
|
||||
void delete_fbo(FBO *fbo) {
|
||||
glDeleteFramebuffers(1, &fbo->fbo);
|
||||
glDeleteTextures(1, &fbo->depth);
|
||||
glDeleteTextures(1, &fbo->tex);
|
||||
static void swap_fbos(FBO **fbo1, FBO **fbo2) {
|
||||
FBO *temp = *fbo1;
|
||||
*fbo1 = *fbo2;
|
||||
*fbo2 = temp;
|
||||
}
|
||||
|
||||
void init_fbo_pair(FBOPair *pair, float scale, int type) {
|
||||
pair->front = pair->_fbopair_private.array + FBO_FRONT;
|
||||
pair->back = pair->_fbopair_private.array + FBO_BACK;
|
||||
|
||||
reinit_fbo(pair->front, scale, type);
|
||||
reinit_fbo(pair->back, scale, type);
|
||||
}
|
||||
|
||||
void delete_fbo_pair(FBOPair *pair) {
|
||||
delete_fbo(pair->front);
|
||||
delete_fbo(pair->back);
|
||||
}
|
||||
|
||||
void swap_fbo_pair(FBOPair *pair) {
|
||||
swap_fbos(&pair->front, &pair->back);
|
||||
}
|
||||
|
||||
void draw_fbo(FBO *fbo) {
|
||||
|
@ -96,9 +120,3 @@ 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;
|
||||
}
|
||||
|
|
30
src/fbo.h
30
src/fbo.h
|
@ -11,7 +11,7 @@
|
|||
|
||||
#include "taiseigl.h"
|
||||
|
||||
typedef struct {
|
||||
typedef struct FBO {
|
||||
GLuint fbo;
|
||||
GLuint tex;
|
||||
GLuint depth;
|
||||
|
@ -20,9 +20,29 @@ typedef struct {
|
|||
float scale;
|
||||
} FBO;
|
||||
|
||||
void init_fbo(FBO *fbo, float scale, int type);
|
||||
void reinit_fbo(FBO *fbo, float scale, int type);
|
||||
#define FBO_FRONT 0
|
||||
#define FBO_BACK 1
|
||||
|
||||
typedef struct FBOPair {
|
||||
/*
|
||||
* Rule of thumb:
|
||||
* 1. Bind back buffer;
|
||||
* 2. Draw front buffer;
|
||||
* 3. Call swap_fbo_pair;
|
||||
* 4. Rinse, repeat.
|
||||
*/
|
||||
|
||||
FBO *front;
|
||||
FBO *back;
|
||||
|
||||
struct {
|
||||
FBO array[2];
|
||||
} _fbopair_private;
|
||||
} FBOPair;
|
||||
|
||||
void init_fbo_pair(FBOPair *pair, float scale, int type);
|
||||
void delete_fbo_pair(FBOPair *pair);
|
||||
void swap_fbo_pair(FBOPair *pair);
|
||||
|
||||
void draw_fbo(FBO *fbo);
|
||||
void draw_fbo_viewport(FBO *fbo);
|
||||
void delete_fbo(FBO *fbo);
|
||||
void swap_fbos(FBO **fbo1, FBO **fbo2);
|
||||
|
|
|
@ -247,7 +247,7 @@ static void marisa_laser_renderer_visual(Enemy *renderer, int t, bool render) {
|
|||
glUniform1f(u_clr_phase, -1.5 * t/M_PI);
|
||||
glUniform1f(u_clr_freq, 10.0);
|
||||
glBlendFunc(GL_SRC_COLOR, GL_ONE);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, resources.fbo.rgba[0].fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, resources.fbo_pairs.rgba.front->fbo);
|
||||
glClearColor(0, 0, 0, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glClearColor(0, 0, 0, 1);
|
||||
|
@ -261,10 +261,10 @@ static void marisa_laser_renderer_visual(Enemy *renderer, int t, bool render) {
|
|||
}
|
||||
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, resources.fbo.fg[0].fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, resources.fbo_pairs.fg.back->fbo);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glUseProgram(0);
|
||||
draw_fbo_viewport(&resources.fbo.rgba[0]);
|
||||
draw_fbo_viewport(resources.fbo_pairs.rgba.front);
|
||||
glUseProgram(shader->prog);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
|
||||
|
|
|
@ -149,33 +149,30 @@ void postprocess_unload(PostprocessShader **list) {
|
|||
list_foreach(list, delete_shader, NULL);
|
||||
}
|
||||
|
||||
void postprocess(PostprocessShader *ppshaders, FBO **primfbo, FBO **auxfbo, PostprocessPrepareFuncPtr prepare, PostprocessDrawFuncPtr draw) {
|
||||
void postprocess(PostprocessShader *ppshaders, FBOPair *fbos, PostprocessPrepareFuncPtr prepare, PostprocessDrawFuncPtr draw) {
|
||||
if(!ppshaders) {
|
||||
return;
|
||||
}
|
||||
|
||||
swap_fbos(primfbo, auxfbo);
|
||||
|
||||
for(PostprocessShader *pps = ppshaders; pps; pps = pps->next) {
|
||||
Shader *s = pps->shader;
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, (*primfbo)->fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbos->back->fbo);
|
||||
glUseProgram(s->prog);
|
||||
|
||||
if(prepare) {
|
||||
prepare(*primfbo, s);
|
||||
prepare(fbos->back, s);
|
||||
}
|
||||
|
||||
for(PostprocessShaderUniform *u = pps->uniforms; u; u = u->next) {
|
||||
u->func(u->loc, u->amount, u->values.v);
|
||||
}
|
||||
|
||||
swap_fbos(primfbo, auxfbo);
|
||||
draw(*primfbo);
|
||||
glUseProgram(0);
|
||||
draw(fbos->front);
|
||||
swap_fbo_pair(fbos);
|
||||
}
|
||||
|
||||
swap_fbos(primfbo, auxfbo);
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -58,7 +58,7 @@ char* postprocess_path(const char *path);
|
|||
|
||||
PostprocessShader* postprocess_load(const char *path, unsigned int flags);
|
||||
void postprocess_unload(PostprocessShader **list);
|
||||
void postprocess(PostprocessShader *ppshaders, FBO **primfbo, FBO **auxfbo, PostprocessPrepareFuncPtr prepare, PostprocessDrawFuncPtr draw);
|
||||
void postprocess(PostprocessShader *ppshaders, FBOPair *fbos, PostprocessPrepareFuncPtr prepare, PostprocessDrawFuncPtr draw);
|
||||
|
||||
/*
|
||||
* Glue for resources api
|
||||
|
|
|
@ -477,12 +477,9 @@ void free_resources(bool all) {
|
|||
|
||||
delete_vbo(&_vbo);
|
||||
postprocess_unload(&resources.stage_postprocess);
|
||||
delete_fbo(&resources.fbo.bg[0]);
|
||||
delete_fbo(&resources.fbo.bg[1]);
|
||||
delete_fbo(&resources.fbo.fg[0]);
|
||||
delete_fbo(&resources.fbo.fg[1]);
|
||||
delete_fbo(&resources.fbo.rgba[0]);
|
||||
delete_fbo(&resources.fbo.rgba[1]);
|
||||
delete_fbo_pair(&resources.fbo_pairs.bg);
|
||||
delete_fbo_pair(&resources.fbo_pairs.fg);
|
||||
delete_fbo_pair(&resources.fbo_pairs.rgba);
|
||||
|
||||
if(!getenvint("TAISEI_NOASYNC", 0)) {
|
||||
events_unregister_handler(resource_asyncload_handler);
|
||||
|
|
|
@ -102,10 +102,10 @@ typedef struct Resources {
|
|||
PostprocessShader *stage_postprocess;
|
||||
|
||||
struct {
|
||||
FBO bg[2];
|
||||
FBO fg[2];
|
||||
FBO rgba[2]; // XXX: do we actually need 2 RGBA FBOs?
|
||||
} fbo;
|
||||
FBOPair bg;
|
||||
FBOPair fg;
|
||||
FBOPair rgba;
|
||||
} fbo_pairs;
|
||||
} Resources;
|
||||
|
||||
extern Resources resources;
|
||||
|
|
|
@ -75,15 +75,15 @@ void stage_draw_preload(void) {
|
|||
}
|
||||
}
|
||||
|
||||
static void apply_shader_rules(ShaderRule *shaderrules, FBO **fbo0, FBO **fbo1) {
|
||||
static void apply_shader_rules(ShaderRule *shaderrules, FBOPair *fbos) {
|
||||
if(!shaderrules) {
|
||||
return;
|
||||
}
|
||||
|
||||
for(ShaderRule *rule = shaderrules; *rule; ++rule) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, (*fbo1)->fbo);
|
||||
(*rule)(*fbo0);
|
||||
swap_fbos(fbo0, fbo1);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbos->back->fbo);
|
||||
(*rule)(fbos->front);
|
||||
swap_fbo_pair(fbos);
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -155,29 +155,24 @@ static void draw_spellbg(int t) {
|
|||
glPopMatrix();
|
||||
}
|
||||
|
||||
static void apply_bg_shaders(ShaderRule *shaderrules, FBO **fbo0, FBO **fbo1) {
|
||||
static void apply_bg_shaders(ShaderRule *shaderrules, FBOPair *fbos) {
|
||||
Boss *b = global.boss;
|
||||
if(b && b->current && b->current->draw_rule) {
|
||||
int t = global.frames - b->current->starttime;
|
||||
|
||||
FBO *fbo0_orig = *fbo0;
|
||||
if(t < 4*ATTACK_START_DELAY || b->current->endtime) {
|
||||
apply_shader_rules(shaderrules, fbo0, fbo1);
|
||||
apply_shader_rules(shaderrules, fbos);
|
||||
}
|
||||
|
||||
if(*fbo0 == fbo0_orig) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, (*fbo1)->fbo);
|
||||
draw_fbo_viewport(*fbo0);
|
||||
swap_fbos(fbo0, fbo1);
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, (*fbo1)->fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbos->back->fbo);
|
||||
draw_fbo_viewport(fbos->front);
|
||||
draw_spellbg(t);
|
||||
swap_fbo_pair(fbos);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbos->back->fbo);
|
||||
|
||||
complex pos = b->pos;
|
||||
float ratio = (float)VIEWPORT_H/VIEWPORT_W;
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, (*fbo0)->fbo);
|
||||
if(t<ATTACK_START_DELAY) {
|
||||
Shader *shader = get_shader("spellcard_intro");
|
||||
glUseProgram(shader->prog);
|
||||
|
@ -213,11 +208,12 @@ static void apply_bg_shaders(ShaderRule *shaderrules, FBO **fbo0, FBO **fbo1) {
|
|||
glUseProgram(0);
|
||||
}
|
||||
|
||||
draw_fbo_viewport(*fbo1);
|
||||
draw_fbo_viewport(fbos->front);
|
||||
swap_fbo_pair(fbos);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glUseProgram(0);
|
||||
} else {
|
||||
apply_shader_rules(shaderrules, fbo0, fbo1);
|
||||
apply_shader_rules(shaderrules, fbos);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -260,9 +256,9 @@ static void apply_zoom_shader(void) {
|
|||
}
|
||||
}
|
||||
|
||||
static FBO* stage_render_bg(StageInfo *stage) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, resources.fbo.bg[0].fbo);
|
||||
float scale = resources.fbo.bg[0].scale;
|
||||
static void stage_render_bg(StageInfo *stage) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, resources.fbo_pairs.bg.back->fbo);
|
||||
float scale = resources.fbo_pairs.bg.back->scale;
|
||||
glViewport(0, 0, scale*VIEWPORT_W, scale*VIEWPORT_H);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
|
@ -272,11 +268,9 @@ static FBO* stage_render_bg(StageInfo *stage) {
|
|||
stage->procs->draw();
|
||||
glPopMatrix();
|
||||
|
||||
FBO *fbo0 = resources.fbo.bg;
|
||||
FBO *fbo1 = resources.fbo.bg + 1;
|
||||
|
||||
apply_bg_shaders(stage->procs->shader_rules, &fbo0, &fbo1);
|
||||
return fbo0;
|
||||
swap_fbo_pair(&resources.fbo_pairs.bg);
|
||||
apply_bg_shaders(stage->procs->shader_rules, &resources.fbo_pairs.bg);
|
||||
return;
|
||||
}
|
||||
|
||||
static void stage_draw_objects(void) {
|
||||
|
@ -335,7 +329,7 @@ void stage_draw_foreground(void) {
|
|||
global.shake_view = global.shake_view_fade = 0;
|
||||
}
|
||||
}
|
||||
draw_fbo(&resources.fbo.fg[0]);
|
||||
draw_fbo(resources.fbo_pairs.fg.front);
|
||||
glPopMatrix();
|
||||
set_ortho();
|
||||
}
|
||||
|
@ -348,16 +342,15 @@ void stage_draw_scene(StageInfo *stage) {
|
|||
#endif
|
||||
|
||||
bool draw_bg = !config_get_int(CONFIG_NO_STAGEBG) && !key_nobg;
|
||||
FBO *fbg = NULL;
|
||||
|
||||
if(draw_bg) {
|
||||
// render the 3D background
|
||||
fbg = stage_render_bg(stage);
|
||||
stage_render_bg(stage);
|
||||
}
|
||||
|
||||
// switch to foreground FBO
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, resources.fbo.fg[0].fbo);
|
||||
float scale = resources.fbo.fg[0].scale;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, resources.fbo_pairs.fg.back->fbo);
|
||||
float scale = resources.fbo_pairs.fg.back->scale;
|
||||
glViewport(0, 0, scale*VIEWPORT_W, scale*VIEWPORT_H);
|
||||
set_ortho_ex(VIEWPORT_W,VIEWPORT_H);
|
||||
|
||||
|
@ -368,7 +361,7 @@ void stage_draw_scene(StageInfo *stage) {
|
|||
}
|
||||
|
||||
// draw the 3D background
|
||||
draw_fbo(fbg);
|
||||
draw_fbo(resources.fbo_pairs.bg.front);
|
||||
|
||||
// disable boss background distortion
|
||||
glUseProgram(0);
|
||||
|
@ -382,35 +375,29 @@ void stage_draw_scene(StageInfo *stage) {
|
|||
}
|
||||
|
||||
// draw the 2D objects
|
||||
set_ortho_ex(VIEWPORT_W,VIEWPORT_H);
|
||||
set_ortho_ex(VIEWPORT_W, VIEWPORT_H);
|
||||
stage_draw_objects();
|
||||
|
||||
// apply postprocessing shaders
|
||||
FBO *fbo0 = resources.fbo.fg, *fbo1 = resources.fbo.fg+1;
|
||||
// everything drawn, now apply postprocessing
|
||||
swap_fbo_pair(&resources.fbo_pairs.fg);
|
||||
|
||||
// stage postprocessing
|
||||
apply_shader_rules(global.stage->procs->postprocess_rules, &fbo0, &fbo1);
|
||||
apply_shader_rules(global.stage->procs->postprocess_rules, &resources.fbo_pairs.fg);
|
||||
|
||||
// bomb effects shader if present and player bombing
|
||||
if(global.frames - global.plr.recovery < 0 && global.plr.mode->procs.bomb_shader) {
|
||||
ShaderRule rules[] = {global.plr.mode->procs.bomb_shader,0};
|
||||
apply_shader_rules(rules,&fbo0,&fbo1);
|
||||
apply_shader_rules(rules, &resources.fbo_pairs.fg);
|
||||
}
|
||||
|
||||
// custom postprocessing
|
||||
postprocess(
|
||||
resources.stage_postprocess,
|
||||
&fbo0,
|
||||
&fbo1,
|
||||
&resources.fbo_pairs.fg,
|
||||
postprocess_prepare,
|
||||
draw_fbo_viewport
|
||||
);
|
||||
|
||||
// update the primary foreground FBO if needed
|
||||
if(fbo0 != resources.fbo.fg) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, resources.fbo.fg[0].fbo);
|
||||
draw_fbo_viewport(fbo0);
|
||||
}
|
||||
|
||||
// switch to main framebuffer
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
video_set_viewport();
|
||||
|
|
11
src/video.c
11
src/video.c
|
@ -176,12 +176,9 @@ static void video_update_quality(void) {
|
|||
|
||||
log_debug("q:%f, fg:%f, bg:%f, text:%f", q, fg, bg, text);
|
||||
|
||||
reinit_fbo(&resources.fbo.bg[0], bg, GL_RGB);
|
||||
reinit_fbo(&resources.fbo.bg[1], bg, GL_RGB);
|
||||
reinit_fbo(&resources.fbo.fg[0], fg, GL_RGB);
|
||||
reinit_fbo(&resources.fbo.fg[1], fg, GL_RGB);
|
||||
reinit_fbo(&resources.fbo.rgba[0], fg, GL_RGBA);
|
||||
reinit_fbo(&resources.fbo.rgba[1], fg, GL_RGBA);
|
||||
init_fbo_pair(&resources.fbo_pairs.bg, bg, GL_RGB);
|
||||
init_fbo_pair(&resources.fbo_pairs.fg, fg, GL_RGB);
|
||||
init_fbo_pair(&resources.fbo_pairs.rgba, fg, GL_RGBA);
|
||||
|
||||
reload_fonts(text);
|
||||
|
||||
|
@ -546,7 +543,7 @@ void video_init(void) {
|
|||
bool fullscreen_available = false;
|
||||
|
||||
memset(&video, 0, sizeof(video));
|
||||
memset(&resources.fbo, 0, sizeof(resources.fbo));
|
||||
memset(&resources.fbo_pairs, 0, sizeof(resources.fbo_pairs));
|
||||
|
||||
video_init_sdl();
|
||||
log_info("Using driver '%s'", SDL_GetCurrentVideoDriver());
|
||||
|
|
Loading…
Reference in a new issue