rescale the fbo so it’s always rendered pixel perfectly

This commit is contained in:
laochailan 2017-04-19 09:56:18 +02:00
parent 587246e528
commit 8ea9cff499
4 changed files with 30 additions and 17 deletions

View file

@ -10,8 +10,7 @@
static float sanitize_scale(float scale) {
// return ftopow2(clamp(scale, 0.25, 4.0));
scale = max(0.1, scale);
return ((int)(scale*VIEWPORT_W*VIEWPORT_H+0.9999))/(float)VIEWPORT_W/VIEWPORT_H;
return max(0.1, scale);
}
void init_fbo(FBO *fbo, float scale) {
@ -70,15 +69,15 @@ void delete_fbo(FBO *fbo) {
}
void draw_fbo(FBO *fbo) {
float wq = (fbo->scale*VIEWPORT_W)/(float)fbo->nw;
float hq = (fbo->scale*VIEWPORT_H)/(float)fbo->nh;
float wq = floor(fbo->scale*VIEWPORT_W)/(float)fbo->nw;
float hq = floor(fbo->scale*VIEWPORT_H)/(float)fbo->nh;
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glScalef(wq, hq, 1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(VIEWPORT_W/2, VIEWPORT_H/2, 0);
glTranslatef(VIEWPORT_W/2., VIEWPORT_H/2., 0);
glScalef(VIEWPORT_W, VIEWPORT_H, 1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, fbo->tex);

View file

@ -264,9 +264,19 @@ static void postprocess_prepare(FBO *fbo, Shader *s) {
}
void stage_draw_foreground(void) {
int vw, vh;
video_get_viewport_size(&vw,&vh);
// CAUTION: Very intricate pixel perfect scaling that will ruin your day.
float facw = (float)vw/SCREEN_W;
float fach = (float)vh/SCREEN_H;
float scale = resources.fbo.fg[0].scale;
// draw the foreground FBO
glPushMatrix();
glTranslatef(VIEWPORT_X, VIEWPORT_Y, 0);
glScalef(1/facw,1/fach,1);
glTranslatef(floorf(facw*VIEWPORT_X), floorf(fach*VIEWPORT_Y), 0);
glScalef(floorf(scale*VIEWPORT_W)/VIEWPORT_W,floorf(scale*VIEWPORT_H)/VIEWPORT_H,1);
// apply the screenshake effect
if(global.shake_view) {
glTranslatef(global.shake_view*sin(global.frames),global.shake_view*sin(global.frames*1.1+3),0);
@ -279,9 +289,9 @@ void stage_draw_foreground(void) {
global.shake_view = global.shake_view_fade = 0;
}
}
draw_fbo(&resources.fbo.fg[0]);
glPopMatrix();
set_ortho();
}
void stage_draw_scene(StageInfo *stage) {

View file

@ -49,7 +49,7 @@ static int video_compare_modes(const void *a, const void *b) {
return va->width * va->height - vb->width * vb->height;
}
void video_set_viewport(void) {
void video_get_viewport_size(int *width, int *height) {
float w = video.current.width;
float h = video.current.height;
float r = w / h;
@ -59,9 +59,17 @@ void video_set_viewport(void) {
} else if(r < VIDEO_ASPECT_RATIO) {
h = w / VIDEO_ASPECT_RATIO;
}
*width = w;
*height = h;
}
void video_set_viewport(void) {
int w, h;
video_get_viewport_size(&w,&h);
glClear(GL_COLOR_BUFFER_BIT);
glViewport((video.current.width - w) / 2, (video.current.height - h) / 2, (int)w, (int)h);
glViewport((video.current.width - w) / 2, (video.current.height - h) / 2, w, h);
}
void video_update_vsync(void) {
@ -153,14 +161,9 @@ static void video_init_gl(void) {
}
static void video_update_quality(void) {
float q;
float r = (float)video.current.width / video.current.height;
if(r >= VIDEO_ASPECT_RATIO) {
q = (float)video.current.height / SCREEN_H;
} else {
q = (float)video.current.width / SCREEN_W;
}
int vw, vh;
video_get_viewport_size(&vw,&vh);
float q = (float)vh / SCREEN_H;
float fg = q * config_get_float(CONFIG_FG_QUALITY);
float bg = q * config_get_float(CONFIG_BG_QUALITY);

View file

@ -35,6 +35,7 @@ extern Video video;
void video_init(void);
void video_shutdown(void);
void video_setmode(int w, int h, bool fs, bool resizable);
void video_get_viewport_size(int *width, int *height);
void video_set_viewport(void);
bool video_isfullscreen(void);
bool video_isresizable(void);