From ed77c356fc1c323cef306fef2e7af03fd67a6871 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 28 Oct 2011 16:57:06 +0000 Subject: Fix: OpenGL renders on graphics cards which do not support non-power-of-two textures were stretched and the wrong size. --- source/blender/editors/render/render_opengl.c | 8 +++---- source/blender/editors/space_view3d/view3d_draw.c | 6 ++--- source/blender/gpu/GPU_extensions.h | 5 ++-- source/blender/gpu/intern/gpu_extensions.c | 29 +++++++++++++---------- source/blender/gpu/intern/gpu_material.c | 3 ++- 5 files changed, 29 insertions(+), 22 deletions(-) (limited to 'source') diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index feeb2fefca7..fa764e6eefc 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -154,7 +154,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender) if((scene->r.mode & R_OSA) == 0) { ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat); - glReadPixels(0, 0, sizex, sizey, GL_RGBA, GL_FLOAT, rr->rectf); + GPU_offscreen_read_pixels(oglrender->ofs, GL_FLOAT, rr->rectf); } else { /* simple accumulation, less hassle then FSAA FBO's */ @@ -167,7 +167,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender) /* first sample buffer, also initializes 'rv3d->persmat' */ ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat); - glReadPixels(0, 0, sizex, sizey, GL_RGBA, GL_FLOAT, accum_buffer); + GPU_offscreen_read_pixels(oglrender->ofs, GL_FLOAT, accum_buffer); /* skip the first sample */ for(j=1; j < SAMPLES; j++) { @@ -175,7 +175,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender) window_translate_m4(winmat_jitter, rv3d->persmat, jit_ofs[j][0] / sizex, jit_ofs[j][1] / sizey); ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat_jitter); - glReadPixels(0, 0, sizex, sizey, GL_RGBA, GL_FLOAT, accum_tmp); + GPU_offscreen_read_pixels(oglrender->ofs, GL_FLOAT, accum_tmp); add_vn_vn(accum_buffer, accum_tmp, sizex*sizey*sizeof(float)); } @@ -278,7 +278,7 @@ static int screen_opengl_render_init(bContext *C, wmOperator *op) sizey= (scene->r.size*scene->r.ysch)/100; /* corrects render size with actual size, not every card supports non-power-of-two dimensions */ - ofs= GPU_offscreen_create(&sizex, &sizey, err_out); + ofs= GPU_offscreen_create(sizex, sizey, err_out); if(!ofs) { BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL offscreen buffer, %s", err_out); diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 20b1df6ef2c..32e553262e2 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -2379,7 +2379,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in glPushAttrib(GL_LIGHTING_BIT); /* bind */ - ofs= GPU_offscreen_create(&sizex, &sizey, err_out); + ofs= GPU_offscreen_create(sizex, sizey, err_out); if(ofs == NULL) return NULL; @@ -2403,9 +2403,9 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in ibuf= IMB_allocImBuf(sizex, sizey, 32, flag); if(ibuf->rect_float) - glReadPixels(0, 0, sizex, sizey, GL_RGBA, GL_FLOAT, ibuf->rect_float); + GPU_offscreen_read_pixels(ofs, GL_FLOAT, ibuf->rect_float); else if(ibuf->rect) - glReadPixels(0, 0, sizex, sizey, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); + GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, ibuf->rect); //if((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW)) // BKE_stamp_buf(scene, NULL, rr->rectf, rr->rectx, rr->recty, 4); diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h index 965f317aa50..3fff79390e3 100644 --- a/source/blender/gpu/GPU_extensions.h +++ b/source/blender/gpu/GPU_extensions.h @@ -136,7 +136,7 @@ int GPU_texture_opengl_bindcode(GPUTexture *tex); GPUFrameBuffer *GPU_framebuffer_create(void); int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, char err_out[256]); void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex); -void GPU_framebuffer_texture_bind(GPUFrameBuffer *fb, GPUTexture *tex); +void GPU_framebuffer_texture_bind(GPUFrameBuffer *fb, GPUTexture *tex, int w, int h); void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, GPUTexture *tex); void GPU_framebuffer_free(GPUFrameBuffer *fb); @@ -146,10 +146,11 @@ void GPU_framebuffer_restore(void); - wrapper around framebuffer and texture for simple offscreen drawing - changes size if graphics card can't support it */ -GPUOffScreen *GPU_offscreen_create(int *width, int *height, char err_out[256]); +GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256]); void GPU_offscreen_free(GPUOffScreen *ofs); void GPU_offscreen_bind(GPUOffScreen *ofs); void GPU_offscreen_unbind(GPUOffScreen *ofs); +void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels); /* GPU Shader - only for fragment shaders now diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index 6189062a855..e1a89daf7e2 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -790,7 +790,7 @@ void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex) tex->fb = NULL; } -void GPU_framebuffer_texture_bind(GPUFrameBuffer *UNUSED(fb), GPUTexture *tex) +void GPU_framebuffer_texture_bind(GPUFrameBuffer *UNUSED(fb), GPUTexture *tex, int w, int h) { /* push attributes */ glPushAttrib(GL_ENABLE_BIT); @@ -801,7 +801,7 @@ void GPU_framebuffer_texture_bind(GPUFrameBuffer *UNUSED(fb), GPUTexture *tex) glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tex->fb->object); /* push matrices and set default viewport and matrix */ - glViewport(0, 0, tex->w, tex->h); + glViewport(0, 0, w, h); GG.currentfb = tex->fb->object; glMatrixMode(GL_PROJECTION); @@ -859,13 +859,19 @@ struct GPUOffScreen { GPUFrameBuffer *fb; GPUTexture *color; GPUTexture *depth; + + /* requested width/height, may be smaller than actual texture size due + to missing non-power of two support, so we compensate for that */ + int w, h; }; -GPUOffScreen *GPU_offscreen_create(int *width, int *height, char err_out[256]) +GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256]) { GPUOffScreen *ofs; ofs= MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen"); + ofs->w= width; + ofs->h= height; ofs->fb = GPU_framebuffer_create(); if(!ofs->fb) { @@ -873,24 +879,18 @@ GPUOffScreen *GPU_offscreen_create(int *width, int *height, char err_out[256]) return NULL; } - ofs->depth = GPU_texture_create_depth(*width, *height, err_out); + ofs->depth = GPU_texture_create_depth(width, height, err_out); if(!ofs->depth) { GPU_offscreen_free(ofs); return NULL; } - if(*width!=ofs->depth->w || *height!=ofs->depth->h) { - *width= ofs->depth->w; - *height= ofs->depth->h; - printf("Offscreen size differs from given size!\n"); - } - if(!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, err_out)) { GPU_offscreen_free(ofs); return NULL; } - ofs->color = GPU_texture_create_2D(*width, *height, NULL, err_out); + ofs->color = GPU_texture_create_2D(width, height, NULL, err_out); if(!ofs->color) { GPU_offscreen_free(ofs); return NULL; @@ -921,7 +921,7 @@ void GPU_offscreen_free(GPUOffScreen *ofs) void GPU_offscreen_bind(GPUOffScreen *ofs) { glDisable(GL_SCISSOR_TEST); - GPU_framebuffer_texture_bind(ofs->fb, ofs->color); + GPU_framebuffer_texture_bind(ofs->fb, ofs->color, ofs->w, ofs->h); } void GPU_offscreen_unbind(GPUOffScreen *ofs) @@ -931,6 +931,11 @@ void GPU_offscreen_unbind(GPUOffScreen *ofs) glEnable(GL_SCISSOR_TEST); } +void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels) +{ + glReadPixels(0, 0, ofs->w, ofs->h, GL_RGBA, type, pixels); +} + /* GPUShader */ struct GPUShader { diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index d0f834977c8..26c08f6cae5 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -1661,7 +1661,8 @@ void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[][4], int *winsize /* opengl */ glDisable(GL_SCISSOR_TEST); - GPU_framebuffer_texture_bind(lamp->fb, lamp->tex); + GPU_framebuffer_texture_bind(lamp->fb, lamp->tex, + GPU_texture_opengl_width(lamp->tex), GPU_texture_opengl_height(lamp->tex)); /* set matrices */ copy_m4_m4(viewmat, lamp->viewmat); -- cgit v1.2.3