Fix: OpenGL renders on graphics cards which do not support non-power-of-two
textures were stretched and the wrong size.
This commit is contained in:
@@ -154,7 +154,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender)
|
|||||||
|
|
||||||
if((scene->r.mode & R_OSA) == 0) {
|
if((scene->r.mode & R_OSA) == 0) {
|
||||||
ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat);
|
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 {
|
else {
|
||||||
/* simple accumulation, less hassle then FSAA FBO's */
|
/* 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' */
|
/* first sample buffer, also initializes 'rv3d->persmat' */
|
||||||
ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat);
|
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 */
|
/* skip the first sample */
|
||||||
for(j=1; j < SAMPLES; j++) {
|
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);
|
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);
|
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));
|
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;
|
sizey= (scene->r.size*scene->r.ysch)/100;
|
||||||
|
|
||||||
/* corrects render size with actual size, not every card supports non-power-of-two dimensions */
|
/* 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) {
|
if(!ofs) {
|
||||||
BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL offscreen buffer, %s", err_out);
|
BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL offscreen buffer, %s", err_out);
|
||||||
|
@@ -2379,7 +2379,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in
|
|||||||
glPushAttrib(GL_LIGHTING_BIT);
|
glPushAttrib(GL_LIGHTING_BIT);
|
||||||
|
|
||||||
/* bind */
|
/* bind */
|
||||||
ofs= GPU_offscreen_create(&sizex, &sizey, err_out);
|
ofs= GPU_offscreen_create(sizex, sizey, err_out);
|
||||||
if(ofs == NULL)
|
if(ofs == NULL)
|
||||||
return 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);
|
ibuf= IMB_allocImBuf(sizex, sizey, 32, flag);
|
||||||
|
|
||||||
if(ibuf->rect_float)
|
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)
|
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))
|
//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);
|
// BKE_stamp_buf(scene, NULL, rr->rectf, rr->rectx, rr->recty, 4);
|
||||||
|
@@ -136,7 +136,7 @@ int GPU_texture_opengl_bindcode(GPUTexture *tex);
|
|||||||
GPUFrameBuffer *GPU_framebuffer_create(void);
|
GPUFrameBuffer *GPU_framebuffer_create(void);
|
||||||
int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, char err_out[256]);
|
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_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_texture_unbind(GPUFrameBuffer *fb, GPUTexture *tex);
|
||||||
void GPU_framebuffer_free(GPUFrameBuffer *fb);
|
void GPU_framebuffer_free(GPUFrameBuffer *fb);
|
||||||
|
|
||||||
@@ -146,10 +146,11 @@ void GPU_framebuffer_restore(void);
|
|||||||
- wrapper around framebuffer and texture for simple offscreen drawing
|
- wrapper around framebuffer and texture for simple offscreen drawing
|
||||||
- changes size if graphics card can't support it */
|
- 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_free(GPUOffScreen *ofs);
|
||||||
void GPU_offscreen_bind(GPUOffScreen *ofs);
|
void GPU_offscreen_bind(GPUOffScreen *ofs);
|
||||||
void GPU_offscreen_unbind(GPUOffScreen *ofs);
|
void GPU_offscreen_unbind(GPUOffScreen *ofs);
|
||||||
|
void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels);
|
||||||
|
|
||||||
/* GPU Shader
|
/* GPU Shader
|
||||||
- only for fragment shaders now
|
- only for fragment shaders now
|
||||||
|
@@ -790,7 +790,7 @@ void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex)
|
|||||||
tex->fb = NULL;
|
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 */
|
/* push attributes */
|
||||||
glPushAttrib(GL_ENABLE_BIT);
|
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);
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tex->fb->object);
|
||||||
|
|
||||||
/* push matrices and set default viewport and matrix */
|
/* 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;
|
GG.currentfb = tex->fb->object;
|
||||||
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
@@ -859,13 +859,19 @@ struct GPUOffScreen {
|
|||||||
GPUFrameBuffer *fb;
|
GPUFrameBuffer *fb;
|
||||||
GPUTexture *color;
|
GPUTexture *color;
|
||||||
GPUTexture *depth;
|
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;
|
GPUOffScreen *ofs;
|
||||||
|
|
||||||
ofs= MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen");
|
ofs= MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen");
|
||||||
|
ofs->w= width;
|
||||||
|
ofs->h= height;
|
||||||
|
|
||||||
ofs->fb = GPU_framebuffer_create();
|
ofs->fb = GPU_framebuffer_create();
|
||||||
if(!ofs->fb) {
|
if(!ofs->fb) {
|
||||||
@@ -873,24 +879,18 @@ GPUOffScreen *GPU_offscreen_create(int *width, int *height, char err_out[256])
|
|||||||
return NULL;
|
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) {
|
if(!ofs->depth) {
|
||||||
GPU_offscreen_free(ofs);
|
GPU_offscreen_free(ofs);
|
||||||
return NULL;
|
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)) {
|
if(!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, err_out)) {
|
||||||
GPU_offscreen_free(ofs);
|
GPU_offscreen_free(ofs);
|
||||||
return NULL;
|
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) {
|
if(!ofs->color) {
|
||||||
GPU_offscreen_free(ofs);
|
GPU_offscreen_free(ofs);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -921,7 +921,7 @@ void GPU_offscreen_free(GPUOffScreen *ofs)
|
|||||||
void GPU_offscreen_bind(GPUOffScreen *ofs)
|
void GPU_offscreen_bind(GPUOffScreen *ofs)
|
||||||
{
|
{
|
||||||
glDisable(GL_SCISSOR_TEST);
|
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)
|
void GPU_offscreen_unbind(GPUOffScreen *ofs)
|
||||||
@@ -931,6 +931,11 @@ void GPU_offscreen_unbind(GPUOffScreen *ofs)
|
|||||||
glEnable(GL_SCISSOR_TEST);
|
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 */
|
/* GPUShader */
|
||||||
|
|
||||||
struct GPUShader {
|
struct GPUShader {
|
||||||
|
@@ -1661,7 +1661,8 @@ void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[][4], int *winsize
|
|||||||
|
|
||||||
/* opengl */
|
/* opengl */
|
||||||
glDisable(GL_SCISSOR_TEST);
|
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 */
|
/* set matrices */
|
||||||
copy_m4_m4(viewmat, lamp->viewmat);
|
copy_m4_m4(viewmat, lamp->viewmat);
|
||||||
|
Reference in New Issue
Block a user