diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2013-01-05 19:33:18 +0400 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2013-01-05 19:33:18 +0400 |
commit | fa0805e287e762df3638df1982297c794c4cf4b7 (patch) | |
tree | 1b2a7d612bde64569aad2afd72410a43a8147f27 | |
parent | e8b415bdb4ba282e3574cad1463bf2512fe5eb8f (diff) |
Changes for opengl render to reflect new alpha premul pipeline
without hurting quick texture painting
- ED_view3d_draw_offscreen will now output buffer with
transparent alpha, if sky needed it should be alpha-undered
later.
- ED_view3d_draw_offscreen_imbuf now accepts alpha mode as an
argument which could be either R_ADDSKY or R_PREMULALPHA
- OpenGL render and sequencer's opengl preview will now reflect
scene's Alpha Mode
- Quick Edit will use OpenGL with transparent alpha mode
-rw-r--r-- | source/blender/blenkernel/intern/sequencer.c | 2 | ||||
-rw-r--r-- | source/blender/editors/include/ED_view3d.h | 8 | ||||
-rw-r--r-- | source/blender/editors/render/render_opengl.c | 18 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/paint_image.c | 2 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_draw.c | 77 | ||||
-rw-r--r-- | source/blender/imbuf/IMB_imbuf.h | 3 | ||||
-rw-r--r-- | source/blender/imbuf/intern/imageprocess.c | 50 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_files.c | 4 |
8 files changed, 109 insertions, 55 deletions
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 8d010de408a..2c1fd092fbb 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -2391,7 +2391,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float BKE_scene_update_for_newframe(context.bmain, scene, scene->lay); ibuf = sequencer_view3d_cb(scene, camera, context.rectx, context.recty, IB_rect, context.scene->r.seq_prev_type, context.scene->r.seq_flag & R_SEQ_SOLID_TEX, - TRUE, FALSE, err_out); + TRUE, scene->r.alphamode, err_out); if (ibuf == NULL) { fprintf(stderr, "seq_render_scene_strip failed to get opengl buffer: %s\n", err_out); } diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 3d13938c204..ac2c47216a6 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -270,13 +270,13 @@ int ED_view3d_scene_layer_set(int lay, const int *values, int *active); int 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], int do_bgpic, int colormanage_background); + int winx, int winy, float viewmat[4][4], float winmat[4][4], int do_bgpic); struct ImBuf *ED_view3d_draw_offscreen_imbuf(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int sizex, int sizey, unsigned int flag, - int draw_background, int colormanage_background, char err_out[256]); + int draw_background, int alpha_mode, char err_out[256]); struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(struct Scene *scene, struct Object *camera, int width, int height, unsigned int flag, int drawtype, - int use_solid_tex, int draw_background, int colormanage_background, char err_out[256]); - + int use_solid_tex, int draw_background, int alpha_mode, char err_out[256]); +void ED_view3d_offscreen_sky_color_get(struct Scene *scene, float sky_color[3]); struct Base *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]); void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar, short do_clip); diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index cbc076b3342..7ba6a92e4be 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -43,6 +43,7 @@ #include "DNA_scene_types.h" #include "DNA_object_types.h" +#include "DNA_world_types.h" #include "BKE_context.h" #include "BKE_global.h" @@ -192,7 +193,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, TRUE, FALSE); + ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, TRUE); GPU_offscreen_read_pixels(oglrender->ofs, GL_FLOAT, rr->rectf); } else { @@ -206,7 +207,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender) 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, FALSE); + ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat, TRUE); GPU_offscreen_read_pixels(oglrender->ofs, GL_FLOAT, accum_buffer); /* skip the first sample */ @@ -216,7 +217,7 @@ 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, FALSE); + 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)); } @@ -232,7 +233,8 @@ static void screen_opengl_render_apply(OGLRender *oglrender) else { /* 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, FALSE, err_out); + 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); camera = scene->camera; if (ibuf_view) { @@ -243,7 +245,13 @@ static void screen_opengl_render_apply(OGLRender *oglrender) fprintf(stderr, "%s: failed to get buffer, %s\n", __func__, err_out); } } - + + 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 diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index fa8252c824d..d0f8e36e17d 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -6038,7 +6038,7 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op) if (w > maxsize) w = maxsize; if (h > maxsize) h = maxsize; - ibuf = ED_view3d_draw_offscreen_imbuf(CTX_data_scene(C), CTX_wm_view3d(C), CTX_wm_region(C), w, h, IB_rect, FALSE, FALSE, err_out); + ibuf = ED_view3d_draw_offscreen_imbuf(CTX_data_scene(C), CTX_wm_view3d(C), CTX_wm_region(C), w, h, IB_rect, FALSE, R_ALPHAPREMUL, err_out); if (!ibuf) { /* Mostly happens when OpenGL offscreen buffer was failed to create, */ /* but could be other reasons. Should be handled in the future. nazgul */ diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 4ccf26e12b1..76f62db3c5b 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -2393,7 +2393,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, FALSE); + ED_view3d_draw_offscreen(scene, v3d, &ar, winsize, winsize, viewmat, winmat, FALSE); GPU_lamp_shadow_buffer_unbind(shadow->lamp); v3d->drawtype = drawtype; @@ -2540,13 +2540,11 @@ void ED_view3d_draw_offscreen_init(Scene *scene, View3D *v3d) /* ED_view3d_draw_offscreen_init should be called before this to initialize * 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], - int do_bgpic, int colormanage_background) +void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx, int winy, + float viewmat[4][4], float winmat[4][4], int do_bgpic) { RegionView3D *rv3d = ar->regiondata; Base *base; - float backcol[3]; int bwinx, bwiny; rcti brect; @@ -2574,34 +2572,7 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, * warning! can be slow so only free animated images - campbell */ GPU_free_images_anim(); - /* set background color, fallback on the view background color - * (if active clip is set but frame is failed to load fallback to horizon color as background) */ - if (scene->world) { - /* NOTE: currently OpenGL is supposed to always work in sRGB space and do not - * apply any tonemaps since it's really tricky to support for all features (GLSL, textures, etc) - * but due to compatibility issues background is being affected display transform, so we can - * emulate behavior of disabled color management - * but this function is also used for sequencer's scene strips which shouldn't be affected by - * tonemaps now and should be purely sRGB, that's why we've got this colormanage_background - * we can drop this flag in cost of some compatibility loss -- background wouldn't be - * color managed in 3d viewport - * same goes to opengl rendering, where color profile should be applied as very final step - */ - - if (colormanage_background) { - IMB_colormanagement_pixel_to_display_space_v3(backcol, &scene->world->horr, &scene->view_settings, - &scene->display_settings); - } - else { - linearrgb_to_srgb_v3_v3(backcol, &scene->world->horr); - } - - glClearColor(backcol[0], backcol[1], backcol[2], 0.0f); - } - else { - UI_ThemeClearColor(TH_BACK); - } - + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -2703,10 +2674,30 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, G.f &= ~G_RENDER_OGL; } +/* get a color used for offscreen sky, returns color in sRGB space */ +void ED_view3d_offscreen_sky_color_get(Scene *scene, float sky_color[3]) +{ + if (scene->world) + linearrgb_to_srgb_v3_v3(sky_color, &scene->world->horr); + else + 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, int draw_background, - int colormanage_background, char err_out[256]) +ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, int sizex, int sizey, unsigned int flag, + int draw_background, int alpha_mode, char err_out[256]) { RegionView3D *rv3d = ar->regiondata; ImBuf *ibuf; @@ -2733,10 +2724,10 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, 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, colormanage_background); + ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, params.winmat, draw_background); } else { - ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, NULL, draw_background, colormanage_background); + ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, NULL, draw_background); } /* read in pixels & stamp */ @@ -2747,6 +2738,9 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, 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); @@ -2760,9 +2754,8 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, } /* creates own 3d views, used by the sequencer */ -ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int width, int height, - unsigned int flag, int drawtype, int use_solid_tex, int draw_background, - int colormanage_background, char err_out[256]) +ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int width, int height, unsigned int flag, int drawtype, + int use_solid_tex, int draw_background, int alpha_mode, char err_out[256]) { View3D v3d = {NULL}; ARegion ar = {NULL}; @@ -2805,7 +2798,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int w invert_m4_m4(rv3d.persinv, rv3d.viewinv); return ED_view3d_draw_offscreen_imbuf(scene, &v3d, &ar, width, height, flag, - draw_background, colormanage_background, err_out); + draw_background, alpha_mode, err_out); // seq_view3d_cb(scene, cfra, render_size, seqrectx, seqrecty); } diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 850060ef4d5..8d60227377b 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -416,6 +416,9 @@ void nearest_interpolation_color(struct ImBuf *in, unsigned char col[4], float c void bilinear_interpolation_color(struct ImBuf *in, unsigned char col[4], float col_float[4], float u, float v); void bilinear_interpolation_color_wrap(struct ImBuf *in, unsigned char col[4], float col_float[4], float u, float v); +void IMB_alpha_under_color_float(float *rect_float, int x, int y, float backcol[3]); +void IMB_alpha_under_color_byte(unsigned char *rect, int x, int y, float backcol[3]); + /** * * \attention defined in readimage.c diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c index 1eac6236829..59282c9d207 100644 --- a/source/blender/imbuf/intern/imageprocess.c +++ b/source/blender/imbuf/intern/imageprocess.c @@ -327,3 +327,53 @@ void IMB_processor_apply_threaded(int buffer_lines, int handle_size, void *init_ MEM_freeN(handles); } + +/* Alpha-under */ + +void IMB_alpha_under_color_float(float *rect_float, int x, int y, float backcol[3]) +{ + int a = x * y; + float *fp = rect_float; + + while (a--) { + if (fp[3] == 0.0f) { + copy_v3_v3(fp, backcol); + } + else { + float mul = 1.0f - fp[3]; + + fp[0] += mul * backcol[0]; + fp[1] += mul * backcol[1]; + fp[2] += mul * backcol[2]; + } + + fp[3] = 1.0f; + + fp += 4; + } +} + +void IMB_alpha_under_color_byte(unsigned char *rect, int x, int y, float backcol[3]) +{ + int a = x * y; + unsigned char *cp = rect; + + while (a--) { + if (cp[3] == 0) { + cp[0] = backcol[0] * 255; + cp[1] = backcol[1] * 255; + cp[2] = backcol[2] * 255; + } + else { + int mul = 255 - cp[3]; + + cp[0] += mul * backcol[0] / 255; + cp[1] += mul * backcol[1] / 255; + cp[2] += mul * backcol[2] / 255; + } + + cp[3] = 255; + + cp += 4; + } +} diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index f31aff3d3f8..a9b3e4272ce 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -733,11 +733,11 @@ static ImBuf *blend_file_thumb(Scene *scene, bScreen *screen, int **thumb_pt) if (scene->camera) { ibuf = ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera, BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2, - IB_rect, OB_SOLID, FALSE, FALSE, FALSE, err_out); + IB_rect, OB_SOLID, FALSE, FALSE, R_ADDSKY, err_out); } else { ibuf = ED_view3d_draw_offscreen_imbuf(scene, v3d, ar, BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2, - IB_rect, FALSE, FALSE, err_out); + IB_rect, FALSE, R_ADDSKY, err_out); } if (ibuf) { |