diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 091bc583360..a1cfc6f91a7 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -281,7 +281,7 @@ int ED_view3d_scene_layer_set(int lay, const int *values, int *active); bool ED_view3d_context_activate(struct bContext *C); void ED_view3d_draw_offscreen_init(struct Scene *scene, struct View3D *v3d); void ED_view3d_draw_offscreen(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, - int winx, int winy, float viewmat[4][4], float winmat[4][4], bool do_bgpic); + int winx, int winy, float viewmat[4][4], float winmat[4][4], bool do_bgpic, bool do_sky); struct ImBuf *ED_view3d_draw_offscreen_imbuf(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int sizex, int sizey, unsigned int flag, bool draw_background, int alpha_mode, char err_out[256]); diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index 9d443fab552..ead5a64d4f8 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -135,6 +135,9 @@ static void screen_opengl_render_apply(OGLRender *oglrender) int sizex = oglrender->sizex; int sizey = oglrender->sizey; const short view_context = (v3d != NULL); + bool draw_bgpic = true; + bool draw_sky = (scene->r.alphamode == R_ADDSKY); + unsigned char *rect = NULL; rr = RE_AcquireResultRead(oglrender->re); @@ -167,7 +170,6 @@ static void screen_opengl_render_apply(OGLRender *oglrender) BKE_sequencer_imbuf_from_sequencer_space(scene, linear_ibuf); } - memcpy(rr->rectf, linear_ibuf->rect_float, sizeof(float) * 4 * oglrender->sizex * oglrender->sizey); IMB_freeImBuf(linear_ibuf); @@ -194,23 +196,27 @@ static void screen_opengl_render_apply(OGLRender *oglrender) else perspective_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend); } + rect = MEM_mallocN(sizex * sizey * sizeof(unsigned char) * 4, "offscreen rect"); + if ((scene->r.mode & R_OSA) == 0) { - ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, TRUE); - GPU_offscreen_read_pixels(oglrender->ofs, GL_FLOAT, rr->rectf); + ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, draw_bgpic, draw_sky); + GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect); } else { /* simple accumulation, less hassle then FSAA FBO's */ static float jit_ofs[32][2]; float winmat_jitter[4][4]; - float *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(float) * 4, "accum1"); - float *accum_tmp = MEM_mallocN(sizex * sizey * sizeof(float) * 4, "accum2"); - int j; + int *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(int) * 4, "accum1");; + int i, j; BLI_jitter_init(jit_ofs[0], scene->r.osa); /* first sample buffer, also initializes 'rv3d->persmat' */ - ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, TRUE); - GPU_offscreen_read_pixels(oglrender->ofs, GL_FLOAT, accum_buffer); + ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, draw_bgpic, draw_sky); + GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect); + + for (i = 0; i < sizex * sizey * 4; i++) + accum_buffer[i] = rect[i]; /* skip the first sample */ for (j = 1; j < scene->r.osa; j++) { @@ -219,15 +225,17 @@ static void screen_opengl_render_apply(OGLRender *oglrender) (jit_ofs[j][0] * 2.0f) / sizex, (jit_ofs[j][1] * 2.0f) / sizey); - ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat_jitter, TRUE); - GPU_offscreen_read_pixels(oglrender->ofs, GL_FLOAT, accum_tmp); - add_vn_vn(accum_buffer, accum_tmp, sizex * sizey * sizeof(float)); + ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat_jitter, draw_bgpic, draw_sky); + GPU_offscreen_read_pixels(oglrender->ofs, GL_UNSIGNED_BYTE, rect); + + for (i = 0; i < sizex * sizey * 4; i++) + accum_buffer[i] += rect[i]; } - mul_vn_vn_fl(rr->rectf, accum_buffer, sizex * sizey * sizeof(float), 1.0f / scene->r.osa); + for (i = 0; i < sizex * sizey * 4; i++) + rect[i] = accum_buffer[i] / scene->r.osa; MEM_freeN(accum_buffer); - MEM_freeN(accum_tmp); } GPU_offscreen_unbind(oglrender->ofs); /* unbind */ @@ -236,11 +244,15 @@ static void screen_opengl_render_apply(OGLRender *oglrender) /* shouldnt suddenly give errors mid-render but possible */ char err_out[256] = "unknown"; ImBuf *ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera, oglrender->sizex, oglrender->sizey, - IB_rectfloat, OB_SOLID, FALSE, TRUE, R_ALPHAPREMUL, err_out); + IB_rect, OB_SOLID, FALSE, TRUE, + (draw_sky)? R_ADDSKY: R_ALPHAPREMUL, err_out); camera = scene->camera; if (ibuf_view) { - memcpy(rr->rectf, ibuf_view->rect_float, sizeof(float) * 4 * oglrender->sizex * oglrender->sizey); + /* steal rect reference from ibuf */ + rect = (unsigned char*)ibuf_view->rect; + ibuf_view->mall &= ~IB_rect; + IMB_freeImBuf(ibuf_view); } else { @@ -248,12 +260,6 @@ static void screen_opengl_render_apply(OGLRender *oglrender) } } - if (scene->r.alphamode == R_ADDSKY) { - float sky_color[3]; - ED_view3d_offscreen_sky_color_get(scene, sky_color); - IMB_alpha_under_color_float(rr->rectf, sizex, sizey, sky_color); - } - /* note on color management: * * OpenGL renders into sRGB colors, but render buffers are expected to be @@ -262,21 +268,18 @@ static void screen_opengl_render_apply(OGLRender *oglrender) * correct linear float buffer. */ - if (!oglrender->is_sequencer) { + if (rect) { /* sequencer has got trickier conversion happened above - * also assume opengl's space matches byte buffer color space - */ - if (!glaBufferTransformFromRole_glsl(rr->rectf, oglrender->sizex, oglrender->sizey, COLOR_ROLE_DEFAULT_BYTE)) { - IMB_buffer_float_from_float(rr->rectf, rr->rectf, - 4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, TRUE, - oglrender->sizex, oglrender->sizey, oglrender->sizex, oglrender->sizex); - } + * also assume opengl's space matches byte buffer color space */ + IMB_buffer_float_from_byte(rr->rectf, rect, + IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, TRUE, + oglrender->sizex, oglrender->sizey, oglrender->sizex, oglrender->sizex); } /* rr->rectf is now filled with image data */ if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW)) - BKE_stamp_buf(scene, camera, NULL, rr->rectf, rr->rectx, rr->recty, 4); + BKE_stamp_buf(scene, camera, rect, rr->rectf, rr->rectx, rr->recty, 4); RE_ReleaseResult(oglrender->re); @@ -284,8 +287,15 @@ static void screen_opengl_render_apply(OGLRender *oglrender) ibuf = BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock); if (ibuf) { - image_buffer_rect_update(scene, rr, ibuf, NULL); + /* update display buffer */ + if (ibuf->rect == NULL) + imb_addrectImBuf(ibuf); + IMB_partial_display_buffer_update(ibuf, rr->rectf, rect, rr->rectx, 0, 0, + &scene->view_settings, &scene->display_settings, + 0, 0, rr->rectx, rr->recty, TRUE); + + /* write file for animation */ if (oglrender->write_still) { char name[FILE_MAX]; int ok; @@ -302,6 +312,9 @@ static void screen_opengl_render_apply(OGLRender *oglrender) } BKE_image_release_ibuf(oglrender->ima, ibuf, lock); + + if (rect) + MEM_freeN(rect); } static int screen_opengl_render_init(bContext *C, wmOperator *op) diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 2a6b9cfea9e..0475724e463 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -2463,7 +2463,7 @@ static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d) invert_m4_m4(rv3d.persinv, rv3d.viewinv); /* no need to call ED_view3d_draw_offscreen_init since shadow buffers were already updated */ - ED_view3d_draw_offscreen(scene, v3d, &ar, winsize, winsize, viewmat, winmat, false); + ED_view3d_draw_offscreen(scene, v3d, &ar, winsize, winsize, viewmat, winmat, false, false); GPU_lamp_shadow_buffer_unbind(shadow->lamp); v3d->drawtype = drawtype; @@ -2611,7 +2611,7 @@ void ED_view3d_draw_offscreen_init(Scene *scene, View3D *v3d) * stuff like shadow buffers */ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx, int winy, - float viewmat[4][4], float winmat[4][4], bool do_bgpic) + float viewmat[4][4], float winmat[4][4], bool do_bgpic, bool do_sky) { RegionView3D *rv3d = ar->regiondata; Base *base; @@ -2642,7 +2642,16 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx, * warning! can be slow so only free animated images - campbell */ GPU_free_images_anim(); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + /* clear opengl buffers */ + if (do_sky) { + float sky_color[3]; + + ED_view3d_offscreen_sky_color_get(scene, sky_color); + glClearColor(sky_color[0], sky_color[1], sky_color[2], 1.0f); + } + else { + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + } glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -2753,18 +2762,6 @@ void ED_view3d_offscreen_sky_color_get(Scene *scene, float sky_color[3]) UI_GetThemeColor3fv(TH_BACK, sky_color); } -static void offscreen_imbuf_add_sky(ImBuf *ibuf, Scene *scene) -{ - float sky_color[3]; - - ED_view3d_offscreen_sky_color_get(scene, sky_color); - - if (ibuf->rect_float) - IMB_alpha_under_color_float(ibuf->rect_float, ibuf->x, ibuf->y, sky_color); - else - IMB_alpha_under_color_byte((unsigned char *) ibuf->rect, ibuf->x, ibuf->y, sky_color); -} - /* utility func for ED_view3d_draw_offscreen */ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, int sizex, int sizey, unsigned int flag, bool draw_background, int alpha_mode, char err_out[256]) @@ -2772,6 +2769,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in RegionView3D *rv3d = ar->regiondata; ImBuf *ibuf; GPUOffScreen *ofs; + bool draw_sky = (alpha_mode == R_ADDSKY); /* state changes make normal drawing go weird otherwise */ glPushAttrib(GL_LIGHTING_BIT); @@ -2794,10 +2792,10 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in BKE_camera_params_compute_viewplane(¶ms, sizex, sizey, scene->r.xasp, scene->r.yasp); BKE_camera_params_compute_matrix(¶ms); - ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, params.winmat, draw_background); + ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, params.winmat, draw_background, draw_sky); } else { - ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, NULL, draw_background); + ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, NULL, draw_background, draw_sky); } /* read in pixels & stamp */ @@ -2808,9 +2806,6 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in else if (ibuf->rect) GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, ibuf->rect); - if (alpha_mode == R_ADDSKY) - offscreen_imbuf_add_sky(ibuf, scene); - /* unbind */ GPU_offscreen_unbind(ofs); GPU_offscreen_free(ofs);