Changeset View
Changeset View
Standalone View
Standalone View
source/blender/draw/engines/overlay/overlay_image.cc
- This file was moved from source/blender/draw/engines/overlay/overlay_image.c.
| Show All 17 Lines | |||||
| #include "DNA_screen_types.h" | #include "DNA_screen_types.h" | ||||
| #include "DEG_depsgraph_query.h" | #include "DEG_depsgraph_query.h" | ||||
| #include "ED_view3d.h" | #include "ED_view3d.h" | ||||
| #include "IMB_imbuf_types.h" | #include "IMB_imbuf_types.h" | ||||
| #include "overlay_private.h" | #include "overlay_private.hh" | ||||
| void OVERLAY_image_init(OVERLAY_Data *vedata) | void OVERLAY_image_init(OVERLAY_Data *vedata) | ||||
| { | { | ||||
| const DRWContextState *draw_ctx = DRW_context_state_get(); | const DRWContextState *draw_ctx = DRW_context_state_get(); | ||||
| OVERLAY_PrivateData *pd = vedata->stl->pd; | OVERLAY_PrivateData *pd = vedata->stl->pd; | ||||
| DRWView *default_view = (DRWView *)DRW_view_default_get(); | DRWView *default_view = (DRWView *)DRW_view_default_get(); | ||||
| pd->view_reference_images = DRW_view_create_with_zoffset(default_view, draw_ctx->rv3d, -1.0f); | pd->view_reference_images = DRW_view_create_with_zoffset(default_view, draw_ctx->rv3d, -1.0f); | ||||
| ▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | |||||
| static eStereoViews camera_background_images_stereo_eye(const Scene *scene, const View3D *v3d) | static eStereoViews camera_background_images_stereo_eye(const Scene *scene, const View3D *v3d) | ||||
| { | { | ||||
| if ((scene->r.scemode & R_MULTIVIEW) == 0) { | if ((scene->r.scemode & R_MULTIVIEW) == 0) { | ||||
| return STEREO_LEFT_ID; | return STEREO_LEFT_ID; | ||||
| } | } | ||||
| if (v3d->stereo3d_camera != STEREO_3D_ID) { | if (v3d->stereo3d_camera != STEREO_3D_ID) { | ||||
| /* show only left or right camera */ | /* show only left or right camera */ | ||||
| return v3d->stereo3d_camera; | return eStereoViews(v3d->stereo3d_camera); | ||||
| } | } | ||||
| return v3d->multiview_eye; | return eStereoViews(v3d->multiview_eye); | ||||
| } | } | ||||
| static void camera_background_images_stereo_setup(const Scene *scene, | static void camera_background_images_stereo_setup(const Scene *scene, | ||||
| const View3D *v3d, | const View3D *v3d, | ||||
| Image *ima, | Image *ima, | ||||
| ImageUser *iuser) | ImageUser *iuser) | ||||
| { | { | ||||
| if (BKE_image_is_stereo(ima)) { | if (BKE_image_is_stereo(ima)) { | ||||
| Show All 11 Lines | static struct GPUTexture *image_camera_background_texture_get(CameraBGImage *bgpic, | ||||
| OVERLAY_PrivateData *pd, | OVERLAY_PrivateData *pd, | ||||
| float *r_aspect, | float *r_aspect, | ||||
| bool *r_use_alpha_premult, | bool *r_use_alpha_premult, | ||||
| bool *r_use_view_transform) | bool *r_use_view_transform) | ||||
| { | { | ||||
| void *lock; | void *lock; | ||||
| Image *image = bgpic->ima; | Image *image = bgpic->ima; | ||||
| ImageUser *iuser = &bgpic->iuser; | ImageUser *iuser = &bgpic->iuser; | ||||
| MovieClip *clip = NULL; | MovieClip *clip = nullptr; | ||||
| GPUTexture *tex = NULL; | GPUTexture *tex = nullptr; | ||||
| Scene *scene = draw_ctx->scene; | Scene *scene = draw_ctx->scene; | ||||
| float aspect_x, aspect_y; | float aspect_x, aspect_y; | ||||
| int width, height; | int width, height; | ||||
| int ctime = (int)DEG_get_ctime(draw_ctx->depsgraph); | int ctime = (int)DEG_get_ctime(draw_ctx->depsgraph); | ||||
| *r_use_alpha_premult = false; | *r_use_alpha_premult = false; | ||||
| *r_use_view_transform = false; | *r_use_view_transform = false; | ||||
| switch (bgpic->source) { | switch (bgpic->source) { | ||||
| case CAM_BGIMG_SOURCE_IMAGE: | case CAM_BGIMG_SOURCE_IMAGE: { | ||||
| if (image == NULL) { | if (image == nullptr) { | ||||
| return NULL; | return nullptr; | ||||
| } | } | ||||
| *r_use_alpha_premult = (image->alpha_mode == IMA_ALPHA_PREMUL); | *r_use_alpha_premult = (image->alpha_mode == IMA_ALPHA_PREMUL); | ||||
| *r_use_view_transform = (image->flag & IMA_VIEW_AS_RENDER) != 0; | *r_use_view_transform = (image->flag & IMA_VIEW_AS_RENDER) != 0; | ||||
| BKE_image_user_frame_calc(image, iuser, ctime); | BKE_image_user_frame_calc(image, iuser, ctime); | ||||
| if (image->source == IMA_SRC_SEQUENCE && !(iuser->flag & IMA_USER_FRAME_IN_RANGE)) { | if (image->source == IMA_SRC_SEQUENCE && !(iuser->flag & IMA_USER_FRAME_IN_RANGE)) { | ||||
| /* Frame is out of range, don't show. */ | /* Frame is out of range, don't show. */ | ||||
| return NULL; | return nullptr; | ||||
| } | } | ||||
| camera_background_images_stereo_setup(scene, draw_ctx->v3d, image, iuser); | camera_background_images_stereo_setup(scene, draw_ctx->v3d, image, iuser); | ||||
| iuser->scene = draw_ctx->scene; | iuser->scene = draw_ctx->scene; | ||||
| ImBuf *ibuf = BKE_image_acquire_ibuf(image, iuser, &lock); | ImBuf *ibuf = BKE_image_acquire_ibuf(image, iuser, &lock); | ||||
| if (ibuf == NULL) { | if (ibuf == nullptr) { | ||||
| BKE_image_release_ibuf(image, ibuf, lock); | BKE_image_release_ibuf(image, ibuf, lock); | ||||
| iuser->scene = NULL; | iuser->scene = nullptr; | ||||
| return NULL; | return nullptr; | ||||
| } | } | ||||
| width = ibuf->x; | width = ibuf->x; | ||||
| height = ibuf->y; | height = ibuf->y; | ||||
| tex = BKE_image_get_gpu_texture(image, iuser, ibuf); | tex = BKE_image_get_gpu_texture(image, iuser, ibuf); | ||||
| BKE_image_release_ibuf(image, ibuf, lock); | BKE_image_release_ibuf(image, ibuf, lock); | ||||
| iuser->scene = NULL; | iuser->scene = nullptr; | ||||
| if (tex == NULL) { | if (tex == nullptr) { | ||||
| return NULL; | return nullptr; | ||||
| } | } | ||||
| aspect_x = bgpic->ima->aspx; | aspect_x = bgpic->ima->aspx; | ||||
| aspect_y = bgpic->ima->aspy; | aspect_y = bgpic->ima->aspy; | ||||
| break; | break; | ||||
| } | |||||
| case CAM_BGIMG_SOURCE_MOVIE: | case CAM_BGIMG_SOURCE_MOVIE: { | ||||
| if (bgpic->flag & CAM_BGIMG_FLAG_CAMERACLIP) { | if (bgpic->flag & CAM_BGIMG_FLAG_CAMERACLIP) { | ||||
| if (scene->camera) { | if (scene->camera) { | ||||
| clip = BKE_object_movieclip_get(scene, scene->camera, true); | clip = BKE_object_movieclip_get(scene, scene->camera, true); | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| clip = bgpic->clip; | clip = bgpic->clip; | ||||
| } | } | ||||
| if (clip == NULL) { | if (clip == nullptr) { | ||||
| return NULL; | return nullptr; | ||||
| } | } | ||||
| BKE_movieclip_user_set_frame(&bgpic->cuser, ctime); | BKE_movieclip_user_set_frame(&bgpic->cuser, ctime); | ||||
| tex = BKE_movieclip_get_gpu_texture(clip, &bgpic->cuser); | tex = BKE_movieclip_get_gpu_texture(clip, &bgpic->cuser); | ||||
| if (tex == NULL) { | if (tex == nullptr) { | ||||
| return NULL; | return nullptr; | ||||
| } | } | ||||
| aspect_x = clip->aspx; | aspect_x = clip->aspx; | ||||
| aspect_y = clip->aspy; | aspect_y = clip->aspy; | ||||
| *r_use_view_transform = true; | *r_use_view_transform = true; | ||||
| BKE_movieclip_get_size(clip, &bgpic->cuser, &width, &height); | BKE_movieclip_get_size(clip, &bgpic->cuser, &width, &height); | ||||
| /* Save for freeing. */ | /* Save for freeing. */ | ||||
| BLI_addtail(&pd->bg_movie_clips, BLI_genericNodeN(clip)); | BLI_addtail(&pd->bg_movie_clips, BLI_genericNodeN(clip)); | ||||
| break; | break; | ||||
| } | |||||
| default: | default: | ||||
| /* Unsupported type. */ | /* Unsupported type. */ | ||||
| return NULL; | return nullptr; | ||||
| } | } | ||||
| *r_aspect = (width * aspect_x) / (height * aspect_y); | *r_aspect = (width * aspect_x) / (height * aspect_y); | ||||
| return tex; | return tex; | ||||
| } | } | ||||
| static void OVERLAY_image_free_movieclips_textures(OVERLAY_Data *data) | static void OVERLAY_image_free_movieclips_textures(OVERLAY_Data *data) | ||||
| { | { | ||||
| /* Free Movie clip textures after rendering */ | /* Free Movie clip textures after rendering */ | ||||
| LinkData *link; | LinkData *link; | ||||
| while ((link = BLI_pophead(&data->stl->pd->bg_movie_clips))) { | while ((link = static_cast<LinkData *>(BLI_pophead(&data->stl->pd->bg_movie_clips)))) { | ||||
| MovieClip *clip = (MovieClip *)link->data; | MovieClip *clip = (MovieClip *)link->data; | ||||
| BKE_movieclip_free_gputexture(clip); | BKE_movieclip_free_gputexture(clip); | ||||
| MEM_freeN(link); | MEM_freeN(link); | ||||
| } | } | ||||
| } | } | ||||
| static void image_camera_background_matrix_get(const Camera *cam, | static void image_camera_background_matrix_get(const Camera *cam, | ||||
| const CameraBGImage *bgpic, | const CameraBGImage *bgpic, | ||||
| ▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | |||||
| void OVERLAY_image_camera_cache_populate(OVERLAY_Data *vedata, Object *ob) | void OVERLAY_image_camera_cache_populate(OVERLAY_Data *vedata, Object *ob) | ||||
| { | { | ||||
| OVERLAY_PrivateData *pd = vedata->stl->pd; | OVERLAY_PrivateData *pd = vedata->stl->pd; | ||||
| OVERLAY_PassList *psl = vedata->psl; | OVERLAY_PassList *psl = vedata->psl; | ||||
| const DRWContextState *draw_ctx = DRW_context_state_get(); | const DRWContextState *draw_ctx = DRW_context_state_get(); | ||||
| const View3D *v3d = draw_ctx->v3d; | const View3D *v3d = draw_ctx->v3d; | ||||
| const Scene *scene = draw_ctx->scene; | const Scene *scene = draw_ctx->scene; | ||||
| Camera *cam = ob->data; | Camera *cam = static_cast<Camera *>(ob->data); | ||||
| const bool show_frame = BKE_object_empty_image_frame_is_visible_in_view3d(ob, draw_ctx->rv3d); | const bool show_frame = BKE_object_empty_image_frame_is_visible_in_view3d(ob, draw_ctx->rv3d); | ||||
| if (!show_frame || DRW_state_is_select()) { | if (!show_frame || DRW_state_is_select()) { | ||||
| return; | return; | ||||
| } | } | ||||
| const bool stereo_eye = camera_background_images_stereo_eye(scene, v3d) == STEREO_LEFT_ID; | const bool stereo_eye = camera_background_images_stereo_eye(scene, v3d) == STEREO_LEFT_ID; | ||||
| Show All 17 Lines | LISTBASE_FOREACH (CameraBGImage *, bgpic, &cam->bg_images) { | ||||
| if (tex) { | if (tex) { | ||||
| image_camera_background_matrix_get(cam, bgpic, draw_ctx, aspect, mat); | image_camera_background_matrix_get(cam, bgpic, draw_ctx, aspect, mat); | ||||
| const bool is_foreground = (bgpic->flag & CAM_BGIMG_FLAG_FOREGROUND) != 0; | const bool is_foreground = (bgpic->flag & CAM_BGIMG_FLAG_FOREGROUND) != 0; | ||||
| /* Alpha is clamped just below 1.0 to fix background images to interfere with foreground | /* Alpha is clamped just below 1.0 to fix background images to interfere with foreground | ||||
| * images. Without this a background image with 1.0 will be rendered on top of a transparent | * images. Without this a background image with 1.0 will be rendered on top of a transparent | ||||
| * foreground image due to the different blending modes they use. */ | * foreground image due to the different blending modes they use. */ | ||||
| const float color_premult_alpha[4] = {1.0f, 1.0f, 1.0f, MIN2(bgpic->alpha, 0.999999)}; | const float color_premult_alpha[4] = {1.0f, 1.0f, 1.0f, std::min(bgpic->alpha, 0.999999f)}; | ||||
| DRWPass *pass = is_foreground ? (use_view_transform ? psl->image_foreground_scene_ps : | DRWPass *pass = is_foreground ? (use_view_transform ? psl->image_foreground_scene_ps : | ||||
| psl->image_foreground_ps) : | psl->image_foreground_ps) : | ||||
| (use_view_transform ? psl->image_background_scene_ps : | (use_view_transform ? psl->image_background_scene_ps : | ||||
| psl->image_background_ps); | psl->image_background_ps); | ||||
| GPUShader *sh = OVERLAY_shader_image(); | GPUShader *sh = OVERLAY_shader_image(); | ||||
| DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); | DRWShadingGroup *grp = DRW_shgroup_create(sh, pass); | ||||
| DRW_shgroup_uniform_texture(grp, "imgTexture", tex); | DRW_shgroup_uniform_texture(grp, "imgTexture", tex); | ||||
| DRW_shgroup_uniform_bool_copy(grp, "imgPremultiplied", use_alpha_premult); | DRW_shgroup_uniform_bool_copy(grp, "imgPremultiplied", use_alpha_premult); | ||||
| DRW_shgroup_uniform_bool_copy(grp, "imgAlphaBlend", true); | DRW_shgroup_uniform_bool_copy(grp, "imgAlphaBlend", true); | ||||
| DRW_shgroup_uniform_bool_copy(grp, "isCameraBackground", true); | DRW_shgroup_uniform_bool_copy(grp, "isCameraBackground", true); | ||||
| DRW_shgroup_uniform_bool_copy(grp, "depthSet", true); | DRW_shgroup_uniform_bool_copy(grp, "depthSet", true); | ||||
| DRW_shgroup_uniform_vec4_copy(grp, "color", color_premult_alpha); | DRW_shgroup_uniform_vec4_copy(grp, "color", color_premult_alpha); | ||||
| DRW_shgroup_call_obmat(grp, DRW_cache_quad_get(), mat); | DRW_shgroup_call_obmat(grp, DRW_cache_quad_get(), mat); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| void OVERLAY_image_empty_cache_populate(OVERLAY_Data *vedata, Object *ob) | void OVERLAY_image_empty_cache_populate(OVERLAY_Data *vedata, Object *ob) | ||||
| { | { | ||||
| OVERLAY_PassList *psl = vedata->psl; | OVERLAY_PassList *psl = vedata->psl; | ||||
| const DRWContextState *draw_ctx = DRW_context_state_get(); | const DRWContextState *draw_ctx = DRW_context_state_get(); | ||||
| const RegionView3D *rv3d = draw_ctx->rv3d; | const RegionView3D *rv3d = draw_ctx->rv3d; | ||||
| GPUTexture *tex = NULL; | GPUTexture *tex = nullptr; | ||||
| Image *ima = ob->data; | Image *ima = static_cast<Image *>(ob->data); | ||||
| float mat[4][4]; | float mat[4][4]; | ||||
| const bool show_frame = BKE_object_empty_image_frame_is_visible_in_view3d(ob, rv3d); | const bool show_frame = BKE_object_empty_image_frame_is_visible_in_view3d(ob, rv3d); | ||||
| const bool show_image = show_frame && BKE_object_empty_image_data_is_visible_in_view3d(ob, rv3d); | const bool show_image = show_frame && BKE_object_empty_image_data_is_visible_in_view3d(ob, rv3d); | ||||
| const bool use_alpha_blend = (ob->empty_image_flag & OB_EMPTY_IMAGE_USE_ALPHA_BLEND) != 0; | const bool use_alpha_blend = (ob->empty_image_flag & OB_EMPTY_IMAGE_USE_ALPHA_BLEND) != 0; | ||||
| const bool use_alpha_premult = ima && (ima->alpha_mode == IMA_ALPHA_PREMUL); | const bool use_alpha_premult = ima && (ima->alpha_mode == IMA_ALPHA_PREMUL); | ||||
| if (!show_frame) { | if (!show_frame) { | ||||
| return; | return; | ||||
| } | } | ||||
| { | { | ||||
| /* Calling 'BKE_image_get_size' may free the texture. Get the size from 'tex' instead, | /* Calling 'BKE_image_get_size' may free the texture. Get the size from 'tex' instead, | ||||
| * see: T59347 */ | * see: T59347 */ | ||||
| int size[2] = {0}; | int size[2] = {0}; | ||||
| if (ima != NULL) { | if (ima != nullptr) { | ||||
| ImageUser iuser = *ob->iuser; | ImageUser iuser = *ob->iuser; | ||||
| camera_background_images_stereo_setup(draw_ctx->scene, draw_ctx->v3d, ima, &iuser); | camera_background_images_stereo_setup(draw_ctx->scene, draw_ctx->v3d, ima, &iuser); | ||||
| tex = BKE_image_get_gpu_texture(ima, &iuser, NULL); | tex = BKE_image_get_gpu_texture(ima, &iuser, nullptr); | ||||
| if (tex) { | if (tex) { | ||||
| size[0] = GPU_texture_orig_width(tex); | size[0] = GPU_texture_orig_width(tex); | ||||
| size[1] = GPU_texture_orig_height(tex); | size[1] = GPU_texture_orig_height(tex); | ||||
| } | } | ||||
| } | } | ||||
| CLAMP_MIN(size[0], 1); | CLAMP_MIN(size[0], 1); | ||||
| CLAMP_MIN(size[1], 1); | CLAMP_MIN(size[1], 1); | ||||
| float image_aspect[2]; | float image_aspect[2]; | ||||
| overlay_image_calc_aspect(ob->data, size, image_aspect); | overlay_image_calc_aspect(ima, size, image_aspect); | ||||
| copy_m4_m4(mat, ob->obmat); | copy_m4_m4(mat, ob->obmat); | ||||
| mul_v3_fl(mat[0], image_aspect[0] * 0.5f * ob->empty_drawsize); | mul_v3_fl(mat[0], image_aspect[0] * 0.5f * ob->empty_drawsize); | ||||
| mul_v3_fl(mat[1], image_aspect[1] * 0.5f * ob->empty_drawsize); | mul_v3_fl(mat[1], image_aspect[1] * 0.5f * ob->empty_drawsize); | ||||
| madd_v3_v3fl(mat[3], mat[0], ob->ima_ofs[0] * 2.0f + 1.0f); | madd_v3_v3fl(mat[3], mat[0], ob->ima_ofs[0] * 2.0f + 1.0f); | ||||
| madd_v3_v3fl(mat[3], mat[1], ob->ima_ofs[1] * 2.0f + 1.0f); | madd_v3_v3fl(mat[3], mat[1], ob->ima_ofs[1] * 2.0f + 1.0f); | ||||
| } | } | ||||
| /* Use the actual depth if we are doing depth tests to determine the distance to the object */ | /* Use the actual depth if we are doing depth tests to determine the distance to the object */ | ||||
| char depth_mode = DRW_state_is_depth() ? OB_EMPTY_IMAGE_DEPTH_DEFAULT : ob->empty_image_depth; | char depth_mode = DRW_state_is_depth() ? OB_EMPTY_IMAGE_DEPTH_DEFAULT : ob->empty_image_depth; | ||||
| DRWPass *pass = NULL; | DRWPass *pass = nullptr; | ||||
| if ((ob->dtx & OB_DRAW_IN_FRONT) != 0) { | if ((ob->dtx & OB_DRAW_IN_FRONT) != 0) { | ||||
| /* Object In Front overrides image empty depth mode. */ | /* Object In Front overrides image empty depth mode. */ | ||||
| pass = psl->image_empties_front_ps; | pass = psl->image_empties_front_ps; | ||||
| } | } | ||||
| else { | else { | ||||
| switch (depth_mode) { | switch (depth_mode) { | ||||
| case OB_EMPTY_IMAGE_DEPTH_DEFAULT: | case OB_EMPTY_IMAGE_DEPTH_DEFAULT: | ||||
| pass = (use_alpha_blend) ? psl->image_empties_blend_ps : psl->image_empties_ps; | pass = (use_alpha_blend) ? psl->image_empties_blend_ps : psl->image_empties_ps; | ||||
| ▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | void OVERLAY_image_draw(OVERLAY_Data *vedata) | ||||
| OVERLAY_PassList *psl = vedata->psl; | OVERLAY_PassList *psl = vedata->psl; | ||||
| OVERLAY_PrivateData *pd = vedata->stl->pd; | OVERLAY_PrivateData *pd = vedata->stl->pd; | ||||
| DRW_view_set_active(pd->view_reference_images); | DRW_view_set_active(pd->view_reference_images); | ||||
| DRW_draw_pass(psl->image_empties_ps); | DRW_draw_pass(psl->image_empties_ps); | ||||
| DRW_draw_pass(psl->image_empties_blend_ps); | DRW_draw_pass(psl->image_empties_blend_ps); | ||||
| DRW_view_set_active(NULL); | DRW_view_set_active(nullptr); | ||||
| } | } | ||||
| void OVERLAY_image_in_front_draw(OVERLAY_Data *vedata) | void OVERLAY_image_in_front_draw(OVERLAY_Data *vedata) | ||||
| { | { | ||||
| OVERLAY_PassList *psl = vedata->psl; | OVERLAY_PassList *psl = vedata->psl; | ||||
| OVERLAY_PrivateData *pd = vedata->stl->pd; | OVERLAY_PrivateData *pd = vedata->stl->pd; | ||||
| DRW_view_set_active(pd->view_reference_images); | DRW_view_set_active(pd->view_reference_images); | ||||
| DRW_draw_pass(psl->image_empties_front_ps); | DRW_draw_pass(psl->image_empties_front_ps); | ||||
| DRW_draw_pass(psl->image_foreground_ps); | DRW_draw_pass(psl->image_foreground_ps); | ||||
| DRW_view_set_active(NULL); | DRW_view_set_active(nullptr); | ||||
| OVERLAY_image_free_movieclips_textures(vedata); | OVERLAY_image_free_movieclips_textures(vedata); | ||||
| } | } | ||||