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
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user