Overlay-Next: Image
Overlay-Next version of image. Rel #102179 Co-authored-by: Clément Foucault <foucault.clem@gmail.com> Pull Request: https://projects.blender.org/blender/blender/pulls/126243
This commit is contained in:
committed by
Clément Foucault
parent
cb03748e45
commit
ce28af7352
@@ -300,6 +300,7 @@ set(SRC
|
|||||||
engines/overlay/overlay_next_force_field.hh
|
engines/overlay/overlay_next_force_field.hh
|
||||||
engines/overlay/overlay_next_grease_pencil.hh
|
engines/overlay/overlay_next_grease_pencil.hh
|
||||||
engines/overlay/overlay_next_grid.hh
|
engines/overlay/overlay_next_grid.hh
|
||||||
|
engines/overlay/overlay_next_image.hh
|
||||||
engines/overlay/overlay_next_instance.hh
|
engines/overlay/overlay_next_instance.hh
|
||||||
engines/overlay/overlay_next_lattice.hh
|
engines/overlay/overlay_next_lattice.hh
|
||||||
engines/overlay/overlay_next_light.hh
|
engines/overlay/overlay_next_light.hh
|
||||||
|
|||||||
@@ -12,9 +12,10 @@
|
|||||||
|
|
||||||
#include "DEG_depsgraph_query.hh"
|
#include "DEG_depsgraph_query.hh"
|
||||||
|
|
||||||
#include "BKE_movieclip.h"
|
|
||||||
#include "BKE_tracking.h"
|
#include "BKE_tracking.h"
|
||||||
|
|
||||||
|
#include "BLI_math_rotation.h"
|
||||||
|
|
||||||
#include "DNA_camera_types.h"
|
#include "DNA_camera_types.h"
|
||||||
|
|
||||||
#include "ED_view3d.hh"
|
#include "ED_view3d.hh"
|
||||||
@@ -72,6 +73,22 @@ class Cameras {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
PassSimple ps_ = {"Cameras"};
|
PassSimple ps_ = {"Cameras"};
|
||||||
|
|
||||||
|
/* Camera background images with "Depth" switched to "Back".
|
||||||
|
* Shown in camera view behind all objects. */
|
||||||
|
PassMain background_ps_ = {"background_ps_"};
|
||||||
|
/* Camera background images with "Depth" switched to "Front".
|
||||||
|
* Shown in camera view in front of all objects. */
|
||||||
|
PassMain foreground_ps_ = {"foreground_ps_"};
|
||||||
|
|
||||||
|
/* Same as `background_ps_` with "View as Render" checked. */
|
||||||
|
PassMain background_scene_ps_ = {"background_scene_ps_"};
|
||||||
|
/* Same as `foreground_ps_` with "View as Render" checked. */
|
||||||
|
PassMain foreground_scene_ps_ = {"foreground_scene_ps_"};
|
||||||
|
|
||||||
|
View view_reference_images = {"view_reference_images"};
|
||||||
|
float view_dist = 0.0f;
|
||||||
|
|
||||||
struct CallBuffers {
|
struct CallBuffers {
|
||||||
const SelectionType selection_type_;
|
const SelectionType selection_type_;
|
||||||
CameraInstanceBuf distances_buf = {selection_type_, "camera_distances_buf"};
|
CameraInstanceBuf distances_buf = {selection_type_, "camera_distances_buf"};
|
||||||
@@ -123,7 +140,9 @@ class Cameras {
|
|||||||
|
|
||||||
const float4x4 object_to_world{ob->object_to_world().ptr()};
|
const float4x4 object_to_world{ob->object_to_world().ptr()};
|
||||||
|
|
||||||
LISTBASE_FOREACH (MovieTrackingObject *, tracking_object, &tracking->objects) {
|
for (MovieTrackingObject *tracking_object :
|
||||||
|
ListBaseWrapper<MovieTrackingObject>(&tracking->objects))
|
||||||
|
{
|
||||||
float4x4 tracking_object_mat;
|
float4x4 tracking_object_mat;
|
||||||
|
|
||||||
if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
|
if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
|
||||||
@@ -140,7 +159,9 @@ class Cameras {
|
|||||||
tracking_object_mat = object_to_world * math::invert(object_mat);
|
tracking_object_mat = object_to_world * math::invert(object_mat);
|
||||||
}
|
}
|
||||||
|
|
||||||
LISTBASE_FOREACH (MovieTrackingTrack *, track, &tracking_object->tracks) {
|
for (MovieTrackingTrack *track :
|
||||||
|
ListBaseWrapper<MovieTrackingTrack>(&tracking_object->tracks))
|
||||||
|
{
|
||||||
if ((track->flag & TRACK_HAS_BUNDLE) == 0) {
|
if ((track->flag & TRACK_HAS_BUNDLE) == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -343,8 +364,10 @@ class Cameras {
|
|||||||
public:
|
public:
|
||||||
Cameras(const SelectionType selection_type) : call_buffers_{selection_type} {};
|
Cameras(const SelectionType selection_type) : call_buffers_{selection_type} {};
|
||||||
|
|
||||||
void begin_sync()
|
void begin_sync(Resources &res, State &state, View &view)
|
||||||
{
|
{
|
||||||
|
view_dist = state.view_dist_get(view.winmat());
|
||||||
|
|
||||||
call_buffers_.distances_buf.clear();
|
call_buffers_.distances_buf.clear();
|
||||||
call_buffers_.frame_buf.clear();
|
call_buffers_.frame_buf.clear();
|
||||||
call_buffers_.tria_buf.clear();
|
call_buffers_.tria_buf.clear();
|
||||||
@@ -355,9 +378,29 @@ class Cameras {
|
|||||||
call_buffers_.stereo_connect_lines.clear();
|
call_buffers_.stereo_connect_lines.clear();
|
||||||
call_buffers_.tracking_path.clear();
|
call_buffers_.tracking_path.clear();
|
||||||
Empties::begin_sync(call_buffers_.empties);
|
Empties::begin_sync(call_buffers_.empties);
|
||||||
|
|
||||||
|
/* Init image passes. */
|
||||||
|
auto init_pass = [&](PassMain &pass, DRWState draw_state) {
|
||||||
|
pass.init();
|
||||||
|
pass.state_set(draw_state | state.clipping_state);
|
||||||
|
pass.shader_set(res.shaders.image_plane.get());
|
||||||
|
res.select_bind(pass);
|
||||||
|
};
|
||||||
|
|
||||||
|
DRWState draw_state;
|
||||||
|
draw_state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_GREATER | DRW_STATE_BLEND_ALPHA_PREMUL;
|
||||||
|
init_pass(background_ps_, draw_state);
|
||||||
|
|
||||||
|
draw_state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA_UNDER_PREMUL;
|
||||||
|
init_pass(background_scene_ps_, draw_state);
|
||||||
|
|
||||||
|
draw_state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA_PREMUL;
|
||||||
|
init_pass(foreground_ps_, draw_state);
|
||||||
|
init_pass(foreground_scene_ps_, draw_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void object_sync(const ObjectRef &ob_ref, Resources &res, State &state)
|
void object_sync(
|
||||||
|
const ObjectRef &ob_ref, ShapeCache &shapes, Manager &manager, Resources &res, State &state)
|
||||||
{
|
{
|
||||||
Object *ob = ob_ref.object;
|
Object *ob = ob_ref.object;
|
||||||
const select::ID select_id = res.select_id(ob_ref);
|
const select::ID select_id = res.select_id(ob_ref);
|
||||||
@@ -499,12 +542,12 @@ class Cameras {
|
|||||||
call_buffers_);
|
call_buffers_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: /* Background images. */
|
if (is_camera_view && (cam->flag & CAM_SHOW_BG_IMAGE) &&
|
||||||
// if (look_through && (cam->flag & CAM_SHOW_BG_IMAGE) &&
|
!BLI_listbase_is_empty(&cam->bg_images))
|
||||||
// !BLI_listbase_is_empty(&cam->bg_images))
|
{
|
||||||
// {
|
sync_camera_images(
|
||||||
// OVERLAY_image_camera_cache_populate(vedata, ob);
|
ob_ref, select_id, shapes, manager, state, res, call_buffers_.selection_type_);
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void end_sync(Resources &res, ShapeCache &shapes, const State &state)
|
void end_sync(Resources &res, ShapeCache &shapes, const State &state)
|
||||||
@@ -561,6 +604,251 @@ class Cameras {
|
|||||||
GPU_framebuffer_bind(framebuffer);
|
GPU_framebuffer_bind(framebuffer);
|
||||||
manager.submit(ps_, view);
|
manager.submit(ps_, view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void draw_scene_background_images(Framebuffer &framebuffer,
|
||||||
|
const State &state,
|
||||||
|
Manager &manager,
|
||||||
|
View &view)
|
||||||
|
{
|
||||||
|
if (state.space_type != SPACE_VIEW3D) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GPU_framebuffer_bind(framebuffer);
|
||||||
|
|
||||||
|
manager.submit(background_scene_ps_, view);
|
||||||
|
manager.submit(foreground_scene_ps_, view);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_background_images(Framebuffer &framebuffer, Manager &manager, View &view)
|
||||||
|
{
|
||||||
|
GPU_framebuffer_bind(framebuffer);
|
||||||
|
manager.submit(background_ps_, view);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_in_front(Framebuffer &framebuffer, Manager &manager, View &view)
|
||||||
|
{
|
||||||
|
GPU_framebuffer_bind(framebuffer);
|
||||||
|
|
||||||
|
view_reference_images.sync(view.viewmat(),
|
||||||
|
winmat_polygon_offset(view.winmat(), view_dist, -1.0f));
|
||||||
|
|
||||||
|
manager.submit(foreground_ps_, view_reference_images);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void sync_camera_images(const ObjectRef &ob_ref,
|
||||||
|
select::ID select_id,
|
||||||
|
ShapeCache &shapes,
|
||||||
|
Manager &manager,
|
||||||
|
const State &state,
|
||||||
|
Resources &res,
|
||||||
|
const SelectionType selection_type)
|
||||||
|
{
|
||||||
|
Object *ob = ob_ref.object;
|
||||||
|
const Camera *cam = static_cast<Camera *>(ob->data);
|
||||||
|
|
||||||
|
const bool show_frame = BKE_object_empty_image_frame_is_visible_in_view3d(ob, state.rv3d);
|
||||||
|
|
||||||
|
if (!show_frame || selection_type != SelectionType::DISABLED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool stereo_eye = Images::images_stereo_eye(state.scene, state.v3d) == STEREO_LEFT_ID;
|
||||||
|
const char *viewname = (stereo_eye == STEREO_LEFT_ID) ? STEREO_RIGHT_NAME : STEREO_LEFT_NAME;
|
||||||
|
float4x4 modelmat;
|
||||||
|
BKE_camera_multiview_model_matrix(&state.scene->r, ob, viewname, modelmat.ptr());
|
||||||
|
|
||||||
|
for (const CameraBGImage *bgpic : ConstListBaseWrapper<CameraBGImage>(&cam->bg_images)) {
|
||||||
|
if (bgpic->flag & CAM_BGIMG_FLAG_DISABLED) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
float aspect = 1.0;
|
||||||
|
bool use_alpha_premult;
|
||||||
|
bool use_view_transform = false;
|
||||||
|
float4x4 mat;
|
||||||
|
|
||||||
|
/* retrieve the image we want to show, continue to next when no image could be found */
|
||||||
|
GPUTexture *tex = image_camera_background_texture_get(
|
||||||
|
bgpic, state, res, aspect, use_alpha_premult, use_view_transform);
|
||||||
|
|
||||||
|
if (tex) {
|
||||||
|
image_camera_background_matrix_get(cam, bgpic, state, aspect, mat);
|
||||||
|
|
||||||
|
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
|
||||||
|
* 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. */
|
||||||
|
const float4 color_premult_alpha{1.0f, 1.0f, 1.0f, std::min(bgpic->alpha, 0.999999f)};
|
||||||
|
|
||||||
|
PassMain &pass = is_foreground ?
|
||||||
|
(use_view_transform ? foreground_scene_ps_ : foreground_ps_) :
|
||||||
|
(use_view_transform ? background_scene_ps_ : background_ps_);
|
||||||
|
pass.bind_texture("imgTexture", tex);
|
||||||
|
pass.push_constant("imgPremultiplied", use_alpha_premult);
|
||||||
|
pass.push_constant("imgAlphaBlend", true);
|
||||||
|
pass.push_constant("isCameraBackground", true);
|
||||||
|
pass.push_constant("depthSet", true);
|
||||||
|
pass.push_constant("ucolor", color_premult_alpha);
|
||||||
|
ResourceHandle res_handle = manager.resource_handle(mat);
|
||||||
|
pass.draw(shapes.quad_solid.get(), res_handle, select_id.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void image_camera_background_matrix_get(const Camera *cam,
|
||||||
|
const CameraBGImage *bgpic,
|
||||||
|
const State &state,
|
||||||
|
const float image_aspect,
|
||||||
|
float4x4 &rmat)
|
||||||
|
{
|
||||||
|
float4x4 rotate, scale = float4x4::identity(), translate = float4x4::identity();
|
||||||
|
|
||||||
|
axis_angle_to_mat4_single(rotate.ptr(), 'Z', -bgpic->rotation);
|
||||||
|
|
||||||
|
/* Normalized Object space camera frame corners. */
|
||||||
|
float cam_corners[4][3];
|
||||||
|
BKE_camera_view_frame(state.scene, cam, cam_corners);
|
||||||
|
float cam_width = fabsf(cam_corners[0][0] - cam_corners[3][0]);
|
||||||
|
float cam_height = fabsf(cam_corners[0][1] - cam_corners[1][1]);
|
||||||
|
float cam_aspect = cam_width / cam_height;
|
||||||
|
|
||||||
|
if (bgpic->flag & CAM_BGIMG_FLAG_CAMERA_CROP) {
|
||||||
|
/* Crop. */
|
||||||
|
if (image_aspect > cam_aspect) {
|
||||||
|
scale[0][0] *= cam_height * image_aspect;
|
||||||
|
scale[1][1] *= cam_height;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
scale[0][0] *= cam_width;
|
||||||
|
scale[1][1] *= cam_width / image_aspect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (bgpic->flag & CAM_BGIMG_FLAG_CAMERA_ASPECT) {
|
||||||
|
/* Fit. */
|
||||||
|
if (image_aspect > cam_aspect) {
|
||||||
|
scale[0][0] *= cam_width;
|
||||||
|
scale[1][1] *= cam_width / image_aspect;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
scale[0][0] *= cam_height * image_aspect;
|
||||||
|
scale[1][1] *= cam_height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Stretch. */
|
||||||
|
scale[0][0] *= cam_width;
|
||||||
|
scale[1][1] *= cam_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
translate[3][0] = bgpic->offset[0];
|
||||||
|
translate[3][1] = bgpic->offset[1];
|
||||||
|
translate[3][2] = cam_corners[0][2];
|
||||||
|
if (cam->type == CAM_ORTHO) {
|
||||||
|
translate[3].xy() *= cam->ortho_scale;
|
||||||
|
}
|
||||||
|
/* These lines are for keeping 2.80 behavior and could be removed to keep 2.79 behavior. */
|
||||||
|
translate[3][0] *= min_ff(1.0f, cam_aspect);
|
||||||
|
translate[3][1] /= max_ff(1.0f, cam_aspect) * (image_aspect / cam_aspect);
|
||||||
|
/* quad is -1..1 so divide by 2. */
|
||||||
|
scale[0][0] *= 0.5f * bgpic->scale * ((bgpic->flag & CAM_BGIMG_FLAG_FLIP_X) ? -1.0 : 1.0);
|
||||||
|
scale[1][1] *= 0.5f * bgpic->scale * ((bgpic->flag & CAM_BGIMG_FLAG_FLIP_Y) ? -1.0 : 1.0);
|
||||||
|
/* Camera shift. (middle of cam_corners) */
|
||||||
|
translate[3][0] += (cam_corners[0][0] + cam_corners[2][0]) * 0.5f;
|
||||||
|
translate[3][1] += (cam_corners[0][1] + cam_corners[2][1]) * 0.5f;
|
||||||
|
|
||||||
|
rmat = translate * rotate * scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
GPUTexture *image_camera_background_texture_get(const CameraBGImage *bgpic,
|
||||||
|
const State &state,
|
||||||
|
Resources &res,
|
||||||
|
float &r_aspect,
|
||||||
|
bool &r_use_alpha_premult,
|
||||||
|
bool &r_use_view_transform)
|
||||||
|
{
|
||||||
|
::Image *image = bgpic->ima;
|
||||||
|
ImageUser *iuser = (ImageUser *)&bgpic->iuser;
|
||||||
|
MovieClip *clip = nullptr;
|
||||||
|
GPUTexture *tex = nullptr;
|
||||||
|
float aspect_x, aspect_y;
|
||||||
|
int width, height;
|
||||||
|
int ctime = int(DEG_get_ctime(state.depsgraph));
|
||||||
|
r_use_alpha_premult = false;
|
||||||
|
r_use_view_transform = false;
|
||||||
|
|
||||||
|
switch (bgpic->source) {
|
||||||
|
case CAM_BGIMG_SOURCE_IMAGE: {
|
||||||
|
if (image == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
r_use_alpha_premult = (image->alpha_mode == IMA_ALPHA_PREMUL);
|
||||||
|
r_use_view_transform = (image->flag & IMA_VIEW_AS_RENDER) != 0;
|
||||||
|
|
||||||
|
BKE_image_user_frame_calc(image, iuser, ctime);
|
||||||
|
if (image->source == IMA_SRC_SEQUENCE && !(iuser->flag & IMA_USER_FRAME_IN_RANGE)) {
|
||||||
|
/* Frame is out of range, don't show. */
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Images::stereo_setup(state.scene, state.v3d, image, iuser);
|
||||||
|
|
||||||
|
iuser->scene = (Scene *)state.scene;
|
||||||
|
tex = BKE_image_get_gpu_viewer_texture(image, iuser);
|
||||||
|
iuser->scene = nullptr;
|
||||||
|
|
||||||
|
if (tex == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
width = GPU_texture_original_width(tex);
|
||||||
|
height = GPU_texture_original_height(tex);
|
||||||
|
|
||||||
|
aspect_x = bgpic->ima->aspx;
|
||||||
|
aspect_y = bgpic->ima->aspy;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CAM_BGIMG_SOURCE_MOVIE: {
|
||||||
|
if (bgpic->flag & CAM_BGIMG_FLAG_CAMERACLIP) {
|
||||||
|
if (state.scene->camera) {
|
||||||
|
clip = BKE_object_movieclip_get((Scene *)state.scene, state.scene->camera, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
clip = bgpic->clip;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clip == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
BKE_movieclip_user_set_frame((MovieClipUser *)&bgpic->cuser, ctime);
|
||||||
|
tex = BKE_movieclip_get_gpu_texture(clip, (MovieClipUser *)&bgpic->cuser);
|
||||||
|
if (tex == nullptr) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
aspect_x = clip->aspx;
|
||||||
|
aspect_y = clip->aspy;
|
||||||
|
r_use_view_transform = true;
|
||||||
|
|
||||||
|
BKE_movieclip_get_size(clip, &bgpic->cuser, &width, &height);
|
||||||
|
|
||||||
|
/* Save for freeing. */
|
||||||
|
res.bg_movie_clips.append(clip);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* Unsupported type. */
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
r_aspect = (width * aspect_x) / (height * aspect_y);
|
||||||
|
return tex;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace blender::draw::overlay
|
} // namespace blender::draw::overlay
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "overlay_next_image.hh"
|
||||||
#include "overlay_next_private.hh"
|
#include "overlay_next_private.hh"
|
||||||
|
|
||||||
namespace blender::draw::overlay {
|
namespace blender::draw::overlay {
|
||||||
@@ -17,8 +18,25 @@ class Empties {
|
|||||||
using EmptyInstanceBuf = ShapeInstanceBuf<ExtraInstanceData>;
|
using EmptyInstanceBuf = ShapeInstanceBuf<ExtraInstanceData>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/* Images added by Image > Background. Both added in preset view (like Top, Front, ..) and in
|
||||||
|
* custom view. Object property "In Front" unchecked. */
|
||||||
|
PassSortable images_back_ps_ = {"images_back_ps_"};
|
||||||
|
/* All Empty images from cases of `images_ps_`, `images_blend_ps_`, `images_back_ps_`
|
||||||
|
* with object property "In Front" checked. */
|
||||||
|
PassSortable images_front_ps_ = {"images_front_ps_"};
|
||||||
|
|
||||||
|
/* Images added by Empty > Image and Image > Reference with unchecked image "Opacity".
|
||||||
|
* Object property "In Front" unchecked. */
|
||||||
|
PassMain images_ps_ = {"images_ps_"};
|
||||||
|
/* Images added by Empty > Image and Image > Reference with image "Opacity" checked.
|
||||||
|
* Object property "In Front" unchecked. */
|
||||||
|
PassSortable images_blend_ps_ = {"images_blend_ps_"};
|
||||||
|
|
||||||
PassSimple ps_ = {"Empties"};
|
PassSimple ps_ = {"Empties"};
|
||||||
|
|
||||||
|
View view_reference_images = {"view_reference_images"};
|
||||||
|
float view_dist = 0.0f;
|
||||||
|
|
||||||
struct CallBuffers {
|
struct CallBuffers {
|
||||||
const SelectionType selection_type_;
|
const SelectionType selection_type_;
|
||||||
EmptyInstanceBuf plain_axes_buf = {selection_type_, "plain_axes_buf"};
|
EmptyInstanceBuf plain_axes_buf = {selection_type_, "plain_axes_buf"};
|
||||||
@@ -34,8 +52,36 @@ class Empties {
|
|||||||
public:
|
public:
|
||||||
Empties(const SelectionType selection_type) : call_buffers_{selection_type} {};
|
Empties(const SelectionType selection_type) : call_buffers_{selection_type} {};
|
||||||
|
|
||||||
void begin_sync()
|
void begin_sync(Resources &res, const State &state, const View &view)
|
||||||
{
|
{
|
||||||
|
view_dist = state.view_dist_get(view.winmat());
|
||||||
|
|
||||||
|
auto init_pass = [&](PassMain &pass, DRWState draw_state) {
|
||||||
|
pass.init();
|
||||||
|
pass.state_set(draw_state | state.clipping_state);
|
||||||
|
pass.shader_set(res.shaders.image_plane.get());
|
||||||
|
res.select_bind(pass);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto init_sortable = [&](PassSortable &pass, DRWState draw_state) {
|
||||||
|
pass.init();
|
||||||
|
PassMain::Sub &sub = pass.sub("ResourceBind", -FLT_MAX);
|
||||||
|
sub.state_set(draw_state | state.clipping_state);
|
||||||
|
res.select_bind(pass, sub);
|
||||||
|
};
|
||||||
|
|
||||||
|
DRWState draw_state;
|
||||||
|
|
||||||
|
draw_state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
|
||||||
|
init_pass(images_ps_, draw_state);
|
||||||
|
|
||||||
|
draw_state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND_ALPHA_PREMUL;
|
||||||
|
init_sortable(images_back_ps_, draw_state);
|
||||||
|
init_sortable(images_blend_ps_, draw_state);
|
||||||
|
|
||||||
|
draw_state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA_PREMUL;
|
||||||
|
init_sortable(images_front_ps_, draw_state);
|
||||||
|
|
||||||
begin_sync(call_buffers_);
|
begin_sync(call_buffers_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,10 +97,18 @@ class Empties {
|
|||||||
call_buffers.image_buf.clear();
|
call_buffers.image_buf.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void object_sync(const ObjectRef &ob_ref, Resources &res, const State &state)
|
void object_sync(const ObjectRef &ob_ref,
|
||||||
|
ShapeCache &shapes,
|
||||||
|
Manager &manager,
|
||||||
|
Resources &res,
|
||||||
|
const State &state)
|
||||||
{
|
{
|
||||||
const float4 color = res.object_wire_color(ob_ref, state);
|
const float4 color = res.object_wire_color(ob_ref, state);
|
||||||
const select::ID select_id = res.select_id(ob_ref);
|
const select::ID select_id = res.select_id(ob_ref);
|
||||||
|
if (ob_ref.object->empty_drawtype == OB_EMPTY_IMAGE) {
|
||||||
|
image_sync(ob_ref, select_id, shapes, manager, res, state, call_buffers_.image_buf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
object_sync(select_id,
|
object_sync(select_id,
|
||||||
ob_ref.object->object_to_world(),
|
ob_ref.object->object_to_world(),
|
||||||
ob_ref.object->empty_drawsize,
|
ob_ref.object->empty_drawsize,
|
||||||
@@ -94,10 +148,6 @@ class Empties {
|
|||||||
case OB_ARROWS:
|
case OB_ARROWS:
|
||||||
call_buffers.arrows_buf.append(data, select_id);
|
call_buffers.arrows_buf.append(data, select_id);
|
||||||
break;
|
break;
|
||||||
case OB_EMPTY_IMAGE:
|
|
||||||
/* This only show the frame. See OVERLAY_image_empty_cache_populate() for the image. */
|
|
||||||
call_buffers.image_buf.append(data, select_id);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,6 +184,161 @@ class Empties {
|
|||||||
GPU_framebuffer_bind(framebuffer);
|
GPU_framebuffer_bind(framebuffer);
|
||||||
manager.submit(ps_, view);
|
manager.submit(ps_, view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void draw_background_images(Framebuffer &framebuffer, Manager &manager, View &view)
|
||||||
|
{
|
||||||
|
GPU_framebuffer_bind(framebuffer);
|
||||||
|
manager.submit(images_back_ps_, view);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_images(Framebuffer &framebuffer, Manager &manager, View &view)
|
||||||
|
{
|
||||||
|
GPU_framebuffer_bind(framebuffer);
|
||||||
|
|
||||||
|
view_reference_images.sync(view.viewmat(),
|
||||||
|
winmat_polygon_offset(view.winmat(), view_dist, -1.0f));
|
||||||
|
|
||||||
|
manager.submit(images_ps_, view_reference_images);
|
||||||
|
manager.submit(images_blend_ps_, view_reference_images);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_in_front_images(Framebuffer &framebuffer, Manager &manager, View &view)
|
||||||
|
{
|
||||||
|
GPU_framebuffer_bind(framebuffer);
|
||||||
|
|
||||||
|
view_reference_images.sync(view.viewmat(),
|
||||||
|
winmat_polygon_offset(view.winmat(), view_dist, -1.0f));
|
||||||
|
|
||||||
|
manager.submit(images_front_ps_, view_reference_images);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void image_sync(const ObjectRef &ob_ref,
|
||||||
|
select::ID select_id,
|
||||||
|
ShapeCache &shapes,
|
||||||
|
Manager &manager,
|
||||||
|
Resources &res,
|
||||||
|
const State &state,
|
||||||
|
EmptyInstanceBuf &empty_image_buf)
|
||||||
|
{
|
||||||
|
Object *ob = ob_ref.object;
|
||||||
|
GPUTexture *tex = nullptr;
|
||||||
|
::Image *ima = static_cast<::Image *>(ob_ref.object->data);
|
||||||
|
float4x4 mat;
|
||||||
|
|
||||||
|
const bool show_frame = BKE_object_empty_image_frame_is_visible_in_view3d(ob, state.rv3d);
|
||||||
|
const bool show_image = show_frame &&
|
||||||
|
BKE_object_empty_image_data_is_visible_in_view3d(ob, state.rv3d);
|
||||||
|
const bool use_alpha_blend = (ob_ref.object->empty_image_flag &
|
||||||
|
OB_EMPTY_IMAGE_USE_ALPHA_BLEND) != 0;
|
||||||
|
const bool use_alpha_premult = ima && (ima->alpha_mode == IMA_ALPHA_PREMUL);
|
||||||
|
|
||||||
|
if (!show_frame) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Calling 'BKE_image_get_size' may free the texture. Get the size from 'tex' instead,
|
||||||
|
* see: #59347 */
|
||||||
|
int2 size = int2(0);
|
||||||
|
if (ima != nullptr) {
|
||||||
|
ImageUser iuser = *ob->iuser;
|
||||||
|
Images::stereo_setup(state.scene, state.v3d, ima, &iuser);
|
||||||
|
tex = BKE_image_get_gpu_texture(ima, &iuser);
|
||||||
|
if (tex) {
|
||||||
|
size = int2(GPU_texture_original_width(tex), GPU_texture_original_height(tex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CLAMP_MIN(size.x, 1);
|
||||||
|
CLAMP_MIN(size.y, 1);
|
||||||
|
|
||||||
|
float2 image_aspect;
|
||||||
|
calc_image_aspect(ima, size, image_aspect);
|
||||||
|
|
||||||
|
mat = ob->object_to_world();
|
||||||
|
mat.x_axis() *= image_aspect.x * 0.5f * ob->empty_drawsize;
|
||||||
|
mat.y_axis() *= image_aspect.y * 0.5f * ob->empty_drawsize;
|
||||||
|
mat[3] += float4(mat.x_axis() * (ob->ima_ofs[0] * 2.0f + 1.0f) +
|
||||||
|
mat.y_axis() * (ob->ima_ofs[1] * 2.0f + 1.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (show_frame) {
|
||||||
|
const float4 color = res.object_wire_color(ob_ref, state);
|
||||||
|
empty_image_buf.append(ExtraInstanceData(mat, color, 1.0f), select_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (show_image && tex && ((ob->color[3] > 0.0f) || !use_alpha_blend)) {
|
||||||
|
/* Use the actual depth if we are doing depth tests to determine the distance to the
|
||||||
|
* object. */
|
||||||
|
char depth_mode = DRW_state_is_depth() ? char(OB_EMPTY_IMAGE_DEPTH_DEFAULT) :
|
||||||
|
ob->empty_image_depth;
|
||||||
|
PassMain::Sub &pass = create_subpass(state, *ob, use_alpha_blend, mat, res);
|
||||||
|
pass.bind_texture("imgTexture", tex);
|
||||||
|
pass.push_constant("imgPremultiplied", use_alpha_premult);
|
||||||
|
pass.push_constant("imgAlphaBlend", use_alpha_blend);
|
||||||
|
pass.push_constant("isCameraBackground", false);
|
||||||
|
pass.push_constant("depthSet", depth_mode != OB_EMPTY_IMAGE_DEPTH_DEFAULT);
|
||||||
|
pass.push_constant("ucolor", float4(ob->color));
|
||||||
|
ResourceHandle res_handle = manager.resource_handle(mat);
|
||||||
|
pass.draw(shapes.quad_solid.get(), res_handle, select_id.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PassMain::Sub &create_subpass(const State &state,
|
||||||
|
const Object &ob,
|
||||||
|
const bool use_alpha_blend,
|
||||||
|
const float4x4 &mat,
|
||||||
|
const Resources &res)
|
||||||
|
{
|
||||||
|
const bool in_front = state.use_in_front && (ob.dtx & OB_DRAW_IN_FRONT);
|
||||||
|
if (in_front) {
|
||||||
|
return create_subpass(state, mat, res, images_front_ps_);
|
||||||
|
}
|
||||||
|
const char depth_mode = DRW_state_is_depth() ? char(OB_EMPTY_IMAGE_DEPTH_DEFAULT) :
|
||||||
|
ob.empty_image_depth;
|
||||||
|
switch (depth_mode) {
|
||||||
|
case OB_EMPTY_IMAGE_DEPTH_BACK:
|
||||||
|
return create_subpass(state, mat, res, images_back_ps_);
|
||||||
|
case OB_EMPTY_IMAGE_DEPTH_FRONT:
|
||||||
|
return create_subpass(state, mat, res, images_front_ps_);
|
||||||
|
case OB_EMPTY_IMAGE_DEPTH_DEFAULT:
|
||||||
|
default:
|
||||||
|
return use_alpha_blend ? create_subpass(state, mat, res, images_blend_ps_) : images_ps_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static PassMain::Sub &create_subpass(const State &state,
|
||||||
|
const float4x4 &mat,
|
||||||
|
const Resources &res,
|
||||||
|
PassSortable &parent)
|
||||||
|
{
|
||||||
|
const float3 tmp = state.camera_position - mat.location();
|
||||||
|
const float z = -math::dot(state.camera_forward, tmp);
|
||||||
|
PassMain::Sub &sub = parent.sub("Sub", z);
|
||||||
|
sub.shader_set(res.shaders.image_plane.get());
|
||||||
|
return sub;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void calc_image_aspect(::Image *ima, const int2 &size, float2 &r_image_aspect)
|
||||||
|
{
|
||||||
|
/* if no image, make it a 1x1 empty square, honor scale & offset */
|
||||||
|
const float2 ima_dim = ima ? float2(size.x, size.y) : float2(1.0f);
|
||||||
|
|
||||||
|
/* Get the image aspect even if the buffer is invalid */
|
||||||
|
float2 sca(1.0f);
|
||||||
|
if (ima) {
|
||||||
|
if (ima->aspx > ima->aspy) {
|
||||||
|
sca.y = ima->aspy / ima->aspx;
|
||||||
|
}
|
||||||
|
else if (ima->aspx < ima->aspy) {
|
||||||
|
sca.x = ima->aspx / ima->aspy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const float2 scale_inv(ima_dim.x * sca.x, ima_dim.y * sca.y);
|
||||||
|
r_image_aspect = (scale_inv.x > scale_inv.y) ? float2(1.0f, scale_inv.y / scale_inv.x) :
|
||||||
|
float2(scale_inv.x / scale_inv.y, 1.0f);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace blender::draw::overlay
|
} // namespace blender::draw::overlay
|
||||||
|
|||||||
44
source/blender/draw/engines/overlay/overlay_next_image.hh
Normal file
44
source/blender/draw/engines/overlay/overlay_next_image.hh
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup overlay
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "overlay_next_private.hh"
|
||||||
|
|
||||||
|
namespace blender::draw::overlay {
|
||||||
|
|
||||||
|
class Images {
|
||||||
|
|
||||||
|
public:
|
||||||
|
static eStereoViews images_stereo_eye(const Scene *scene, const View3D *v3d)
|
||||||
|
{
|
||||||
|
if ((scene->r.scemode & R_MULTIVIEW) == 0) {
|
||||||
|
return STEREO_LEFT_ID;
|
||||||
|
}
|
||||||
|
if (v3d->stereo3d_camera != STEREO_3D_ID) {
|
||||||
|
/* show only left or right camera */
|
||||||
|
return eStereoViews(v3d->stereo3d_camera);
|
||||||
|
}
|
||||||
|
|
||||||
|
return eStereoViews(v3d->multiview_eye);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stereo_setup(const Scene *scene, const View3D *v3d, ::Image *ima, ImageUser *iuser)
|
||||||
|
{
|
||||||
|
if (BKE_image_is_stereo(ima)) {
|
||||||
|
iuser->flag |= IMA_SHOW_STEREO;
|
||||||
|
iuser->multiview_eye = images_stereo_eye(scene, v3d);
|
||||||
|
BKE_image_multiview_index(ima, iuser);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
iuser->flag &= ~IMA_SHOW_STEREO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace blender::draw::overlay
|
||||||
@@ -84,6 +84,9 @@ void Instance::begin_sync()
|
|||||||
const DRWView *view_legacy = DRW_view_default_get();
|
const DRWView *view_legacy = DRW_view_default_get();
|
||||||
View view("OverlayView", view_legacy);
|
View view("OverlayView", view_legacy);
|
||||||
|
|
||||||
|
state.camera_position = view.viewinv().location();
|
||||||
|
state.camera_forward = view.viewinv().z_axis();
|
||||||
|
|
||||||
resources.begin_sync();
|
resources.begin_sync();
|
||||||
|
|
||||||
background.begin_sync(resources, state);
|
background.begin_sync(resources, state);
|
||||||
@@ -91,9 +94,9 @@ void Instance::begin_sync()
|
|||||||
|
|
||||||
auto begin_sync_layer = [&](OverlayLayer &layer) {
|
auto begin_sync_layer = [&](OverlayLayer &layer) {
|
||||||
layer.bounds.begin_sync();
|
layer.bounds.begin_sync();
|
||||||
layer.cameras.begin_sync();
|
layer.cameras.begin_sync(resources, state, view);
|
||||||
layer.curves.begin_sync(resources, state, view);
|
layer.curves.begin_sync(resources, state, view);
|
||||||
layer.empties.begin_sync();
|
layer.empties.begin_sync(resources, state, view);
|
||||||
layer.facing.begin_sync(resources, state);
|
layer.facing.begin_sync(resources, state);
|
||||||
layer.force_fields.begin_sync();
|
layer.force_fields.begin_sync();
|
||||||
layer.fluids.begin_sync(resources, state);
|
layer.fluids.begin_sync(resources, state);
|
||||||
@@ -166,10 +169,10 @@ void Instance::object_sync(ObjectRef &ob_ref, Manager &manager)
|
|||||||
if (!state.hide_overlays) {
|
if (!state.hide_overlays) {
|
||||||
switch (ob_ref.object->type) {
|
switch (ob_ref.object->type) {
|
||||||
case OB_EMPTY:
|
case OB_EMPTY:
|
||||||
layer.empties.object_sync(ob_ref, resources, state);
|
layer.empties.object_sync(ob_ref, shapes, manager, resources, state);
|
||||||
break;
|
break;
|
||||||
case OB_CAMERA:
|
case OB_CAMERA:
|
||||||
layer.cameras.object_sync(ob_ref, resources, state);
|
layer.cameras.object_sync(ob_ref, shapes, manager, resources, state);
|
||||||
break;
|
break;
|
||||||
case OB_ARMATURE:
|
case OB_ARMATURE:
|
||||||
break;
|
break;
|
||||||
@@ -323,6 +326,17 @@ void Instance::draw(Manager &manager)
|
|||||||
GPU_framebuffer_clear_color(resources.overlay_line_fb, clear_color);
|
GPU_framebuffer_clear_color(resources.overlay_line_fb, clear_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
regular.cameras.draw_scene_background_images(
|
||||||
|
resources.overlay_color_only_fb, state, manager, view);
|
||||||
|
infront.cameras.draw_scene_background_images(
|
||||||
|
resources.overlay_color_only_fb, state, manager, view);
|
||||||
|
|
||||||
|
regular.empties.draw_background_images(resources.overlay_color_only_fb, manager, view);
|
||||||
|
regular.cameras.draw_background_images(resources.overlay_color_only_fb, manager, view);
|
||||||
|
infront.cameras.draw_background_images(resources.overlay_color_only_fb, manager, view);
|
||||||
|
|
||||||
|
regular.empties.draw_images(resources.overlay_fb, manager, view);
|
||||||
|
|
||||||
regular.prepass.draw(resources.overlay_line_fb, manager, view);
|
regular.prepass.draw(resources.overlay_line_fb, manager, view);
|
||||||
infront.prepass.draw(resources.overlay_line_in_front_fb, manager, view);
|
infront.prepass.draw(resources.overlay_line_in_front_fb, manager, view);
|
||||||
|
|
||||||
@@ -367,6 +381,9 @@ void Instance::draw(Manager &manager)
|
|||||||
|
|
||||||
/* TODO(: Breaks selection on M1 Max. */
|
/* TODO(: Breaks selection on M1 Max. */
|
||||||
// infront.lattices.draw(resources.overlay_line_in_front_fb, manager, view);
|
// infront.lattices.draw(resources.overlay_line_in_front_fb, manager, view);
|
||||||
|
// infront.empties.draw_in_front_images(resources.overlay_in_front_fb, manager, view);
|
||||||
|
// regular.cameras.draw_in_front(resources.overlay_in_front_fb, manager, view);
|
||||||
|
// infront.cameras.draw_in_front(resources.overlay_in_front_fb, manager, view);
|
||||||
|
|
||||||
/* Drawn onto the output framebuffer. */
|
/* Drawn onto the output framebuffer. */
|
||||||
background.draw(manager);
|
background.draw(manager);
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ class Instance {
|
|||||||
|
|
||||||
struct OverlayLayer {
|
struct OverlayLayer {
|
||||||
const SelectionType selection_type_;
|
const SelectionType selection_type_;
|
||||||
|
|
||||||
Bounds bounds = {selection_type_};
|
Bounds bounds = {selection_type_};
|
||||||
Cameras cameras = {selection_type_};
|
Cameras cameras = {selection_type_};
|
||||||
Curves curves;
|
Curves curves;
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "BKE_movieclip.h"
|
||||||
|
|
||||||
#include "BLI_function_ref.hh"
|
#include "BLI_function_ref.hh"
|
||||||
|
|
||||||
#include "GPU_matrix.hh"
|
#include "GPU_matrix.hh"
|
||||||
@@ -57,6 +59,8 @@ struct State {
|
|||||||
short v3d_flag; /* TODO: move to #View3DOverlay. */
|
short v3d_flag; /* TODO: move to #View3DOverlay. */
|
||||||
short v3d_gridflag; /* TODO: move to #View3DOverlay. */
|
short v3d_gridflag; /* TODO: move to #View3DOverlay. */
|
||||||
int cfra;
|
int cfra;
|
||||||
|
float3 camera_position;
|
||||||
|
float3 camera_forward;
|
||||||
DRWState clipping_state;
|
DRWState clipping_state;
|
||||||
|
|
||||||
float view_dist_get(const float4x4 &winmat) const
|
float view_dist_get(const float4x4 &winmat) const
|
||||||
@@ -212,6 +216,7 @@ class ShaderModule {
|
|||||||
ShaderPtr fluid_velocity_streamline;
|
ShaderPtr fluid_velocity_streamline;
|
||||||
ShaderPtr fluid_velocity_mac;
|
ShaderPtr fluid_velocity_mac;
|
||||||
ShaderPtr fluid_velocity_needle;
|
ShaderPtr fluid_velocity_needle;
|
||||||
|
ShaderPtr image_plane;
|
||||||
ShaderPtr lattice_points;
|
ShaderPtr lattice_points;
|
||||||
ShaderPtr lattice_wire;
|
ShaderPtr lattice_wire;
|
||||||
ShaderPtr particle_dot;
|
ShaderPtr particle_dot;
|
||||||
@@ -299,9 +304,22 @@ struct Resources : public select::SelectMap {
|
|||||||
*/
|
*/
|
||||||
TextureRef depth_target_tx;
|
TextureRef depth_target_tx;
|
||||||
|
|
||||||
|
Vector<MovieClip *> bg_movie_clips;
|
||||||
|
|
||||||
Resources(const SelectionType selection_type_, ShaderModule &shader_module)
|
Resources(const SelectionType selection_type_, ShaderModule &shader_module)
|
||||||
: select::SelectMap(selection_type_), shaders(shader_module){};
|
: select::SelectMap(selection_type_), shaders(shader_module){};
|
||||||
|
|
||||||
|
~Resources()
|
||||||
|
{
|
||||||
|
free_movieclips_textures();
|
||||||
|
}
|
||||||
|
|
||||||
|
void begin_sync()
|
||||||
|
{
|
||||||
|
SelectMap::begin_sync();
|
||||||
|
free_movieclips_textures();
|
||||||
|
}
|
||||||
|
|
||||||
ThemeColorID object_wire_theme_id(const ObjectRef &ob_ref, const State &state) const
|
ThemeColorID object_wire_theme_id(const ObjectRef &ob_ref, const State &state) const
|
||||||
{
|
{
|
||||||
const bool is_edit = (state.object_mode & OB_MODE_EDIT) &&
|
const bool is_edit = (state.object_mode & OB_MODE_EDIT) &&
|
||||||
@@ -386,6 +404,14 @@ struct Resources : public select::SelectMap {
|
|||||||
ThemeColorID theme_id = object_wire_theme_id(ob_ref, state);
|
ThemeColorID theme_id = object_wire_theme_id(ob_ref, state);
|
||||||
return background_blend_color(theme_id);
|
return background_blend_color(theme_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void free_movieclips_textures()
|
||||||
|
{
|
||||||
|
/* Free Movie clip textures after rendering */
|
||||||
|
for (MovieClip *clip : bg_movie_clips) {
|
||||||
|
BKE_movieclip_free_gputexture(clip);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -331,6 +331,11 @@ ShaderModule::ShaderModule(const SelectionType selection_type, const bool clippi
|
|||||||
info.vertex_inputs_.pop_last();
|
info.vertex_inputs_.pop_last();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
image_plane = selectable_shader("overlay_image", [](gpu::shader::ShaderCreateInfo &info) {
|
||||||
|
info.additional_infos_.clear();
|
||||||
|
info.additional_info("draw_view", "draw_modelmat_new", "draw_resource_handle_new");
|
||||||
|
});
|
||||||
|
|
||||||
particle_dot = selectable_shader("overlay_particle_dot",
|
particle_dot = selectable_shader("overlay_particle_dot",
|
||||||
[](gpu::shader::ShaderCreateInfo &info) {
|
[](gpu::shader::ShaderCreateInfo &info) {
|
||||||
info.additional_infos_.clear();
|
info.additional_infos_.clear();
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
|
||||||
#pragma BLENDER_REQUIRE(common_colormanagement_lib.glsl)
|
#pragma BLENDER_REQUIRE(common_colormanagement_lib.glsl)
|
||||||
|
#pragma BLENDER_REQUIRE(select_lib.glsl)
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
@@ -25,4 +26,6 @@ void main()
|
|||||||
|
|
||||||
/* Pre-multiplied blending. */
|
/* Pre-multiplied blending. */
|
||||||
fragColor.rgb *= fragColor.a;
|
fragColor.rgb *= fragColor.a;
|
||||||
|
|
||||||
|
select_id_output(select_id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,11 @@
|
|||||||
|
|
||||||
#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
|
#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
|
||||||
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
|
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
|
||||||
|
#pragma BLENDER_REQUIRE(select_lib.glsl)
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
select_id_set(drw_CustomID);
|
||||||
vec3 world_pos = point_object_to_world(pos);
|
vec3 world_pos = point_object_to_world(pos);
|
||||||
if (isCameraBackground) {
|
if (isCameraBackground) {
|
||||||
/* Model matrix converts to view position to avoid jittering (see #91398). */
|
/* Model matrix converts to view position to avoid jittering (see #91398). */
|
||||||
|
|||||||
@@ -191,6 +191,25 @@ struct SelectMap {
|
|||||||
pass.bind_ssbo(SELECT_ID_OUT, &select_output_buf);
|
pass.bind_ssbo(SELECT_ID_OUT, &select_output_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: Deduplicate. */
|
||||||
|
/** IMPORTANT: Changes the draw state. Need to be called after the pass's own state_set. */
|
||||||
|
void select_bind(PassMain &pass, PassMain::Sub &sub)
|
||||||
|
{
|
||||||
|
if (selection_type == SelectionType::DISABLED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pass.use_custom_ids = true;
|
||||||
|
if (disable_depth_test) {
|
||||||
|
/* TODO: clipping state. */
|
||||||
|
sub.state_set(DRW_STATE_WRITE_COLOR);
|
||||||
|
}
|
||||||
|
sub.bind_ubo(SELECT_DATA, &info_buf);
|
||||||
|
/* IMPORTANT: This binds a dummy buffer `in_select_buf` but it is not supposed to be used. */
|
||||||
|
sub.bind_ssbo(SELECT_ID_IN, &dummy_select_buf);
|
||||||
|
sub.bind_ssbo(SELECT_ID_OUT, &select_output_buf);
|
||||||
|
}
|
||||||
|
|
||||||
void end_sync()
|
void end_sync()
|
||||||
{
|
{
|
||||||
if (selection_type == SelectionType::DISABLED) {
|
if (selection_type == SelectionType::DISABLED) {
|
||||||
|
|||||||
Reference in New Issue
Block a user