Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drawing to FBO - sprite inverted up and down issue

Well, usage of FBO is wide and it helps make complex effects much easier. I set FBO and draw to it, then render FBO textured quad, without any problem, even test simple screen processing color shader. But everything I render to FBO became upside down for some reason. If I render to stock screen FBO everything is normal, and I don't even perform any rotations to sprite.

FBO creation

typedef struct tex
{
 dim2i size; // int width, int height
 GLuint id;
} tex;

typedef struct fbo
{
 GLuint frame_buffer;
 tex buffer_tex;
}fbo;

void set_fbo(fbo* res, int width, int height)
{
 GLint tex_size;
 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &tex_size);
 GLint render_buffer_size;
 glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &render_buffer_size);
 LOGI("Max render buffer size: %d, max texture size: %d", render_buffer_size, tex_size);    //max render buffer size: 3838, max texture size: 2048
 glGenFramebuffers(1, &res->frame_buffer);
 GLuint depth_buffer;
 glGenRenderbuffers(1, &depth_buffer);
 glGenTextures(1, &res->buffer_tex.id);
 res->buffer_tex.size.w = width;
 res->buffer_tex.size.h = height;
 glBindTexture(GL_TEXTURE_2D, res->buffer_tex.id);
 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, res->buffer_tex.size.w, res->buffer_tex.size.h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer);
 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, res->buffer_tex.size.w, res->buffer_tex.size.h);
 glBindFramebuffer(GL_FRAMEBUFFER, res->frame_buffer);
 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, res->buffer_tex.id, 0);
 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth_buffer);
 if(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
    LOGE("BUFFER OK");
 else
    LOGE("BUFFER NOT OK");
//BUFFER OK 
 glBindFramebuffer(GL_FRAMEBUFFER, 0);
 glBindTexture(GL_TEXTURE_2D, 0);
}

FBO usage

static fbo FBO;
static decor DECOR; //shield quad
static decor SCREEN_DECOR;// FBO textured quad

void on_surface_changed(int width, int height)
{
 set_fbo(&FBO, width, height);
 ...
}

void on_draw()
{
 glBindFramebuffer(GL_FRAMEBUFFER, FBO.frame_buffer);
 set_render_color(YELLOW); //glClearColor(...)
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 draw_decor(&DECOR, get_shader(SPRITE_SIMPLE_SHADER), *get_proj(ORTHO_PROJ));
 glBindFramebuffer(GL_FRAMEBUFFER, 0);
 set_render_color(BLACK);
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 draw_decor(&SCREEN_DECOR, get_shader(SPRITE_SIMPLE_SHADER), *get_proj(ORTHO_PROJ));
}

Result: with FBOResult with grayscale shader: with grayscale shader

Render without FBO:

void on_draw_simple()
{
 set_render_color(YELLOW); //glClearColor(...)
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 draw_decor(&DECOR, get_shader(SPRITE_SIMPLE_SHADER), *get_proj(ORTHO_PROJ));
}

without FBO

like image 304
Aristarhys Avatar asked Sep 30 '12 07:09

Aristarhys


1 Answers

Aggregated from the comments:

This happens because OpenGL has the origin in the lower left corner, unlike most windowing systems in use, where the origin is in the upper left corner.

Simply make sure that the texture coordinates goes from 0,1 in upper left to 1,0 in lower right to draw the FBO correctly, or draw the quad with the texture flipped vertically.

like image 81
perh Avatar answered Oct 21 '22 19:10

perh