Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/intern/movieclip.c13
-rw-r--r--source/blender/blenloader/intern/readfile.c1
-rw-r--r--source/blender/draw/CMakeLists.txt3
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.c39
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl25
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl25
-rw-r--r--source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl25
-rw-r--r--source/blender/draw/intern/draw_manager.c21
-rw-r--r--source/blender/draw/modes/object_mode.c330
-rw-r--r--source/blender/draw/modes/paint_texture_mode.c5
-rw-r--r--source/blender/draw/modes/shaders/common_colormanagement_lib.glsl30
-rw-r--r--source/blender/draw/modes/shaders/object_camera_image_frag.glsl23
-rw-r--r--source/blender/draw/modes/shaders/object_camera_image_vert.glsl18
-rw-r--r--source/blender/draw/modes/shaders/object_empty_image_frag.glsl25
-rw-r--r--source/blender/draw/modes/shaders/paint_texture_frag.glsl25
-rw-r--r--source/blender/editors/space_view3d/view3d_draw_legacy.c335
-rw-r--r--source/blender/gpu/GPU_texture.h8
-rw-r--r--source/blender/gpu/intern/gpu_draw.c82
-rw-r--r--source/blender/makesdna/DNA_movieclip_types.h13
-rw-r--r--source/blender/makesrna/intern/rna_camera.c2
20 files changed, 546 insertions, 502 deletions
diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c
index c377223d14b..6bc83f8dd09 100644
--- a/source/blender/blenkernel/intern/movieclip.c
+++ b/source/blender/blenkernel/intern/movieclip.c
@@ -67,6 +67,8 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
+#include "GPU_texture.h"
+
#ifdef WITH_OPENEXR
# include "intern/openexr/openexr_multi.h"
#endif
@@ -1353,6 +1355,17 @@ static void free_buffers(MovieClip *clip)
IMB_free_anim(clip->anim);
clip->anim = NULL;
}
+
+ MovieClip_RuntimeGPUTexture *tex;
+ for (tex = clip->runtime.gputextures.first; tex; tex = tex->next) {
+ for (int i = 0; i < TEXTARGET_COUNT; i++) {
+ if (tex->gputexture[i] != NULL) {
+ GPU_texture_free(tex->gputexture[i]);
+ tex->gputexture[i] = NULL;
+ }
+ }
+ }
+ BLI_freelistN(&clip->runtime.gputextures);
}
void BKE_movieclip_clear_cache(MovieClip *clip)
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 541ebe8f01d..393f8f87a90 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -2038,6 +2038,7 @@ void blo_end_movieclip_pointer_map(FileData *fd, Main *oldmain)
for (; clip; clip = clip->id.next) {
clip->cache = newmclipadr(fd, clip->cache);
clip->tracking.camera.intrinsics = newmclipadr(fd, clip->tracking.camera.intrinsics);
+ BLI_freelistN(&clip->runtime.gputextures);
}
for (; sce; sce = sce->id.next) {
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 5a8a4d46ac9..8631a9f556b 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -249,6 +249,7 @@ data_to_c_simple(engines/workbench/shaders/workbench_volume_vert.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_volume_frag.glsl SRC)
data_to_c_simple(engines/workbench/shaders/workbench_world_light_lib.glsl SRC)
+data_to_c_simple(modes/shaders/common_colormanagement_lib.glsl SRC)
data_to_c_simple(modes/shaders/common_globals_lib.glsl SRC)
data_to_c_simple(modes/shaders/common_hair_lib.glsl SRC)
data_to_c_simple(modes/shaders/common_hair_refine_vert.glsl SRC)
@@ -295,6 +296,8 @@ data_to_c_simple(modes/shaders/overlay_face_orientation_vert.glsl SRC)
data_to_c_simple(modes/shaders/overlay_face_wireframe_vert.glsl SRC)
data_to_c_simple(modes/shaders/overlay_face_wireframe_geom.glsl SRC)
data_to_c_simple(modes/shaders/overlay_face_wireframe_frag.glsl SRC)
+data_to_c_simple(modes/shaders/object_camera_image_frag.glsl SRC)
+data_to_c_simple(modes/shaders/object_camera_image_vert.glsl SRC)
data_to_c_simple(modes/shaders/object_empty_axes_vert.glsl SRC)
data_to_c_simple(modes/shaders/object_empty_image_frag.glsl SRC)
data_to_c_simple(modes/shaders/object_empty_image_vert.glsl SRC)
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index 6d1227bb0a8..ae3bf8cead6 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -61,6 +61,7 @@ extern char datatoc_gpencil_edit_point_geom_glsl[];
extern char datatoc_gpencil_edit_point_frag_glsl[];
extern char datatoc_gpencil_blend_frag_glsl[];
+extern char datatoc_common_colormanagement_lib_glsl[];
extern char datatoc_common_view_lib_glsl[];
/* *********** STATIC *********** */
@@ -169,29 +170,37 @@ static void GPENCIL_create_shaders(void)
{
/* normal fill shader */
if (!e_data.gpencil_fill_sh) {
- e_data.gpencil_fill_sh = DRW_shader_create_with_lib(datatoc_gpencil_fill_vert_glsl,
- NULL,
- datatoc_gpencil_fill_frag_glsl,
- datatoc_common_view_lib_glsl,
- NULL);
+ e_data.gpencil_fill_sh = GPU_shader_create_from_arrays({
+ .vert =
+ (const char *[]){datatoc_common_view_lib_glsl, datatoc_gpencil_fill_vert_glsl, NULL},
+ .frag = (const char *[]){datatoc_common_colormanagement_lib_glsl,
+ datatoc_gpencil_fill_frag_glsl,
+ NULL},
+ });
}
/* normal stroke shader using geometry to display lines (line mode) */
if (!e_data.gpencil_stroke_sh) {
- e_data.gpencil_stroke_sh = DRW_shader_create_with_lib(datatoc_gpencil_stroke_vert_glsl,
- datatoc_gpencil_stroke_geom_glsl,
- datatoc_gpencil_stroke_frag_glsl,
- datatoc_common_view_lib_glsl,
- NULL);
+ e_data.gpencil_stroke_sh = GPU_shader_create_from_arrays({
+ .vert =
+ (const char *[]){datatoc_common_view_lib_glsl, datatoc_gpencil_stroke_vert_glsl, NULL},
+ .geom = (const char *[]){datatoc_gpencil_stroke_geom_glsl, NULL},
+ .frag = (const char *[]){datatoc_common_colormanagement_lib_glsl,
+ datatoc_gpencil_stroke_frag_glsl,
+ NULL},
+ });
}
/* dot/rectangle mode for normal strokes using geometry */
if (!e_data.gpencil_point_sh) {
- e_data.gpencil_point_sh = DRW_shader_create_with_lib(datatoc_gpencil_point_vert_glsl,
- datatoc_gpencil_point_geom_glsl,
- datatoc_gpencil_point_frag_glsl,
- datatoc_common_view_lib_glsl,
- NULL);
+ e_data.gpencil_point_sh = GPU_shader_create_from_arrays({
+ .vert =
+ (const char *[]){datatoc_common_view_lib_glsl, datatoc_gpencil_point_vert_glsl, NULL},
+ .geom = (const char *[]){datatoc_gpencil_point_geom_glsl, NULL},
+ .frag = (const char *[]){datatoc_common_colormanagement_lib_glsl,
+ datatoc_gpencil_point_frag_glsl,
+ NULL},
+ });
}
/* used for edit points or strokes with one point only */
if (!e_data.gpencil_edit_point_sh) {
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl
index 1fdfd05332e..87bf116ff89 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_fill_frag.glsl
@@ -90,31 +90,6 @@ void set_color(in vec4 color,
ocolor.a *= layer_opacity;
}
-float linearrgb_to_srgb(float c)
-{
- if (c < 0.0031308) {
- return (c < 0.0) ? 0.0 : c * 12.92;
- }
- else {
- return 1.055 * pow(c, 1.0 / 2.4) - 0.055;
- }
-}
-
-vec4 texture_read_as_srgb(sampler2D tex, bool premultiplied, vec2 co)
-{
- /* By convention image textures return scene linear colors, but
- * grease pencil still works in srgb. */
- vec4 color = texture(tex, co);
- /* Unpremultiply if stored multiplied, since straight alpha is expected by shaders. */
- if (premultiplied && !(color.a == 0.0 || color.a == 1.0)) {
- color.rgb = color.rgb / color.a;
- }
- color.r = linearrgb_to_srgb(color.r);
- color.g = linearrgb_to_srgb(color.g);
- color.b = linearrgb_to_srgb(color.b);
- return color;
-}
-
void main()
{
vec2 t_center = vec2(0.5, 0.5);
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl
index 7fed42aca0d..34777018a73 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_point_frag.glsl
@@ -48,31 +48,6 @@ vec2 check_box_point(vec2 pt, vec2 radius)
return rtn;
}
-float linearrgb_to_srgb(float c)
-{
- if (c < 0.0031308) {
- return (c < 0.0) ? 0.0 : c * 12.92;
- }
- else {
- return 1.055 * pow(c, 1.0 / 2.4) - 0.055;
- }
-}
-
-vec4 texture_read_as_srgb(sampler2D tex, bool premultiplied, vec2 co)
-{
- /* By convention image textures return scene linear colors, but
- * grease pencil still works in srgb. */
- vec4 color = texture(tex, co);
- /* Unpremultiply if stored multiplied, since straight alpha is expected by shaders. */
- if (premultiplied && !(color.a == 0.0 || color.a == 1.0)) {
- color.rgb = color.rgb / color.a;
- }
- color.r = linearrgb_to_srgb(color.r);
- color.g = linearrgb_to_srgb(color.g);
- color.b = linearrgb_to_srgb(color.b);
- return color;
-}
-
void main()
{
vec2 centered = mTexCoord - vec2(0.5);
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl
index bc703d2a078..73baacb35d4 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_stroke_frag.glsl
@@ -28,31 +28,6 @@ out vec4 fragColor;
bool no_texture = (shading_type[0] == OB_SOLID) && (shading_type[1] != V3D_SHADING_TEXTURE_COLOR);
-float linearrgb_to_srgb(float c)
-{
- if (c < 0.0031308) {
- return (c < 0.0) ? 0.0 : c * 12.92;
- }
- else {
- return 1.055 * pow(c, 1.0 / 2.4) - 0.055;
- }
-}
-
-vec4 texture_read_as_srgb(sampler2D tex, bool premultiplied, vec2 co)
-{
- /* By convention image textures return scene linear colors, but
- * grease pencil still works in srgb. */
- vec4 color = texture(tex, co);
- /* Unpremultiply if stored multiplied, since straight alpha is expected by shaders. */
- if (premultiplied && !(color.a == 0.0 || color.a == 1.0)) {
- color.rgb = color.rgb / color.a;
- }
- color.r = linearrgb_to_srgb(color.r);
- color.g = linearrgb_to_srgb(color.g);
- color.b = linearrgb_to_srgb(color.b);
- return color;
-}
-
void main()
{
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 87366289bf7..7606fa914d1 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -1558,7 +1558,6 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
RegionView3D *rv3d = ar->regiondata;
const bool do_annotations = (((v3d->flag2 & V3D_SHOW_ANNOTATION) != 0) &&
((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0));
- const bool do_camera_frame = !DST.options.is_image_render;
DST.draw_ctx.evil_C = evil_C;
DST.viewport = viewport;
@@ -1650,24 +1649,8 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
drw_engines_draw_background();
- /* WIP, single image drawn over the camera view (replace) */
- bool do_bg_image = false;
- if (rv3d->persp == RV3D_CAMOB) {
- Object *cam_ob = v3d->camera;
- if (cam_ob && cam_ob->type == OB_CAMERA) {
- Camera *cam = cam_ob->data;
- if (!BLI_listbase_is_empty(&cam->bg_images)) {
- do_bg_image = true;
- }
- }
- }
-
GPU_framebuffer_bind(DST.default_framebuffer);
- if (do_bg_image) {
- ED_view3d_draw_bgpic_test(scene, depsgraph, ar, v3d, false, do_camera_frame);
- }
-
DRW_draw_callbacks_pre_scene();
if (DST.draw_ctx.evil_C) {
ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.ar, REGION_DRAW_PRE_VIEW);
@@ -1734,10 +1717,6 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
DRW_stats_reset();
- if (do_bg_image) {
- ED_view3d_draw_bgpic_test(scene, depsgraph, ar, v3d, true, do_camera_frame);
- }
-
if (G.debug_value > 20 && G.debug_value < 30) {
GPU_depth_test(false);
rcti rect; /* local coordinate visible rect inside region, to accommodate overlapping ui */
diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c
index e8c600ee545..1c60fc09057 100644
--- a/source/blender/draw/modes/object_mode.c
+++ b/source/blender/draw/modes/object_mode.c
@@ -38,6 +38,7 @@
#include "DNA_rigidbody_types.h"
#include "DNA_smoke_types.h"
#include "DNA_view3d_types.h"
+#include "DNA_screen_types.h"
#include "DNA_world_types.h"
#include "BKE_anim.h"
@@ -45,6 +46,7 @@
#include "BKE_constraint.h"
#include "BKE_curve.h"
#include "BKE_editmesh.h"
+#include "BKE_image.h"
#include "BKE_mball.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
@@ -55,6 +57,8 @@
#include "BLI_ghash.h"
+#include "IMB_imbuf_types.h"
+
#include "ED_view3d.h"
#include "GPU_batch.h"
@@ -80,6 +84,8 @@ extern char datatoc_object_outline_detect_frag_glsl[];
extern char datatoc_object_outline_expand_frag_glsl[];
extern char datatoc_object_grid_frag_glsl[];
extern char datatoc_object_grid_vert_glsl[];
+extern char datatoc_object_camera_image_frag_glsl[];
+extern char datatoc_object_camera_image_vert_glsl[];
extern char datatoc_object_empty_image_frag_glsl[];
extern char datatoc_object_empty_image_vert_glsl[];
extern char datatoc_object_lightprobe_grid_vert_glsl[];
@@ -87,6 +93,7 @@ extern char datatoc_object_loose_points_frag_glsl[];
extern char datatoc_object_particle_prim_vert_glsl[];
extern char datatoc_object_particle_dot_vert_glsl[];
extern char datatoc_object_particle_dot_frag_glsl[];
+extern char datatoc_common_colormanagement_lib_glsl[];
extern char datatoc_common_globals_lib_glsl[];
extern char datatoc_common_view_lib_glsl[];
extern char datatoc_common_fxaa_lib_glsl[];
@@ -115,6 +122,8 @@ typedef struct OBJECT_PassList {
struct DRWPass *bone_axes[2];
struct DRWPass *particle;
struct DRWPass *lightprobes;
+ struct DRWPass *camera_images_back;
+ struct DRWPass *camera_images_front;
} OBJECT_PassList;
typedef struct OBJECT_FramebufferList {
@@ -148,6 +157,8 @@ typedef struct OBJECT_Shaders {
GPUShader *outline_fade_large;
/* regular shaders */
+ GPUShader *object_camera_image;
+ GPUShader *object_camera_image_cm;
GPUShader *object_empty_image;
GPUShader *object_empty_image_wire;
GPUShader *grid;
@@ -336,6 +347,7 @@ static struct {
struct GPUTexture *outlines_blur_tx;
ListBase smoke_domains;
+ ListBase movie_clips;
} e_data = {NULL}; /* Engine data */
enum {
@@ -460,7 +472,9 @@ static void OBJECT_engine_init(void *vedata)
datatoc_common_view_lib_glsl,
datatoc_object_empty_image_vert_glsl,
NULL},
- .frag = (const char *[]){datatoc_object_empty_image_frag_glsl, NULL},
+ .frag = (const char *[]){datatoc_common_colormanagement_lib_glsl,
+ datatoc_object_empty_image_frag_glsl,
+ NULL},
.defs = (const char *[]){sh_cfg_data->def, empty_image_defs, NULL},
});
sh_data->object_empty_image_wire = GPU_shader_create_from_arrays({
@@ -471,6 +485,21 @@ static void OBJECT_engine_init(void *vedata)
.frag = (const char *[]){datatoc_object_empty_image_frag_glsl, NULL},
.defs = (const char *[]){sh_cfg_data->def, "#define USE_WIRE\n", empty_image_defs, NULL},
});
+
+ sh_data->object_camera_image_cm = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){sh_cfg_data->lib, datatoc_object_camera_image_vert_glsl, NULL},
+ .frag = (const char *[]){datatoc_common_colormanagement_lib_glsl,
+ datatoc_object_camera_image_frag_glsl,
+ NULL},
+ .defs =
+ (const char *[]){sh_cfg_data->def, "#define DRW_STATE_DO_COLOR_MANAGEMENT\n", NULL},
+ });
+ sh_data->object_camera_image = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){sh_cfg_data->lib, datatoc_object_camera_image_vert_glsl, NULL},
+ .frag = (const char *[]){datatoc_common_colormanagement_lib_glsl,
+ datatoc_object_camera_image_frag_glsl,
+ NULL},
+ });
}
/* Grid */
@@ -1035,6 +1064,291 @@ static void DRW_shgroup_empty_image(OBJECT_Shaders *sh_data,
}
}
+/* Draw Camera Background Images */
+typedef struct CameraEngineData {
+ DrawData dd;
+ ListBase bg_data;
+} CameraEngineData;
+typedef struct CameraEngineBGData {
+ float transform_mat[4][4];
+} CameraEngineBGData;
+
+static void camera_engine_data_free(DrawData *dd)
+{
+ CameraEngineData *data = (CameraEngineData *)dd;
+ for (LinkData *link = data->bg_data.first; link; link = link->next) {
+ CameraEngineBGData *bg_data = (CameraEngineBGData *)link->data;
+ MEM_freeN(bg_data);
+ }
+ BLI_freelistN(&data->bg_data);
+}
+
+static void camera_background_images_stereo_setup(Scene *scene,
+ View3D *v3d,
+ Image *ima,
+ ImageUser *iuser)
+{
+ if (BKE_image_is_stereo(ima)) {
+ iuser->flag |= IMA_SHOW_STEREO;
+
+ if ((scene->r.scemode & R_MULTIVIEW) == 0) {
+ iuser->multiview_eye = STEREO_LEFT_ID;
+ }
+ else if (v3d->stereo3d_camera != STEREO_3D_ID) {
+ /* show only left or right camera */
+ iuser->multiview_eye = v3d->stereo3d_camera;
+ }
+
+ BKE_image_multiview_index(ima, iuser);
+ }
+ else {
+ iuser->flag &= ~IMA_SHOW_STEREO;
+ }
+}
+
+static void DRW_shgroup_camera_background_images(OBJECT_Shaders *sh_data,
+ OBJECT_PassList *psl,
+ Object *ob,
+ RegionView3D *rv3d)
+{
+ if (!BKE_object_empty_image_frame_is_visible_in_view3d(ob, rv3d)) {
+ return;
+ }
+
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ struct ARegion *ar = draw_ctx->ar;
+ View3D *v3d = draw_ctx->v3d;
+ Scene *scene = draw_ctx->scene;
+ Depsgraph *depsgraph = draw_ctx->depsgraph;
+ Camera *cam = ob->data;
+ const Object *camera_object = DEG_get_evaluated_object(depsgraph, v3d->camera);
+ const bool is_active = (ob == camera_object);
+ const bool look_through = (is_active && (rv3d->persp == RV3D_CAMOB));
+
+ if (look_through && (cam->flag & CAM_SHOW_BG_IMAGE)) {
+ GPUBatch *batch = DRW_cache_image_plane_get();
+
+ /* load camera engine data */
+ CameraEngineData *camera_engine_data = (CameraEngineData *)DRW_drawdata_ensure(
+ &ob->id,
+ &draw_engine_object_type,
+ sizeof(CameraEngineData),
+ NULL,
+ camera_engine_data_free);
+ LinkData *list_node = camera_engine_data->bg_data.first;
+
+ for (CameraBGImage *bgpic = cam->bg_images.first; bgpic; bgpic = bgpic->next) {
+ if ((bgpic->flag & CAM_BGIMG_FLAG_DISABLED)) {
+ continue;
+ }
+
+ /* retrieve the image we want to show, continue to next when no image could be found */
+ ImBuf *ibuf = NULL;
+ GPUTexture *tex = NULL;
+ float image_aspect_x, image_aspect_y;
+ float image_aspect = 1.0;
+ int image_width, image_height;
+ bool premultiplied = false;
+
+ if (bgpic->source == CAM_BGIMG_SOURCE_IMAGE) {
+ Image *image = bgpic->ima;
+ if (image == NULL) {
+ continue;
+ }
+ premultiplied = (image->alpha_mode == IMA_ALPHA_PREMUL);
+ ImageUser *iuser = &bgpic->iuser;
+ BKE_image_user_frame_calc(image, iuser, (int)DEG_get_ctime(depsgraph));
+ if (image->source == IMA_SRC_SEQUENCE && !(iuser->flag & IMA_USER_FRAME_IN_RANGE)) {
+ /* frame is out of range, dont show */
+ continue;
+ }
+ else {
+ camera_background_images_stereo_setup(scene, v3d, image, iuser);
+ }
+ tex = GPU_texture_from_blender(image, iuser, GL_TEXTURE_2D);
+ if (tex == NULL) {
+ continue;
+ }
+ ibuf = BKE_image_acquire_ibuf(image, iuser, NULL);
+ if (ibuf == NULL) {
+ continue;
+ }
+
+ image_aspect_x = bgpic->ima->aspx;
+ image_aspect_y = bgpic->ima->aspy;
+
+ image_width = ibuf->x;
+ image_height = ibuf->y;
+ BKE_image_release_ibuf(image, ibuf, NULL);
+ image_aspect = (image_width * image_aspect_x) / (image_height * image_aspect_y);
+ }
+ else if (bgpic->source == CAM_BGIMG_SOURCE_MOVIE) {
+ MovieClip *clip = NULL;
+ if (bgpic->flag & CAM_BGIMG_FLAG_CAMERACLIP) {
+ if (scene->camera) {
+ clip = BKE_object_movieclip_get(scene, scene->camera, true);
+ }
+ }
+ else {
+ clip = bgpic->clip;
+ }
+
+ if (clip == NULL) {
+ continue;
+ }
+
+ image_aspect_x = clip->aspx;
+ image_aspect_y = clip->aspy;
+
+ BKE_movieclip_user_set_frame(&bgpic->cuser, (int)DEG_get_ctime(depsgraph));
+ tex = GPU_texture_from_movieclip(clip, &bgpic->cuser, GL_TEXTURE_2D);
+ if (tex == NULL) {
+ continue;
+ }
+ BLI_addtail(&e_data.movie_clips, BLI_genericNodeN(clip));
+ BKE_movieclip_get_size(clip, &bgpic->cuser, &image_width, &image_height);
+ image_aspect = (image_width * image_aspect_x) / (image_height * image_aspect_y);
+ }
+
+ /* ensure link_data is allocated to store matrice */
+ CameraEngineBGData *bg_data;
+ if (list_node != NULL) {
+ bg_data = (CameraEngineBGData *)list_node->data;
+ list_node = list_node->next;
+ }
+ else {
+ bg_data = MEM_mallocN(sizeof(CameraEngineBGData), __func__);
+ BLI_addtail(&camera_engine_data->bg_data, BLI_genericNodeN(bg_data));
+ }
+
+ /* calculate the transformation matric for the current bg image */
+ float uv2img_space[4][4];
+ float img2cam_space[4][4];
+ float rot_m4[4][4];
+ float scale_m4[4][4];
+ float translate_m4[4][4];
+ float win_m4_scale[4][4];
+ float win_m4_translate[4][4];
+
+ unit_m4(uv2img_space);
+ unit_m4(img2cam_space);
+ unit_m4(win_m4_scale);
+ unit_m4(win_m4_translate);
+ unit_m4(scale_m4);
+ axis_angle_to_mat4_single(rot_m4, 'Z', bgpic->rotation);
+ unit_m4(translate_m4);
+
+ const float *size = DRW_viewport_size_get();
+ float camera_aspect_x = 1.0;
+ float camera_aspect_y = 1.0;
+ float camera_offset_x = 0.0;
+ float camera_offset_y = 0.0;
+ float camera_aspect = 1.0;
+ float camera_width = size[0];
+ float camera_height = size[1];
+
+ if (!DRW_state_is_image_render()) {
+ rctf render_border;
+ ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &render_border, true);
+ camera_width = render_border.xmax - render_border.xmin;
+ camera_height = render_border.ymax - render_border.ymin;
+ camera_aspect = camera_width / camera_height;
+ const float camera_aspect_center_x = (render_border.xmax + render_border.xmin) / 2.0;
+ const float camera_aspect_center_y = (render_border.ymax + render_border.ymin) / 2.0;
+
+ camera_aspect_x = camera_width / size[0];
+ camera_aspect_y = camera_height / size[1];
+ win_m4_scale[0][0] = camera_aspect_x;
+ win_m4_scale[1][1] = camera_aspect_y;
+
+ camera_offset_x = (camera_aspect_center_x - (ar->winx / 2.0)) /
+ (0.5 * camera_width / camera_aspect_x);
+ camera_offset_y = (camera_aspect_center_y - (ar->winy / 2.0)) /
+ (0.5 * camera_height / camera_aspect_y);
+ win_m4_translate[3][0] = camera_offset_x;
+ win_m4_translate[3][1] = camera_offset_y;
+ }
+
+ /* Convert from uv space to image space -0.5..-.5 */
+ uv2img_space[0][0] = image_width;
+ uv2img_space[1][1] = image_height;
+
+ img2cam_space[0][0] = (1.0 / image_width);
+ img2cam_space[1][1] = (1.0 / image_height);
+
+ /* Update scaling based on image and camera framing */
+ float scale_x = bgpic->scale;
+ float scale_y = bgpic->scale;
+
+ if (bgpic->flag & CAM_BGIMG_FLAG_CAMERA_ASPECT) {
+ float fit_scale = image_aspect / camera_aspect;
+ if (bgpic->flag & CAM_BGIMG_FLAG_CAMERA_CROP) {
+ if (image_aspect > camera_aspect) {
+ scale_x *= fit_scale;
+ }
+ else {
+ scale_y /= fit_scale;
+ }
+ }
+ else {
+ if (image_aspect > camera_aspect) {
+ scale_y /= fit_scale;
+ }
+ else {
+ scale_x *= fit_scale;
+ }
+ }
+ }
+
+ // scale image to match the desired aspect ratio
+ scale_m4[0][0] = scale_x;
+ scale_m4[1][1] = scale_y;
+
+ // translate
+ translate_m4[3][0] = bgpic->offset[0];
+ translate_m4[3][1] = bgpic->offset[1];
+
+ mul_m4_series(bg_data->transform_mat,
+ win_m4_translate,
+ win_m4_scale,
+ translate_m4,
+ img2cam_space,
+ scale_m4,
+ rot_m4,
+ uv2img_space);
+
+ DRWPass *pass = (bgpic->flag & CAM_BGIMG_FLAG_FOREGROUND) ? psl->camera_images_front :
+ psl->camera_images_back;
+ GPUShader *shader = DRW_state_do_color_management() ? sh_data->object_camera_image_cm :
+ sh_data->object_camera_image;
+ DRWShadingGroup *grp = DRW_shgroup_create(shader, pass);
+
+ DRW_shgroup_uniform_float_copy(
+ grp, "depth", (bgpic->flag & CAM_BGIMG_FLAG_FOREGROUND) ? 0.000001 : 0.999999);
+ DRW_shgroup_uniform_float_copy(grp, "alpha", bgpic->alpha);
+ DRW_shgroup_uniform_texture(grp, "image", tex);
+ DRW_shgroup_uniform_bool_copy(grp, "imagePremultiplied", premultiplied);
+
+ DRW_shgroup_uniform_float_copy(
+ grp, "flipX", (bgpic->flag & CAM_BGIMG_FLAG_FLIP_X) ? -1.0 : 1.0);
+ DRW_shgroup_uniform_float_copy(
+ grp, "flipY", (bgpic->flag & CAM_BGIMG_FLAG_FLIP_Y) ? -1.0 : 1.0);
+ DRW_shgroup_uniform_mat4(grp, "TransformMat", bg_data->transform_mat);
+
+ DRW_shgroup_call(grp, batch, NULL);
+ }
+ }
+}
+
+static void camera_background_images_free_textures(void)
+{
+ for (LinkData *link = e_data.movie_clips.first; link; link = link->next) {
+ MovieClip *clip = (MovieClip *)link->data;
+ GPU_free_texture_movieclip(clip);
+ }
+ BLI_freelistN(&e_data.movie_clips);
+}
+
static void OBJECT_cache_init(void *vedata)
{
const GlobalsUboStorage *gb = &G_draw.block;
@@ -1206,6 +1520,13 @@ static void OBJECT_cache_init(void *vedata)
DRW_shgroup_call(grp, geom, NULL);
}
+ /* Camera background images */
+ {
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_ALPHA;
+ psl->camera_images_back = DRW_pass_create("Camera Images Back", state);
+ psl->camera_images_front = DRW_pass_create("Camera Images Front", state);
+ }
+
for (int i = 0; i < 2; ++i) {
OBJECT_ShadingGroupList *sgl = (i == 1) ? &stl->g_data->sgl_ghost : &stl->g_data->sgl;
@@ -3266,6 +3587,7 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
break;
}
DRW_shgroup_camera(sgl, ob, view_layer);
+ DRW_shgroup_camera_background_images(sh_data, psl, ob, rv3d);
break;
case OB_EMPTY:
if (hide_object_extra) {
@@ -3449,6 +3771,8 @@ static void OBJECT_draw_scene(void *vedata)
float clearcol[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ DRW_draw_pass(psl->camera_images_back);
+
/* Don't draw Transparent passes in MSAA buffer. */
// DRW_draw_pass(psl->bone_envelope); /* Never drawn in Object mode currently. */
DRW_draw_pass(stl->g_data->sgl.transp_shapes);
@@ -3518,7 +3842,6 @@ static void OBJECT_draw_scene(void *vedata)
DRW_draw_pass(psl->outlines_resolve);
}
}
-
volumes_free_smoke_textures();
batch_camera_path_free(&stl->g_data->sgl.camera_path);
@@ -3567,6 +3890,9 @@ static void OBJECT_draw_scene(void *vedata)
batch_camera_path_free(&stl->g_data->sgl_ghost.camera_path);
+ DRW_draw_pass(psl->camera_images_front);
+ camera_background_images_free_textures();
+
DRW_draw_pass(psl->ob_center);
}
diff --git a/source/blender/draw/modes/paint_texture_mode.c b/source/blender/draw/modes/paint_texture_mode.c
index 5f833e4c6a1..82c11a278de 100644
--- a/source/blender/draw/modes/paint_texture_mode.c
+++ b/source/blender/draw/modes/paint_texture_mode.c
@@ -40,6 +40,7 @@
#include "DEG_depsgraph_query.h"
+extern char datatoc_common_colormanagement_lib_glsl[];
extern char datatoc_common_globals_lib_glsl[];
extern char datatoc_common_view_lib_glsl[];
extern char datatoc_paint_texture_vert_glsl[];
@@ -160,7 +161,9 @@ static void PAINT_TEXTURE_engine_init(void *vedata)
datatoc_common_view_lib_glsl,
datatoc_paint_texture_vert_glsl,
NULL},
- .frag = (const char *[]){datatoc_paint_texture_frag_glsl, NULL},
+ .frag = (const char *[]){datatoc_common_colormanagement_lib_glsl,
+ datatoc_paint_texture_frag_glsl,
+ NULL},
.defs = (const char *[]){sh_cfg_data->def, NULL},
});
diff --git a/source/blender/draw/modes/shaders/common_colormanagement_lib.glsl b/source/blender/draw/modes/shaders/common_colormanagement_lib.glsl
new file mode 100644
index 00000000000..45f711296f3
--- /dev/null
+++ b/source/blender/draw/modes/shaders/common_colormanagement_lib.glsl
@@ -0,0 +1,30 @@
+float linearrgb_to_srgb(float c)
+{
+ if (c < 0.0031308) {
+ return (c < 0.0) ? 0.0 : c * 12.92;
+ }
+ else {
+ return 1.055 * pow(c, 1.0 / 2.4) - 0.055;
+ }
+}
+
+vec4 texture_read_as_linearrgb(sampler2D tex, bool premultiplied, vec2 co)
+{
+ /* By convention image textures return scene linear colors, but
+ * overlays still assume srgb. */
+ vec4 color = texture(tex, co);
+ /* Unpremultiply if stored multiplied, since straight alpha is expected by shaders. */
+ if (premultiplied && !(color.a == 0.0 || color.a == 1.0)) {
+ color.rgb = color.rgb / color.a;
+ }
+ return color;
+}
+
+vec4 texture_read_as_srgb(sampler2D tex, bool premultiplied, vec2 co)
+{
+ vec4 color = texture_read_as_linearrgb(tex, premultiplied, co);
+ color.r = linearrgb_to_srgb(color.r);
+ color.g = linearrgb_to_srgb(color.g);
+ color.b = linearrgb_to_srgb(color.b);
+ return color;
+}
diff --git a/source/blender/draw/modes/shaders/object_camera_image_frag.glsl b/source/blender/draw/modes/shaders/object_camera_image_frag.glsl
new file mode 100644
index 00000000000..5d8ad3c79ea
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_camera_image_frag.glsl
@@ -0,0 +1,23 @@
+in vec2 texCoord_interp;
+out vec4 fragColor;
+
+uniform sampler2D image;
+uniform float alpha;
+uniform bool imagePremultiplied;
+
+void main()
+{
+#ifdef DRW_STATE_DO_COLOR_MANAGEMENT
+ /* render engine has already applied the view transform. We sample the
+ * camera images as srgb*/
+ vec4 color = texture_read_as_srgb(image, imagePremultiplied, texCoord_interp);
+
+#else
+ /* Render engine renders in linearrgb. We sample the camera images as
+ * linearrgb */
+ vec4 color = texture_read_as_linearrgb(image, imagePremultiplied, texCoord_interp);
+#endif
+
+ color.a *= alpha;
+ fragColor = color;
+}
diff --git a/source/blender/draw/modes/shaders/object_camera_image_vert.glsl b/source/blender/draw/modes/shaders/object_camera_image_vert.glsl
new file mode 100644
index 00000000000..61b88c013aa
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_camera_image_vert.glsl
@@ -0,0 +1,18 @@
+uniform mat4 TransformMat;
+uniform float flipX;
+uniform float flipY;
+uniform float depth;
+
+in vec2 texCoord;
+in vec2 pos;
+
+out vec2 texCoord_interp;
+
+void main()
+{
+ vec4 position = TransformMat * vec4((pos - 0.5) * 2.0, 1.0, 1.0);
+ gl_Position = vec4(position.xy, depth, 1.0);
+
+ vec2 uv_mul = vec2(flipX, flipY);
+ texCoord_interp = texCoord * uv_mul;
+}
diff --git a/source/blender/draw/modes/shaders/object_empty_image_frag.glsl b/source/blender/draw/modes/shaders/object_empty_image_frag.glsl
index 88220140aec..7dfbf469adc 100644
--- a/source/blender/draw/modes/shaders/object_empty_image_frag.glsl
+++ b/source/blender/draw/modes/shaders/object_empty_image_frag.glsl
@@ -15,31 +15,6 @@ uniform bool imagePremultiplied;
uniform int depthMode;
uniform bool useAlphaTest;
-float linearrgb_to_srgb(float c)
-{
- if (c < 0.0031308) {
- return (c < 0.0) ? 0.0 : c * 12.92;
- }
- else {
- return 1.055 * pow(c, 1.0 / 2.4) - 0.055;
- }
-}
-
-vec4 texture_read_as_srgb(sampler2D tex, bool premultiplied, vec2 co)
-{
- /* By convention image textures return scene linear colors, but
- * overlays still assume srgb. */
- vec4 color = texture(tex, co);
- /* Unpremultiply if stored multiplied, since straight alpha is expected by shaders. */
- if (premultiplied && !(color.a == 0.0 || color.a == 1.0)) {
- color.rgb = color.rgb / color.a;
- }
- color.r = linearrgb_to_srgb(color.r);
- color.g = linearrgb_to_srgb(color.g);
- color.b = linearrgb_to_srgb(color.b);
- return color;
-}
-
void main()
{
#ifdef USE_WIRE
diff --git a/source/blender/draw/modes/shaders/paint_texture_frag.glsl b/source/blender/draw/modes/shaders/paint_texture_frag.glsl
index af7ea99e6a1..e8722590802 100644
--- a/source/blender/draw/modes/shaders/paint_texture_frag.glsl
+++ b/source/blender/draw/modes/shaders/paint_texture_frag.glsl
@@ -18,31 +18,6 @@ uniform vec3 maskingColor;
uniform bool maskingInvertStencil;
#endif
-float linearrgb_to_srgb(float c)
-{
- if (c < 0.0031308) {
- return (c < 0.0) ? 0.0 : c * 12.92;
- }
- else {
- return 1.055 * pow(c, 1.0 / 2.4) - 0.055;
- }
-}
-
-vec4 texture_read_as_srgb(sampler2D tex, bool premultiplied, vec2 co)
-{
- /* By convention image textures return scene linear colors, but
- * overlays still assume srgb. */
- vec4 color = texture(tex, co);
- /* Unpremultiply if stored multiplied, since straight alpha is expected by shaders. */
- if (premultiplied && !(color.a == 0.0 || color.a == 1.0)) {
- color.rgb = color.rgb / color.a;
- }
- color.r = linearrgb_to_srgb(color.r);
- color.g = linearrgb_to_srgb(color.g);
- color.b = linearrgb_to_srgb(color.b);
- return color;
-}
-
void main()
{
vec2 uv = uv_interp;
diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c
index 08ac0d91d42..386c3164843 100644
--- a/source/blender/editors/space_view3d/view3d_draw_legacy.c
+++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c
@@ -301,341 +301,6 @@ uint *ED_view3d_select_id_read(int xmin, int ymin, int xmax, int ymax, uint *r_b
return buf;
}
-/* ************************************************************* */
-
-static void view3d_stereo_bgpic_setup(Scene *scene, View3D *v3d, Image *ima, ImageUser *iuser)
-{
- if (BKE_image_is_stereo(ima)) {
- iuser->flag |= IMA_SHOW_STEREO;
-
- if ((scene->r.scemode & R_MULTIVIEW) == 0) {
- iuser->multiview_eye = STEREO_LEFT_ID;
- }
- else if (v3d->stereo3d_camera != STEREO_3D_ID) {
- /* show only left or right camera */
- iuser->multiview_eye = v3d->stereo3d_camera;
- }
-
- BKE_image_multiview_index(ima, iuser);
- }
- else {
- iuser->flag &= ~IMA_SHOW_STEREO;
- }
-}
-
-static void view3d_draw_bgpic(Scene *scene,
- Depsgraph *depsgraph,
- ARegion *ar,
- View3D *v3d,
- const bool do_foreground,
- const bool do_camera_frame)
-{
- RegionView3D *rv3d = ar->regiondata;
- int fg_flag = do_foreground ? CAM_BGIMG_FLAG_FOREGROUND : 0;
- if (v3d->camera == NULL || v3d->camera->type != OB_CAMERA) {
- return;
- }
- Camera *cam = v3d->camera->data;
-
- for (CameraBGImage *bgpic = cam->bg_images.first; bgpic; bgpic = bgpic->next) {
- if ((bgpic->flag & CAM_BGIMG_FLAG_FOREGROUND) != fg_flag) {
- continue;
- }
-
- {
- float image_aspect[2];
- float x1, y1, x2, y2, centx, centy;
-
- void *lock;
-
- Image *ima = NULL;
-
- /* disable individual images */
- if ((bgpic->flag & CAM_BGIMG_FLAG_DISABLED)) {
- continue;
- }
-
- ImBuf *ibuf = NULL;
- ImBuf *freeibuf = NULL;
- ImBuf *releaseibuf = NULL;
- if (bgpic->source == CAM_BGIMG_SOURCE_IMAGE) {
- ima = bgpic->ima;
- if (ima == NULL) {
- continue;
- }
-
- ImageUser iuser = bgpic->iuser;
- iuser.scene = scene; /* Needed for render results. */
- BKE_image_user_frame_calc(ima, &iuser, (int)DEG_get_ctime(depsgraph));
- if (ima->source == IMA_SRC_SEQUENCE && !(iuser.flag & IMA_USER_FRAME_IN_RANGE)) {
- ibuf = NULL; /* frame is out of range, dont show */
- }
- else {
- view3d_stereo_bgpic_setup(scene, v3d, ima, &iuser);
- ibuf = BKE_image_acquire_ibuf(ima, &iuser, &lock);
- releaseibuf = ibuf;
- }
-
- image_aspect[0] = ima->aspx;
- image_aspect[1] = ima->aspy;
- }
- else if (bgpic->source == CAM_BGIMG_SOURCE_MOVIE) {
- /* TODO: skip drawing when out of frame range (as image sequences do above) */
- MovieClip *clip = NULL;
-
- if (bgpic->flag & CAM_BGIMG_FLAG_CAMERACLIP) {
- if (scene->camera) {
- clip = BKE_object_movieclip_get(scene, scene->camera, true);
- }
- }
- else {
- clip = bgpic->clip;
- }
-
- if (clip == NULL) {
- continue;
- }
-
- BKE_movieclip_user_set_frame(&bgpic->cuser, (int)DEG_get_ctime(depsgraph));
- ibuf = BKE_movieclip_get_ibuf(clip, &bgpic->cuser);
-
- image_aspect[0] = clip->aspx;
- image_aspect[1] = clip->aspy;
-
- /* working with ibuf from image and clip has got different workflow now.
- * ibuf acquired from clip is referenced by cache system and should
- * be dereferenced after usage. */
- freeibuf = ibuf;
- }
- else {
- /* perhaps when loading future files... */
- BLI_assert(0);
- copy_v2_fl(image_aspect, 1.0f);
- }
-
- if (ibuf == NULL) {
- continue;
- }
-
- if ((ibuf->rect == NULL && ibuf->rect_float == NULL) || ibuf->channels != 4) {
- /* invalid image format */
- if (freeibuf) {
- IMB_freeImBuf(freeibuf);
- }
- if (releaseibuf) {
- BKE_image_release_ibuf(ima, releaseibuf, lock);
- }
-
- continue;
- }
-
- if (ibuf->rect == NULL) {
- IMB_rect_from_float(ibuf);
- }
-
- BLI_assert(rv3d->persp == RV3D_CAMOB);
- {
- if (do_camera_frame) {
- rctf vb;
- ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &vb, false);
- x1 = vb.xmin;
- y1 = vb.ymin;
- x2 = vb.xmax;
- y2 = vb.ymax;
- }
- else {
- x1 = ar->winrct.xmin;
- y1 = ar->winrct.ymin;
- x2 = ar->winrct.xmax;
- y2 = ar->winrct.ymax;
- }
-
- /* apply offset last - camera offset is different to offset in blender units */
- /* so this has some sane way of working - this matches camera's shift _exactly_ */
- {
- const float max_dim = max_ff(x2 - x1, y2 - y1);
- const float xof_scale = bgpic->offset[0] * max_dim;
- const float yof_scale = bgpic->offset[1] * max_dim;
-
- x1 += xof_scale;
- y1 += yof_scale;
- x2 += xof_scale;
- y2 += yof_scale;
- }
-
- centx = (x1 + x2) * 0.5f;
- centy = (y1 + y2) * 0.5f;
-
- /* aspect correction */
- if (bgpic->flag & CAM_BGIMG_FLAG_CAMERA_ASPECT) {
- /* apply aspect from clip */
- const float w_src = ibuf->x * image_aspect[0];
- const float h_src = ibuf->y * image_aspect[1];
-
- /* destination aspect is already applied from the camera frame */
- const float w_dst = x1 - x2;
- const float h_dst = y1 - y2;
-
- const float asp_src = w_src / h_src;
- const float asp_dst = w_dst / h_dst;
-
- if (fabsf(asp_src - asp_dst) >= FLT_EPSILON) {
- if ((asp_src > asp_dst) == ((bgpic->flag & CAM_BGIMG_FLAG_CAMERA_CROP) != 0)) {
- /* fit X */
- const float div = asp_src / asp_dst;
- x1 = ((x1 - centx) * div) + centx;
- x2 = ((x2 - centx) * div) + centx;
- }
- else {
- /* fit Y */
- const float div = asp_dst / asp_src;
- y1 = ((y1 - centy) * div) + centy;
- y2 = ((y2 - centy) * div) + centy;
- }
- }
- }
- }
-
- /* complete clip? */
- rctf clip_rect;
- BLI_rctf_init(&clip_rect, x1, x2, y1, y2);
- if (bgpic->rotation) {
- BLI_rctf_rotate_expand(&clip_rect, &clip_rect, bgpic->rotation);
- }
-
- if (clip_rect.xmax < 0 || clip_rect.ymax < 0 || clip_rect.xmin > ar->winx ||
- clip_rect.ymin > ar->winy) {
- if (freeibuf) {
- IMB_freeImBuf(freeibuf);
- }
- if (releaseibuf) {
- BKE_image_release_ibuf(ima, releaseibuf, lock);
- }
-
- continue;
- }
-
- float zoomx = (x2 - x1) / ibuf->x;
- float zoomy = (y2 - y1) / ibuf->y;
-
- /* For some reason; zoom-levels down refuses to use GL_ALPHA_SCALE. */
- if (zoomx < 1.0f || zoomy < 1.0f) {
- float tzoom = min_ff(zoomx, zoomy);
- int mip = 0;
-
- if ((ibuf->userflags & IB_MIPMAP_INVALID) != 0) {
- IMB_remakemipmap(ibuf, 0);
- ibuf->userflags &= ~IB_MIPMAP_INVALID;
- }
- else if (ibuf->mipmap[0] == NULL) {
- IMB_makemipmap(ibuf, 0);
- }
-
- while (tzoom < 1.0f && mip < 8 && ibuf->mipmap[mip]) {
- tzoom *= 2.0f;
- zoomx *= 2.0f;
- zoomy *= 2.0f;
- mip++;
- }
- if (mip > 0) {
- ibuf = ibuf->mipmap[mip - 1];
- }
- }
-
- GPU_depth_test(!do_foreground);
- glDepthMask(GL_FALSE);
-
- GPU_blend(true);
- GPU_blend_set_func_separate(
- GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
-
- GPU_matrix_push_projection();
- GPU_matrix_push();
- ED_region_pixelspace(ar);
-
- GPU_matrix_translate_2f(centx, centy);
- GPU_matrix_scale_1f(bgpic->scale);
- GPU_matrix_rotate_2d(RAD2DEGF(-bgpic->rotation));
-
- if (bgpic->flag & CAM_BGIMG_FLAG_FLIP_X) {
- zoomx *= -1.0f;
- x1 = x2;
- }
- if (bgpic->flag & CAM_BGIMG_FLAG_FLIP_Y) {
- zoomy *= -1.0f;
- y1 = y2;
- }
-
- float col[4] = {1.0f, 1.0f, 1.0f, bgpic->alpha};
- IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
- immDrawPixelsTex(&state,
- x1 - centx,
- y1 - centy,
- ibuf->x,
- ibuf->y,
- GL_RGBA,
- GL_UNSIGNED_BYTE,
- GL_LINEAR,
- ibuf->rect,
- zoomx,
- zoomy,
- col);
-
- GPU_matrix_pop_projection();
- GPU_matrix_pop();
-
- GPU_blend(false);
-
- glDepthMask(GL_TRUE);
- GPU_depth_test(true);
-
- if (freeibuf) {
- IMB_freeImBuf(freeibuf);
- }
- if (releaseibuf) {
- BKE_image_release_ibuf(ima, releaseibuf, lock);
- }
- }
- }
-}
-
-void ED_view3d_draw_bgpic_test(Scene *scene,
- Depsgraph *depsgraph,
- ARegion *ar,
- View3D *v3d,
- const bool do_foreground,
- const bool do_camera_frame)
-{
- RegionView3D *rv3d = ar->regiondata;
-
- if ((rv3d->persp == RV3D_CAMOB) && v3d->camera && (v3d->camera->type == OB_CAMERA)) {
- Camera *cam = v3d->camera->data;
- if ((cam->flag & CAM_SHOW_BG_IMAGE) == 0) {
- return;
- }
- }
- else {
- return;
- }
-
- /* disabled - mango request, since footage /w only render is quite useful
- * and this option is easy to disable all background images at once */
-#if 0
- if (v3d->flag2 & V3D_HIDE_OVERLAYS) {
- return;
- }
-#endif
-
- if ((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) {
- if (rv3d->persp == RV3D_CAMOB) {
- view3d_draw_bgpic(scene, depsgraph, ar, v3d, do_foreground, do_camera_frame);
- }
- }
- else {
- view3d_draw_bgpic(scene, depsgraph, ar, v3d, do_foreground, do_camera_frame);
- }
-}
-
/* *********************** */
void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect)
diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
index 3fb7dfc6331..d5e763987cb 100644
--- a/source/blender/gpu/GPU_texture.h
+++ b/source/blender/gpu/GPU_texture.h
@@ -33,6 +33,8 @@ extern "C" {
struct GPUVertBuf;
struct Image;
struct ImageUser;
+struct MovieClip;
+struct MovieClipUser;
struct PreviewImage;
struct rcti;
@@ -189,6 +191,12 @@ GPUTexture *GPU_texture_from_bindcode(int textarget, int bindcode);
GPUTexture *GPU_texture_from_blender(struct Image *ima, struct ImageUser *iuser, int textarget);
GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap);
+/* movie clip drawing */
+GPUTexture *GPU_texture_from_movieclip(struct MovieClip *clip,
+ struct MovieClipUser *cuser,
+ int textarget);
+void GPU_free_texture_movieclip(struct MovieClip *clip);
+
void GPU_texture_add_mipmap(GPUTexture *tex,
eGPUDataFormat gpu_data_format,
int miplvl,
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index 7813ae68371..f5d599eb647 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -59,6 +59,7 @@
#include "BKE_image.h"
#include "BKE_main.h"
#include "BKE_material.h"
+#include "BKE_movieclip.h"
#include "BKE_node.h"
#include "BKE_scene.h"
@@ -247,7 +248,7 @@ static uint gpu_texture_create_from_ibuf(Image *ima, ImBuf *ibuf, int textarget)
* this allows us to use sRGB texture formats and preserves color values in
* zero alpha areas, and appears generally closer to what game engines that we
* want to be compatible with do. */
- const bool store_premultiplied = (ima->alpha_mode == IMA_ALPHA_PREMUL);
+ const bool store_premultiplied = ima ? (ima->alpha_mode == IMA_ALPHA_PREMUL) : true;
IMB_colormanagement_imbuf_to_byte_texture(
rect, 0, 0, ibuf->x, ibuf->y, ibuf, compress_as_srgb, store_premultiplied);
}
@@ -256,14 +257,13 @@ static uint gpu_texture_create_from_ibuf(Image *ima, ImBuf *ibuf, int textarget)
/* Float image is already in scene linear colorspace or non-color data by
* convention, no colorspace conversion needed. But we do require 4 channels
* currently. */
- const bool store_premultiplied = (ima->alpha_mode != IMA_ALPHA_STRAIGHT);
+ const bool store_premultiplied = ima ? (ima->alpha_mode != IMA_ALPHA_STRAIGHT) : false;
if (ibuf->channels != 4 || !store_premultiplied) {
rect_float = MEM_mallocN(sizeof(float) * 4 * ibuf->x * ibuf->y, __func__);
if (rect_float == NULL) {
return bindcode;
}
-
IMB_colormanagement_imbuf_to_float_texture(
rect_float, 0, 0, ibuf->x, ibuf->y, ibuf, store_premultiplied);
}
@@ -291,6 +291,36 @@ static uint gpu_texture_create_from_ibuf(Image *ima, ImBuf *ibuf, int textarget)
return bindcode;
}
+static GPUTexture **gpu_get_movieclip_gputexture(MovieClip *clip,
+ MovieClipUser *cuser,
+ GLenum textarget)
+{
+ MovieClip_RuntimeGPUTexture *tex;
+ for (tex = clip->runtime.gputextures.first; tex; tex = tex->next) {
+ if (memcmp(&tex->user, cuser, sizeof(MovieClipUser)) == 0) {
+ break;
+ }
+ }
+
+ if (tex == NULL) {
+ tex = MEM_mallocN(sizeof(MovieClip_RuntimeGPUTexture), __func__);
+
+ for (int i = 0; i < TEXTARGET_COUNT; i++) {
+ tex->gputexture[i] = NULL;
+ }
+
+ memcpy(&tex->user, cuser, sizeof(MovieClipUser));
+ BLI_addtail(&clip->runtime.gputextures, tex);
+ }
+
+ if (textarget == GL_TEXTURE_2D)
+ return &tex->gputexture[TEXTARGET_TEXTURE_2D];
+ else if (textarget == GL_TEXTURE_CUBE_MAP)
+ return &tex->gputexture[TEXTARGET_TEXTURE_CUBE_MAP];
+
+ return NULL;
+}
+
static void gpu_texture_update_scaled(
uchar *rect, float *rect_float, int full_w, int full_h, int x, int y, int w, int h)
{
@@ -472,6 +502,52 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget
return *tex;
}
+GPUTexture *GPU_texture_from_movieclip(MovieClip *clip, MovieClipUser *cuser, int textarget)
+{
+ if (clip == NULL) {
+ return NULL;
+ }
+
+ GPUTexture **tex = gpu_get_movieclip_gputexture(clip, cuser, textarget);
+ if (*tex) {
+ return *tex;
+ }
+
+ /* check if we have a valid image buffer */
+ uint bindcode = 0;
+ ImBuf *ibuf = BKE_movieclip_get_ibuf(clip, cuser);
+ if (ibuf == NULL) {
+ *tex = GPU_texture_from_bindcode(textarget, bindcode);
+ return *tex;
+ }
+
+ bindcode = gpu_texture_create_from_ibuf(NULL, ibuf, textarget);
+ IMB_freeImBuf(ibuf);
+
+ *tex = GPU_texture_from_bindcode(textarget, bindcode);
+ return *tex;
+}
+
+void GPU_free_texture_movieclip(struct MovieClip *clip)
+{
+ /* number of gpu textures to keep around as cache
+ * We don't want to keep too many GPU textures for
+ * movie clips around, as they can be large.*/
+ const int MOVIECLIP_NUM_GPUTEXTURES = 1;
+
+ while (BLI_listbase_count(&clip->runtime.gputextures) > MOVIECLIP_NUM_GPUTEXTURES) {
+ MovieClip_RuntimeGPUTexture *tex = BLI_pophead(&clip->runtime.gputextures);
+ for (int i = 0; i < TEXTARGET_COUNT; i++) {
+ /* free glsl image binding */
+ if (tex->gputexture[i]) {
+ GPU_texture_free(tex->gputexture[i]);
+ tex->gputexture[i] = NULL;
+ }
+ }
+ MEM_freeN(tex);
+ }
+}
+
static void **gpu_gen_cube_map(uint *rect, float *frect, int rectw, int recth)
{
size_t block_size = frect ? sizeof(float[4]) : sizeof(uchar[4]);
diff --git a/source/blender/makesdna/DNA_movieclip_types.h b/source/blender/makesdna/DNA_movieclip_types.h
index c804a78eccb..efda24d6e0e 100644
--- a/source/blender/makesdna/DNA_movieclip_types.h
+++ b/source/blender/makesdna/DNA_movieclip_types.h
@@ -57,6 +57,17 @@ typedef struct MovieClipProxy {
short build_tc_flag;
} MovieClipProxy;
+typedef struct MovieClip_RuntimeGPUTexture {
+ void *next, *prev;
+ MovieClipUser user;
+ /** Not written in file 2 = TEXTARGET_COUNT. */
+ struct GPUTexture *gputexture[2];
+} MovieClip_RuntimeGPUTexture;
+
+typedef struct MovieClip_Runtime {
+ struct ListBase gputextures;
+} MovieClip_Runtime;
+
typedef struct MovieClip {
ID id;
/** Animation data (must be immediately after id for utilities to use it). */
@@ -111,6 +122,8 @@ typedef struct MovieClip {
/* color management */
ColorManagedColorspaceSettings colorspace_settings;
+
+ struct MovieClip_Runtime runtime;
} MovieClip;
typedef struct MovieClipScopes {
diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c
index 7cb1610fd31..bb236fc3ef4 100644
--- a/source/blender/makesrna/intern/rna_camera.c
+++ b/source/blender/makesrna/intern/rna_camera.c
@@ -231,12 +231,14 @@ static void rna_def_camera_background_image(BlenderRNA *brna)
prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_XYZ);
RNA_def_property_float_sdna(prop, NULL, "offset");
RNA_def_property_ui_text(prop, "Offset", "");
+ RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 0.1, RNA_TRANSLATION_PREC_DEFAULT);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "scale");
RNA_def_property_ui_text(prop, "Scale", "Scale the background image");
RNA_def_property_range(prop, 0.0, FLT_MAX);
+ RNA_def_property_ui_range(prop, 0.0, 10.0, 0.100, RNA_TRANSLATION_PREC_DEFAULT);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_ANGLE);