Overlay-Next: Initial implementation #107045
@ -2392,6 +2392,7 @@ class USERPREF_PT_experimental_prototypes(ExperimentalPanel, Panel):
|
||||
({"property": "use_full_frame_compositor"}, ("blender/blender/issues/88150", "#88150")),
|
||||
({"property": "enable_eevee_next"}, ("blender/blender/issues/93220", "#93220")),
|
||||
({"property": "enable_workbench_next"}, ("blender/blender/issues/101619", "#101619")),
|
||||
({"property": "enable_overlay_next"}, ("blender/blender/issues/102179", "#102179")),
|
||||
),
|
||||
)
|
||||
|
||||
|
@ -191,6 +191,7 @@ set(SRC
|
||||
engines/gpencil/gpencil_shader_fx.c
|
||||
engines/select/select_draw_utils.c
|
||||
engines/select/select_engine.c
|
||||
engines/select/select_instance.cc
|
||||
engines/overlay/overlay_antialiasing.cc
|
||||
engines/overlay/overlay_armature.cc
|
||||
engines/overlay/overlay_background.cc
|
||||
@ -206,6 +207,7 @@ set(SRC
|
||||
engines/overlay/overlay_gpencil.cc
|
||||
engines/overlay/overlay_grid.cc
|
||||
engines/overlay/overlay_image.cc
|
||||
engines/overlay/overlay_instance.cc
|
||||
engines/overlay/overlay_lattice.cc
|
||||
engines/overlay/overlay_metaball.cc
|
||||
engines/overlay/overlay_mode_transfer.cc
|
||||
@ -311,6 +313,7 @@ set(SRC
|
||||
engines/select/select_engine.h
|
||||
engines/select/select_private.h
|
||||
engines/overlay/overlay_engine.h
|
||||
engines/overlay/overlay_instance.hh
|
||||
engines/overlay/overlay_private.hh
|
||||
)
|
||||
|
||||
@ -598,6 +601,9 @@ set(GLSL_SRC
|
||||
|
||||
engines/select/shaders/select_id_vert.glsl
|
||||
engines/select/shaders/select_id_frag.glsl
|
||||
engines/select/shaders/select_lib.glsl
|
||||
|
||||
engines/select/select_shader_shared.hh
|
||||
|
||||
engines/basic/shaders/basic_conservative_depth_geom.glsl
|
||||
engines/basic/shaders/basic_depth_vert.glsl
|
||||
|
@ -618,9 +618,6 @@ static void drw_shgroup_bone_envelope(ArmatureDrawContext *ctx,
|
||||
|
||||
/* Custom (geometry) */
|
||||
|
||||
extern "C" void drw_batch_cache_validate(Object *custom);
|
||||
extern "C" void drw_batch_cache_generate_requested_delayed(Object *custom);
|
||||
|
||||
BLI_INLINE DRWCallBuffer *custom_bone_instance_shgroup(ArmatureDrawContext *ctx,
|
||||
DRWShadingGroup *grp,
|
||||
GPUBatch *custom_geom)
|
||||
|
104
source/blender/draw/engines/overlay/overlay_background.hh
Normal file
104
source/blender/draw/engines/overlay/overlay_background.hh
Normal file
@ -0,0 +1,104 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup overlay
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DEG_depsgraph_query.h"
|
||||
#include "DNA_camera_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
#include "ED_view3d.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
#include "draw_cache.h"
|
||||
#include "draw_pass.hh"
|
||||
#include "overlay_private.hh"
|
||||
#include "overlay_shader_shared.h"
|
||||
|
||||
namespace blender::draw::overlay {
|
||||
|
||||
template<typename SelectEngineT> class Background {
|
||||
using ResourcesT = Resources<SelectEngineT>;
|
||||
|
||||
private:
|
||||
PassSimple bg_ps_ = {"Background"};
|
||||
|
||||
public:
|
||||
void begin_sync(ResourcesT &res, const State &state)
|
||||
{
|
||||
DRWState pass_state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_BACKGROUND;
|
||||
float4 color_override(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
int background_type;
|
||||
|
||||
if (DRW_state_is_opengl_render() && !DRW_state_draw_background()) {
|
||||
background_type = BG_SOLID;
|
||||
color_override[3] = 1.0f;
|
||||
}
|
||||
/*
|
||||
else if (pd->space_type == SPACE_IMAGE) {
|
||||
background_type = BG_SOLID_CHECKER;
|
||||
}
|
||||
else if (pd->space_type == SPACE_NODE) {
|
||||
background_type = BG_MASK;
|
||||
pass_state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_MUL;
|
||||
}
|
||||
*/
|
||||
else if (!DRW_state_draw_background()) {
|
||||
background_type = BG_CHECKER;
|
||||
}
|
||||
else if (state.v3d->shading.background_type == V3D_SHADING_BACKGROUND_WORLD &&
|
||||
state.scene->world) {
|
||||
background_type = BG_SOLID;
|
||||
/* TODO(fclem): this is a scene referred linear color. we should convert
|
||||
* it to display linear here. */
|
||||
color_override = float4(UNPACK3(&state.scene->world->horr), 1.0f);
|
||||
}
|
||||
else if (state.v3d->shading.background_type == V3D_SHADING_BACKGROUND_VIEWPORT &&
|
||||
state.v3d->shading.type <= OB_SOLID) {
|
||||
background_type = BG_SOLID;
|
||||
color_override = float4(UNPACK3(state.v3d->shading.background_color), 1.0f);
|
||||
}
|
||||
else {
|
||||
switch (UI_GetThemeValue(TH_BACKGROUND_TYPE)) {
|
||||
case TH_BACKGROUND_GRADIENT_LINEAR:
|
||||
background_type = BG_GRADIENT;
|
||||
break;
|
||||
case TH_BACKGROUND_GRADIENT_RADIAL:
|
||||
background_type = BG_RADIAL;
|
||||
break;
|
||||
default:
|
||||
case TH_BACKGROUND_SINGLE_COLOR:
|
||||
background_type = BG_SOLID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bg_ps_.init();
|
||||
bg_ps_.state_set(pass_state);
|
||||
bg_ps_.shader_set(res.shaders.background_fill);
|
||||
bg_ps_.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
bg_ps_.bind_texture("colorBuffer", &res.color_render_tx);
|
||||
bg_ps_.bind_texture("depthBuffer", &res.depth_tx);
|
||||
bg_ps_.push_constant("colorOverride", color_override);
|
||||
bg_ps_.push_constant("bgType", background_type);
|
||||
bg_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);
|
||||
|
||||
if (state.clipping_state != 0 && state.rv3d != nullptr && state.rv3d->clipbb != nullptr) {
|
||||
bg_ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA | DRW_STATE_CULL_BACK);
|
||||
bg_ps_.shader_set(res.shaders.background_clip_bound);
|
||||
bg_ps_.push_constant("ucolor", res.theme_settings.color_clipping_border);
|
||||
bg_ps_.push_constant("boundbox", &state.rv3d->clipbb->vec[0][0], 8);
|
||||
bg_ps_.draw(DRW_cache_cube_get());
|
||||
}
|
||||
}
|
||||
|
||||
void draw(ResourcesT &res, Manager &manager)
|
||||
{
|
||||
GPU_framebuffer_bind(res.overlay_color_only_fb);
|
||||
manager.submit(bg_ps_);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace blender::draw::overlay
|
128
source/blender/draw/engines/overlay/overlay_empty.hh
Normal file
128
source/blender/draw/engines/overlay/overlay_empty.hh
Normal file
@ -0,0 +1,128 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup overlay
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "draw_pass.hh"
|
||||
#include "draw_shader_shared.h"
|
||||
#include "overlay_private.hh"
|
||||
#include "overlay_shape.hh"
|
||||
|
||||
namespace blender::draw::overlay {
|
||||
|
||||
template<typename SelectEngineT> class Empties {
|
||||
using SelectID = typename SelectEngineT::ID;
|
||||
using ResourcesT = Resources<SelectEngineT>;
|
||||
using EmptyInstanceBuf = ShapeInstanceBuf<SelectEngineT, ExtraInstanceData>;
|
||||
|
||||
private:
|
||||
PassSimple empty_ps_ = {"Empties"};
|
||||
PassSimple empty_in_front_ps_ = {"Empties_In_front"};
|
||||
|
||||
struct CallBuffers {
|
||||
EmptyInstanceBuf plain_axes_buf = {"plain_axes_buf"};
|
||||
EmptyInstanceBuf single_arrow_buf = {"single_arrow_buf"};
|
||||
EmptyInstanceBuf cube_buf = {"cube_buf"};
|
||||
EmptyInstanceBuf circle_buf = {"circle_buf"};
|
||||
EmptyInstanceBuf sphere_buf = {"sphere_buf"};
|
||||
EmptyInstanceBuf cone_buf = {"cone_buf"};
|
||||
EmptyInstanceBuf arrows_buf = {"arrows_buf"};
|
||||
EmptyInstanceBuf image_buf = {"image_buf"};
|
||||
} call_buffers_[2];
|
||||
|
||||
public:
|
||||
void begin_sync()
|
||||
{
|
||||
for (int i = 0; i < 2; i++) {
|
||||
call_buffers_[i].plain_axes_buf.clear();
|
||||
call_buffers_[i].single_arrow_buf.clear();
|
||||
call_buffers_[i].cube_buf.clear();
|
||||
call_buffers_[i].circle_buf.clear();
|
||||
call_buffers_[i].sphere_buf.clear();
|
||||
call_buffers_[i].cone_buf.clear();
|
||||
call_buffers_[i].arrows_buf.clear();
|
||||
call_buffers_[i].image_buf.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void object_sync(const ObjectRef &ob_ref, ResourcesT &res, const State &state)
|
||||
{
|
||||
CallBuffers &call_bufs = call_buffers_[int((ob_ref.object->dtx & OB_DRAW_IN_FRONT) != 0)];
|
||||
|
||||
float4 color = res.object_wire_color(ob_ref, state);
|
||||
ExtraInstanceData data(
|
||||
float4x4(ob_ref.object->object_to_world), color, ob_ref.object->empty_drawsize);
|
||||
|
||||
const SelectID select_id = res.select_id(ob_ref);
|
||||
|
||||
switch (ob_ref.object->empty_drawtype) {
|
||||
case OB_PLAINAXES:
|
||||
call_bufs.plain_axes_buf.append(data, select_id);
|
||||
break;
|
||||
case OB_SINGLE_ARROW:
|
||||
call_bufs.single_arrow_buf.append(data, select_id);
|
||||
break;
|
||||
case OB_CUBE:
|
||||
call_bufs.cube_buf.append(data, select_id);
|
||||
break;
|
||||
case OB_CIRCLE:
|
||||
call_bufs.circle_buf.append(data, select_id);
|
||||
break;
|
||||
case OB_EMPTY_SPHERE:
|
||||
call_bufs.sphere_buf.append(data, select_id);
|
||||
break;
|
||||
case OB_EMPTY_CONE:
|
||||
call_bufs.cone_buf.append(data, select_id);
|
||||
break;
|
||||
case OB_ARROWS:
|
||||
call_bufs.arrows_buf.append(data, select_id);
|
||||
break;
|
||||
case OB_EMPTY_IMAGE:
|
||||
/* This only show the frame. See OVERLAY_image_empty_cache_populate() for the image. */
|
||||
call_bufs.image_buf.append(data, select_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void end_sync(ResourcesT &res, ShapeCache &shapes, const State &state)
|
||||
{
|
||||
auto init_pass = [&](PassSimple &pass, CallBuffers &call_bufs) {
|
||||
pass.init();
|
||||
pass.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
|
||||
state.clipping_state);
|
||||
pass.shader_set(res.shaders.extra_shape);
|
||||
pass.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
res.select_bind(pass);
|
||||
|
||||
call_bufs.plain_axes_buf.end_sync(pass, shapes.plain_axes);
|
||||
call_bufs.single_arrow_buf.end_sync(pass, shapes.single_arrow);
|
||||
call_bufs.cube_buf.end_sync(pass, shapes.cube);
|
||||
call_bufs.circle_buf.end_sync(pass, shapes.circle);
|
||||
call_bufs.sphere_buf.end_sync(pass, shapes.empty_sphere);
|
||||
call_bufs.cone_buf.end_sync(pass, shapes.empty_cone);
|
||||
call_bufs.arrows_buf.end_sync(pass, shapes.arrows);
|
||||
call_bufs.image_buf.end_sync(pass, shapes.quad_wire);
|
||||
};
|
||||
init_pass(empty_ps_, call_buffers_[0]);
|
||||
init_pass(empty_in_front_ps_, call_buffers_[1]);
|
||||
}
|
||||
|
||||
void draw(ResourcesT &res, Manager &manager, View &view)
|
||||
{
|
||||
GPU_framebuffer_bind(res.overlay_line_fb);
|
||||
manager.submit(empty_ps_, view);
|
||||
}
|
||||
|
||||
void draw_in_front(ResourcesT &res, Manager &manager, View &view)
|
||||
{
|
||||
GPU_framebuffer_bind(res.overlay_line_in_front_fb);
|
||||
manager.submit(empty_in_front_ps_, view);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace blender::draw::overlay
|
@ -20,11 +20,20 @@
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_paint.h"
|
||||
|
||||
#include "GPU_capabilities.h"
|
||||
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "draw_manager.hh"
|
||||
#include "overlay_instance.hh"
|
||||
|
||||
#include "overlay_engine.h"
|
||||
#include "overlay_private.hh"
|
||||
|
||||
using namespace blender::draw;
|
||||
|
||||
using Instance = blender::draw::overlay::Instance<>;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Engine Callbacks
|
||||
* \{ */
|
||||
@ -46,8 +55,7 @@ static void OVERLAY_engine_init(void *vedata)
|
||||
|
||||
/* Allocate instance. */
|
||||
if (data->instance == nullptr) {
|
||||
data->instance = static_cast<OVERLAY_Instance *>(
|
||||
MEM_callocN(sizeof(*data->instance), __func__));
|
||||
data->instance = new Instance();
|
||||
}
|
||||
|
||||
OVERLAY_PrivateData *pd = stl->pd;
|
||||
@ -729,13 +737,75 @@ static void OVERLAY_draw_scene(void *vedata)
|
||||
static void OVERLAY_engine_free()
|
||||
{
|
||||
OVERLAY_shader_free();
|
||||
overlay::shader_module_free();
|
||||
}
|
||||
|
||||
static void OVERLAY_instance_free(void *instance_)
|
||||
{
|
||||
OVERLAY_Instance *instance = (OVERLAY_Instance *)instance_;
|
||||
DRW_UBO_FREE_SAFE(instance->grid_ubo);
|
||||
MEM_freeN(instance);
|
||||
auto *instance = (Instance *)instance_;
|
||||
if (instance != nullptr) {
|
||||
delete instance;
|
||||
}
|
||||
}
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Engine Instance
|
||||
* \{ */
|
||||
|
||||
static void OVERLAY_next_engine_init(void *vedata)
|
||||
{
|
||||
if (!GPU_shader_storage_buffer_objects_support()) {
|
||||
return;
|
||||
}
|
||||
|
||||
OVERLAY_Data *ved = reinterpret_cast<OVERLAY_Data *>(vedata);
|
||||
|
||||
if (ved->instance == nullptr) {
|
||||
ved->instance = new Instance();
|
||||
}
|
||||
|
||||
reinterpret_cast<Instance *>(ved->instance)->init();
|
||||
}
|
||||
|
||||
static void OVERLAY_next_cache_init(void *vedata)
|
||||
{
|
||||
if (!GPU_shader_storage_buffer_objects_support()) {
|
||||
return;
|
||||
}
|
||||
reinterpret_cast<Instance *>(reinterpret_cast<OVERLAY_Data *>(vedata)->instance)->begin_sync();
|
||||
}
|
||||
|
||||
static void OVERLAY_next_cache_populate(void *vedata, Object *object)
|
||||
{
|
||||
if (!GPU_shader_storage_buffer_objects_support()) {
|
||||
return;
|
||||
}
|
||||
ObjectRef ref;
|
||||
ref.object = object;
|
||||
ref.dupli_object = DRW_object_get_dupli(object);
|
||||
ref.dupli_parent = DRW_object_get_dupli_parent(object);
|
||||
|
||||
reinterpret_cast<Instance *>(reinterpret_cast<OVERLAY_Data *>(vedata)->instance)
|
||||
->object_sync(ref, *DRW_manager_get());
|
||||
}
|
||||
|
||||
static void OVERLAY_next_cache_finish(void *vedata)
|
||||
{
|
||||
if (!GPU_shader_storage_buffer_objects_support()) {
|
||||
return;
|
||||
}
|
||||
reinterpret_cast<Instance *>(reinterpret_cast<OVERLAY_Data *>(vedata)->instance)->end_sync();
|
||||
}
|
||||
|
||||
static void OVERLAY_next_draw_scene(void *vedata)
|
||||
{
|
||||
if (!GPU_shader_storage_buffer_objects_support()) {
|
||||
return;
|
||||
}
|
||||
|
||||
reinterpret_cast<Instance *>(reinterpret_cast<OVERLAY_Data *>(vedata)->instance)
|
||||
->draw(*DRW_manager_get());
|
||||
}
|
||||
|
||||
/** \} */
|
||||
@ -764,6 +834,24 @@ DrawEngineType draw_engine_overlay_type = {
|
||||
nullptr,
|
||||
};
|
||||
|
||||
DrawEngineType draw_engine_overlay_next_type = {
|
||||
nullptr,
|
||||
nullptr,
|
||||
N_("Overlay"),
|
||||
&overlay_data_size,
|
||||
&OVERLAY_next_engine_init,
|
||||
nullptr,
|
||||
&OVERLAY_instance_free,
|
||||
&OVERLAY_next_cache_init,
|
||||
&OVERLAY_next_cache_populate,
|
||||
&OVERLAY_next_cache_finish,
|
||||
&OVERLAY_next_draw_scene,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
#undef SELECT_ENGINE
|
||||
|
@ -12,6 +12,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
extern DrawEngineType draw_engine_overlay_type;
|
||||
extern DrawEngineType draw_engine_overlay_next_type;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -17,8 +17,13 @@
|
||||
|
||||
#include "UI_resources.h"
|
||||
|
||||
#include "overlay_instance.hh"
|
||||
#include "overlay_private.hh"
|
||||
|
||||
using namespace blender::draw;
|
||||
|
||||
using Instance = blender::draw::overlay::Instance<>;
|
||||
|
||||
BLI_STATIC_ASSERT(SI_GRID_STEPS_LEN == OVERLAY_GRID_STEPS_LEN, "")
|
||||
|
||||
void OVERLAY_grid_init(OVERLAY_Data *vedata)
|
||||
@ -225,10 +230,11 @@ void OVERLAY_grid_cache_init(OVERLAY_Data *ved)
|
||||
return;
|
||||
}
|
||||
|
||||
if (ved->instance->grid_ubo == nullptr) {
|
||||
ved->instance->grid_ubo = GPU_uniformbuf_create(sizeof(OVERLAY_GridData));
|
||||
GPUUniformBuf *&grid_ubo = reinterpret_cast<Instance *>(ved->instance)->grid_ubo;
|
||||
if (grid_ubo == nullptr) {
|
||||
grid_ubo = GPU_uniformbuf_create(sizeof(OVERLAY_GridData));
|
||||
}
|
||||
GPU_uniformbuf_update(ved->instance->grid_ubo, &pd->grid_data);
|
||||
GPU_uniformbuf_update(grid_ubo, &pd->grid_data);
|
||||
|
||||
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA;
|
||||
DRW_PASS_CREATE(psl->grid_ps, state);
|
||||
@ -258,7 +264,7 @@ void OVERLAY_grid_cache_init(OVERLAY_Data *ved)
|
||||
|
||||
/* Create 3 quads to render ordered transparency Z axis */
|
||||
grp = DRW_shgroup_create(sh, psl->grid_ps);
|
||||
DRW_shgroup_uniform_block(grp, "grid_buf", ved->instance->grid_ubo);
|
||||
DRW_shgroup_uniform_block(grp, "grid_buf", grid_ubo);
|
||||
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
|
||||
DRW_shgroup_uniform_texture_ref(grp, "depth_tx", &dtxl->depth);
|
||||
|
||||
|
211
source/blender/draw/engines/overlay/overlay_grid.hh
Normal file
211
source/blender/draw/engines/overlay/overlay_grid.hh
Normal file
@ -0,0 +1,211 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup overlay
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DEG_depsgraph_query.h"
|
||||
#include "DNA_camera_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
#include "ED_view3d.h"
|
||||
|
||||
#include "draw_cache.h"
|
||||
#include "draw_pass.hh"
|
||||
#include "overlay_private.hh"
|
||||
#include "overlay_shader_shared.h"
|
||||
|
||||
namespace blender::draw::overlay {
|
||||
|
||||
template<typename SelectEngineT> class Grid {
|
||||
using ResourcesT = Resources<SelectEngineT>;
|
||||
|
||||
private:
|
||||
UniformBuffer<OVERLAY_GridData> data_;
|
||||
|
||||
PassSimple grid_ps_ = {"grid_ps_"};
|
||||
|
||||
float3 grid_axes_ = float3(0.0f);
|
||||
float3 zplane_axes_ = float3(0.0f);
|
||||
OVERLAY_GridBits grid_flag_ = OVERLAY_GridBits(0);
|
||||
OVERLAY_GridBits zneg_flag_ = OVERLAY_GridBits(0);
|
||||
OVERLAY_GridBits zpos_flag_ = OVERLAY_GridBits(0);
|
||||
|
||||
bool enabled_ = false;
|
||||
|
||||
public:
|
||||
void update_ubo(const State &state, const View &view)
|
||||
{
|
||||
float grid_steps[SI_GRID_STEPS_LEN] = {
|
||||
0.001f, 0.01f, 0.1f, 1.0f, 10.0f, 100.0f, 1000.0f, 10000.0f};
|
||||
float grid_steps_y[SI_GRID_STEPS_LEN] = {0.0f}; /* When zero, use value from grid_steps. */
|
||||
data_.line_size = max_ff(0.0f, U.pixelsize - 1.0f) * 0.5f;
|
||||
/* Default, nothing is drawn. */
|
||||
grid_flag_ = zneg_flag_ = zpos_flag_ = OVERLAY_GridBits(0);
|
||||
|
||||
const View3D *v3d = state.v3d;
|
||||
const RegionView3D *rv3d = state.rv3d;
|
||||
|
||||
const bool show_axis_x = (state.v3d_gridflag & V3D_SHOW_X) != 0;
|
||||
const bool show_axis_y = (state.v3d_gridflag & V3D_SHOW_Y) != 0;
|
||||
const bool show_axis_z = (state.v3d_gridflag & V3D_SHOW_Z) != 0;
|
||||
const bool show_floor = (state.v3d_gridflag & V3D_SHOW_FLOOR) != 0;
|
||||
const bool show_ortho_grid = (state.v3d_gridflag & V3D_SHOW_ORTHO_GRID) != 0;
|
||||
const bool show_any = show_axis_x || show_axis_y || show_axis_z || show_floor ||
|
||||
show_ortho_grid;
|
||||
|
||||
enabled_ = !state.hide_overlays && show_any;
|
||||
|
||||
if (!enabled_) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* If perspective view or non-axis aligned view. */
|
||||
if (view.is_persp() || rv3d->view == RV3D_VIEW_USER) {
|
||||
if (show_axis_x) {
|
||||
grid_flag_ |= PLANE_XY | SHOW_AXIS_X;
|
||||
}
|
||||
if (show_axis_y) {
|
||||
grid_flag_ |= PLANE_XY | SHOW_AXIS_Y;
|
||||
}
|
||||
if (show_floor) {
|
||||
grid_flag_ |= PLANE_XY | SHOW_GRID;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (show_ortho_grid && ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT)) {
|
||||
grid_flag_ = PLANE_YZ | SHOW_AXIS_Y | SHOW_AXIS_Z | SHOW_GRID | GRID_BACK;
|
||||
}
|
||||
else if (show_ortho_grid && ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) {
|
||||
grid_flag_ = PLANE_XY | SHOW_AXIS_X | SHOW_AXIS_Y | SHOW_GRID | GRID_BACK;
|
||||
}
|
||||
else if (show_ortho_grid && ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) {
|
||||
grid_flag_ = PLANE_XZ | SHOW_AXIS_X | SHOW_AXIS_Z | SHOW_GRID | GRID_BACK;
|
||||
}
|
||||
}
|
||||
|
||||
grid_axes_[0] = float((grid_flag_ & (PLANE_XZ | PLANE_XY)) != 0);
|
||||
grid_axes_[1] = float((grid_flag_ & (PLANE_YZ | PLANE_XY)) != 0);
|
||||
grid_axes_[2] = float((grid_flag_ & (PLANE_YZ | PLANE_XZ)) != 0);
|
||||
|
||||
/* Z axis if needed */
|
||||
if (((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) && show_axis_z) {
|
||||
zpos_flag_ = SHOW_AXIS_Z;
|
||||
|
||||
float3 zvec = -float3(view.viewinv()[2]);
|
||||
float3 campos = float3(view.viewinv()[3]);
|
||||
|
||||
/* z axis : chose the most facing plane */
|
||||
if (fabsf(zvec[0]) < fabsf(zvec[1])) {
|
||||
zpos_flag_ |= PLANE_XZ;
|
||||
}
|
||||
else {
|
||||
zpos_flag_ |= PLANE_YZ;
|
||||
}
|
||||
zneg_flag_ = zpos_flag_;
|
||||
|
||||
/* Perspective: If camera is below floor plane, we switch clipping.
|
||||
* Orthographic: If eye vector is looking up, we switch clipping. */
|
||||
if ((view.is_persp() && (campos[2] > 0.0f)) || (!view.is_persp() && (zvec[2] < 0.0f))) {
|
||||
zpos_flag_ |= CLIP_ZPOS;
|
||||
zneg_flag_ |= CLIP_ZNEG;
|
||||
}
|
||||
else {
|
||||
zpos_flag_ |= CLIP_ZNEG;
|
||||
zneg_flag_ |= CLIP_ZPOS;
|
||||
}
|
||||
|
||||
zplane_axes_[0] = float((zpos_flag_ & (PLANE_XZ | PLANE_XY)) != 0);
|
||||
zplane_axes_[1] = float((zpos_flag_ & (PLANE_YZ | PLANE_XY)) != 0);
|
||||
zplane_axes_[2] = float((zpos_flag_ & (PLANE_YZ | PLANE_XZ)) != 0);
|
||||
}
|
||||
else {
|
||||
zneg_flag_ = zpos_flag_ = CLIP_ZNEG | CLIP_ZPOS;
|
||||
}
|
||||
|
||||
float dist;
|
||||
if (rv3d->persp == RV3D_CAMOB && v3d->camera && v3d->camera->type == OB_CAMERA) {
|
||||
Object *camera_object = DEG_get_evaluated_object(state.depsgraph, v3d->camera);
|
||||
dist = ((Camera *)(camera_object->data))->clip_end;
|
||||
grid_flag_ |= GRID_CAMERA;
|
||||
zneg_flag_ |= GRID_CAMERA;
|
||||
zpos_flag_ |= GRID_CAMERA;
|
||||
}
|
||||
else {
|
||||
dist = v3d->clip_end;
|
||||
}
|
||||
|
||||
if (view.is_persp()) {
|
||||
data_.size = float4(dist);
|
||||
}
|
||||
else {
|
||||
float viewdist = 1.0f / min_ff(fabsf(view.winmat()[0][0]), fabsf(view.winmat()[1][1]));
|
||||
data_.size = float4(viewdist * dist);
|
||||
}
|
||||
|
||||
data_.distance = dist / 2.0f;
|
||||
|
||||
ED_view3d_grid_steps(state.scene, v3d, rv3d, grid_steps);
|
||||
|
||||
if ((v3d->flag & (V3D_XR_SESSION_SURFACE | V3D_XR_SESSION_MIRROR)) != 0) {
|
||||
/* The calculations for the grid parameters assume that the view matrix has no scale
|
||||
* component, which may not be correct if the user is "shrunk" or "enlarged" by zooming in or
|
||||
* out. Therefore, we need to compensate the values here. */
|
||||
/* Assumption is uniform scaling (all column vectors are of same length). */
|
||||
float viewinvscale = len_v3(view.viewinv()[0]);
|
||||
data_.distance *= viewinvscale;
|
||||
}
|
||||
|
||||
/* Convert to UBO alignment. */
|
||||
for (int i = 0; i < SI_GRID_STEPS_LEN; i++) {
|
||||
data_.steps[i][0] = grid_steps[i];
|
||||
data_.steps[i][1] = (grid_steps_y[i] != 0.0f) ? grid_steps_y[i] : grid_steps[i];
|
||||
}
|
||||
|
||||
data_.push_update();
|
||||
}
|
||||
|
||||
void begin_sync(ResourcesT &res, const State &state, const View &view)
|
||||
{
|
||||
this->update_ubo(state, view);
|
||||
|
||||
if (!enabled_) {
|
||||
return;
|
||||
}
|
||||
|
||||
grid_ps_.init();
|
||||
grid_ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA);
|
||||
grid_ps_.shader_set(res.shaders.grid);
|
||||
grid_ps_.bind_ubo("grid_buf", &data_);
|
||||
grid_ps_.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
grid_ps_.bind_texture("depth_tx", &res.depth_tx);
|
||||
if (zneg_flag_ & SHOW_AXIS_Z) {
|
||||
grid_ps_.push_constant("grid_flag", zneg_flag_);
|
||||
grid_ps_.push_constant("plane_axes", zplane_axes_);
|
||||
grid_ps_.draw(DRW_cache_grid_get());
|
||||
}
|
||||
if (grid_flag_) {
|
||||
grid_ps_.push_constant("grid_flag", grid_flag_);
|
||||
grid_ps_.push_constant("plane_axes", grid_axes_);
|
||||
grid_ps_.draw(DRW_cache_grid_get());
|
||||
}
|
||||
if (zpos_flag_ & SHOW_AXIS_Z) {
|
||||
grid_ps_.push_constant("grid_flag", zpos_flag_);
|
||||
grid_ps_.push_constant("plane_axes", zplane_axes_);
|
||||
grid_ps_.draw(DRW_cache_grid_get());
|
||||
}
|
||||
}
|
||||
|
||||
void draw(ResourcesT &res, Manager &manager, View &view)
|
||||
{
|
||||
if (!enabled_) {
|
||||
return;
|
||||
}
|
||||
|
||||
GPU_framebuffer_bind(res.overlay_color_only_fb);
|
||||
manager.submit(grid_ps_, view);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace blender::draw::overlay
|
250
source/blender/draw/engines/overlay/overlay_instance.cc
Normal file
250
source/blender/draw/engines/overlay/overlay_instance.cc
Normal file
@ -0,0 +1,250 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup overlay
|
||||
*/
|
||||
|
||||
#include "draw_debug.hh"
|
||||
|
||||
#include "overlay_instance.hh"
|
||||
|
||||
namespace blender::draw::overlay {
|
||||
|
||||
template<typename T> void Instance<T>::init()
|
||||
{
|
||||
/* TODO(fclem): Remove DRW global usage. */
|
||||
const DRWContextState *ctx = DRW_context_state_get();
|
||||
/* Was needed by `object_wire_theme_id()` when doing the port. Not sure if needed nowadays. */
|
||||
BKE_view_layer_synced_ensure(ctx->scene, ctx->view_layer);
|
||||
|
||||
state.depsgraph = ctx->depsgraph;
|
||||
state.view_layer = ctx->view_layer;
|
||||
state.scene = ctx->scene;
|
||||
state.v3d = ctx->v3d;
|
||||
state.rv3d = ctx->rv3d;
|
||||
state.active_base = BKE_view_layer_active_base_get(ctx->view_layer);
|
||||
state.object_mode = ctx->object_mode;
|
||||
|
||||
state.pixelsize = U.pixelsize;
|
||||
state.ctx_mode = CTX_data_mode_enum_ex(ctx->object_edit, ctx->obact, ctx->object_mode);
|
||||
state.clear_in_front = (state.v3d->shading.type != OB_SOLID);
|
||||
state.use_in_front = (state.v3d->shading.type <= OB_SOLID) ||
|
||||
BKE_scene_uses_blender_workbench(state.scene);
|
||||
state.is_wireframe_mode = (state.v3d->shading.type == OB_WIRE);
|
||||
state.hide_overlays = (state.v3d->flag2 & V3D_HIDE_OVERLAYS) != 0;
|
||||
state.xray_enabled = XRAY_ACTIVE(state.v3d);
|
||||
state.xray_enabled_and_not_wire = state.xray_enabled && (state.v3d->shading.type > OB_WIRE);
|
||||
state.xray_opacity = XRAY_ALPHA(state.v3d);
|
||||
state.cfra = DEG_get_ctime(state.depsgraph);
|
||||
state.clipping_state = RV3D_CLIPPING_ENABLED(state.v3d, state.rv3d) ? DRW_STATE_CLIP_PLANES :
|
||||
DRWState(0);
|
||||
|
||||
if (!state.hide_overlays) {
|
||||
state.overlay = state.v3d->overlay;
|
||||
state.v3d_flag = state.v3d->flag;
|
||||
state.v3d_gridflag = state.v3d->gridflag;
|
||||
}
|
||||
else {
|
||||
memset(&state.overlay, 0, sizeof(state.overlay));
|
||||
state.v3d_flag = 0;
|
||||
state.v3d_gridflag = 0;
|
||||
state.overlay.flag = V3D_OVERLAY_HIDE_TEXT | V3D_OVERLAY_HIDE_MOTION_PATHS |
|
||||
V3D_OVERLAY_HIDE_BONES | V3D_OVERLAY_HIDE_OBJECT_XTRAS |
|
||||
V3D_OVERLAY_HIDE_OBJECT_ORIGINS;
|
||||
state.overlay.wireframe_threshold = state.v3d->overlay.wireframe_threshold;
|
||||
state.overlay.wireframe_opacity = state.v3d->overlay.wireframe_opacity;
|
||||
}
|
||||
|
||||
/* TODO(fclem): Remove DRW global usage. */
|
||||
resources.globals_buf = G_draw.block_ubo;
|
||||
resources.theme_settings = G_draw.block;
|
||||
}
|
||||
|
||||
template<typename T> void Instance<T>::begin_sync()
|
||||
{
|
||||
const DRWView *view_legacy = DRW_view_default_get();
|
||||
View view("OverlayView", view_legacy);
|
||||
|
||||
resources.begin_sync();
|
||||
|
||||
background.begin_sync(resources, state);
|
||||
prepass.begin_sync(resources, state);
|
||||
empties.begin_sync();
|
||||
metaballs.begin_sync();
|
||||
grid.begin_sync(resources, state, view);
|
||||
}
|
||||
|
||||
template<typename T> void Instance<T>::object_sync(ObjectRef &ob_ref, Manager &manager)
|
||||
{
|
||||
const bool in_edit_mode = object_is_edit_mode(ob_ref.object);
|
||||
const bool needs_prepass = true; /* TODO */
|
||||
|
||||
if (needs_prepass) {
|
||||
switch (ob_ref.object->type) {
|
||||
case OB_MESH:
|
||||
case OB_SURF:
|
||||
case OB_CURVES:
|
||||
case OB_FONT:
|
||||
case OB_CURVES_LEGACY:
|
||||
prepass.object_sync(manager, ob_ref, resources);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (in_edit_mode && !state.hide_overlays) {
|
||||
switch (ob_ref.object->type) {
|
||||
case OB_MESH:
|
||||
break;
|
||||
case OB_ARMATURE:
|
||||
break;
|
||||
case OB_CURVES_LEGACY:
|
||||
break;
|
||||
case OB_SURF:
|
||||
break;
|
||||
case OB_LATTICE:
|
||||
break;
|
||||
case OB_MBALL:
|
||||
metaballs.edit_object_sync(ob_ref, resources);
|
||||
break;
|
||||
case OB_FONT:
|
||||
break;
|
||||
case OB_CURVES:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!state.hide_overlays) {
|
||||
switch (ob_ref.object->type) {
|
||||
case OB_EMPTY:
|
||||
empties.object_sync(ob_ref, resources, state);
|
||||
break;
|
||||
case OB_ARMATURE:
|
||||
break;
|
||||
case OB_MBALL:
|
||||
if (!in_edit_mode) {
|
||||
metaballs.object_sync(ob_ref, resources, state);
|
||||
}
|
||||
break;
|
||||
case OB_GPENCIL_LEGACY:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> void Instance<T>::end_sync()
|
||||
{
|
||||
resources.end_sync();
|
||||
|
||||
metaballs.end_sync(resources, shapes, state);
|
||||
empties.end_sync(resources, shapes, state);
|
||||
}
|
||||
|
||||
template<typename T> void Instance<T>::draw(Manager &manager)
|
||||
{
|
||||
resources.depth_tx.wrap(DRW_viewport_texture_list_get()->depth);
|
||||
resources.depth_in_front_tx.wrap(DRW_viewport_texture_list_get()->depth_in_front);
|
||||
resources.color_overlay_tx.wrap(DRW_viewport_texture_list_get()->color_overlay);
|
||||
resources.color_render_tx.wrap(DRW_viewport_texture_list_get()->color);
|
||||
|
||||
int2 render_size = int2(resources.depth_tx.size());
|
||||
|
||||
const DRWView *view_legacy = DRW_view_default_get();
|
||||
View view("OverlayView", view_legacy);
|
||||
|
||||
/* TODO: Better semantical switch? */
|
||||
if (!resources.color_overlay_tx.is_valid()) {
|
||||
/* Likely to be the selection case. Allocate dummy texture and bind only depth buffer. */
|
||||
resources.line_tx.acquire(int2(1, 1), GPU_RGBA8);
|
||||
resources.color_overlay_alloc_tx.acquire(int2(1, 1), GPU_SRGB8_A8);
|
||||
resources.color_render_alloc_tx.acquire(int2(1, 1), GPU_SRGB8_A8);
|
||||
|
||||
resources.color_overlay_tx.wrap(resources.color_overlay_alloc_tx);
|
||||
resources.color_render_tx.wrap(resources.color_render_alloc_tx);
|
||||
|
||||
resources.overlay_fb.ensure(GPU_ATTACHMENT_TEXTURE(resources.depth_tx));
|
||||
resources.overlay_line_fb.ensure(GPU_ATTACHMENT_TEXTURE(resources.depth_tx));
|
||||
/* Create it but shouldn't even be used. */
|
||||
resources.overlay_color_only_fb.ensure(GPU_ATTACHMENT_NONE,
|
||||
GPU_ATTACHMENT_TEXTURE(resources.color_overlay_tx));
|
||||
}
|
||||
else {
|
||||
resources.line_tx.acquire(render_size, GPU_RGBA8);
|
||||
|
||||
resources.overlay_fb.ensure(GPU_ATTACHMENT_TEXTURE(resources.depth_tx),
|
||||
GPU_ATTACHMENT_TEXTURE(resources.color_overlay_tx));
|
||||
resources.overlay_line_fb.ensure(GPU_ATTACHMENT_TEXTURE(resources.depth_tx),
|
||||
GPU_ATTACHMENT_TEXTURE(resources.color_overlay_tx),
|
||||
GPU_ATTACHMENT_TEXTURE(resources.line_tx));
|
||||
resources.overlay_color_only_fb.ensure(GPU_ATTACHMENT_NONE,
|
||||
GPU_ATTACHMENT_TEXTURE(resources.color_overlay_tx));
|
||||
}
|
||||
|
||||
/* TODO(fclem): Remove mandatory allocation. */
|
||||
if (!resources.depth_in_front_tx.is_valid()) {
|
||||
resources.depth_in_front_alloc_tx.acquire(render_size, GPU_DEPTH_COMPONENT24);
|
||||
resources.depth_in_front_tx.wrap(resources.depth_in_front_alloc_tx);
|
||||
}
|
||||
|
||||
resources.overlay_in_front_fb.ensure(GPU_ATTACHMENT_TEXTURE(resources.depth_in_front_tx),
|
||||
GPU_ATTACHMENT_TEXTURE(resources.color_overlay_tx));
|
||||
resources.overlay_line_in_front_fb.ensure(GPU_ATTACHMENT_TEXTURE(resources.depth_in_front_tx),
|
||||
GPU_ATTACHMENT_TEXTURE(resources.color_overlay_tx),
|
||||
GPU_ATTACHMENT_TEXTURE(resources.line_tx));
|
||||
|
||||
GPU_framebuffer_bind(resources.overlay_color_only_fb);
|
||||
|
||||
float4 clear_color(0.0f);
|
||||
GPU_framebuffer_clear_color(resources.overlay_color_only_fb, clear_color);
|
||||
|
||||
prepass.draw(resources, manager, view);
|
||||
prepass.draw_in_front(resources, manager, view);
|
||||
|
||||
background.draw(resources, manager);
|
||||
|
||||
empties.draw(resources, manager, view);
|
||||
metaballs.draw(resources, manager, view);
|
||||
|
||||
grid.draw(resources, manager, view);
|
||||
|
||||
empties.draw_in_front(resources, manager, view);
|
||||
metaballs.draw_in_front(resources, manager, view);
|
||||
|
||||
// anti_aliasing.draw(resources, manager, view);
|
||||
|
||||
resources.line_tx.release();
|
||||
resources.depth_in_front_alloc_tx.release();
|
||||
resources.color_overlay_alloc_tx.release();
|
||||
resources.color_render_alloc_tx.release();
|
||||
|
||||
resources.read_result();
|
||||
}
|
||||
|
||||
/* Instantiation. */
|
||||
template void Instance<>::init();
|
||||
template void Instance<>::begin_sync();
|
||||
template void Instance<>::object_sync(ObjectRef &ob_ref, Manager &manager);
|
||||
template void Instance<>::end_sync();
|
||||
template void Instance<>::draw(Manager &manager);
|
||||
|
||||
template void Instance<select::Instance>::init();
|
||||
template void Instance<select::Instance>::begin_sync();
|
||||
template void Instance<select::Instance>::object_sync(ObjectRef &ob_ref, Manager &manager);
|
||||
template void Instance<select::Instance>::end_sync();
|
||||
template void Instance<select::Instance>::draw(Manager &manager);
|
||||
|
||||
} // namespace blender::draw::overlay
|
||||
|
||||
/* TODO(fclem): Move elsewhere. */
|
||||
BoneInstanceData::BoneInstanceData(Object *ob,
|
||||
const float *pos,
|
||||
const float radius,
|
||||
const float color[4])
|
||||
{
|
||||
/* TODO(fclem): Use C++ math API. */
|
||||
mul_v3_v3fl(this->mat[0], ob->object_to_world[0], radius);
|
||||
mul_v3_v3fl(this->mat[1], ob->object_to_world[1], radius);
|
||||
mul_v3_v3fl(this->mat[2], ob->object_to_world[2], radius);
|
||||
mul_v3_m4v3(this->mat[3], ob->object_to_world, pos);
|
||||
/* WATCH: Reminder, alpha is wire-size. */
|
||||
OVERLAY_bone_instance_data_set_color(this, color);
|
||||
}
|
102
source/blender/draw/engines/overlay/overlay_instance.hh
Normal file
102
source/blender/draw/engines/overlay/overlay_instance.hh
Normal file
@ -0,0 +1,102 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup overlay
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "draw_manager.hh"
|
||||
|
||||
#include "overlay_background.hh"
|
||||
#include "overlay_empty.hh"
|
||||
#include "overlay_grid.hh"
|
||||
#include "overlay_metaball.hh"
|
||||
#include "overlay_prepass.hh"
|
||||
#include "overlay_shape.hh"
|
||||
|
||||
#include "../select/select_instance.hh"
|
||||
|
||||
namespace blender::draw::overlay {
|
||||
|
||||
template<
|
||||
/* Selection engine reuse most of the Overlay engine by creating selection IDs for each
|
||||
* selectable component and using a special shaders for drawing.
|
||||
* Making the select engine templated makes it easier to phase out any overhead of the
|
||||
* selection for the regular non-selection case.*/
|
||||
typename SelectEngineT = select::InstanceDummy>
|
||||
class Instance {
|
||||
public:
|
||||
/* WORKAROUND: Legacy. Move to grid pass. */
|
||||
GPUUniformBuf *grid_ubo = nullptr;
|
||||
|
||||
ShapeCache shapes;
|
||||
|
||||
/** Global types. */
|
||||
Resources<SelectEngineT> resources = {overlay::ShaderModule<SelectEngineT>::module_get()};
|
||||
State state;
|
||||
|
||||
/** Overlay types. */
|
||||
Background<SelectEngineT> background;
|
||||
Prepass<SelectEngineT> prepass;
|
||||
Metaballs<SelectEngineT> metaballs;
|
||||
Empties<SelectEngineT> empties;
|
||||
Grid<SelectEngineT> grid;
|
||||
|
||||
~Instance()
|
||||
{
|
||||
DRW_UBO_FREE_SAFE(grid_ubo);
|
||||
}
|
||||
|
||||
void init();
|
||||
void begin_sync();
|
||||
void object_sync(ObjectRef &ob_ref, Manager &manager);
|
||||
void end_sync();
|
||||
void draw(Manager &manager);
|
||||
|
||||
private:
|
||||
bool object_is_edit_mode(const Object *ob)
|
||||
{
|
||||
if (DRW_object_is_in_edit_mode(ob)) {
|
||||
/* Also check for context mode as the object mode is not 100% reliable. (see T72490) */
|
||||
switch (ob->type) {
|
||||
case OB_MESH:
|
||||
return state.ctx_mode == CTX_MODE_EDIT_MESH;
|
||||
case OB_ARMATURE:
|
||||
return state.ctx_mode == CTX_MODE_EDIT_ARMATURE;
|
||||
case OB_CURVES_LEGACY:
|
||||
return state.ctx_mode == CTX_MODE_EDIT_CURVE;
|
||||
case OB_SURF:
|
||||
return state.ctx_mode == CTX_MODE_EDIT_SURFACE;
|
||||
case OB_LATTICE:
|
||||
return state.ctx_mode == CTX_MODE_EDIT_LATTICE;
|
||||
case OB_MBALL:
|
||||
return state.ctx_mode == CTX_MODE_EDIT_METABALL;
|
||||
case OB_FONT:
|
||||
return state.ctx_mode == CTX_MODE_EDIT_TEXT;
|
||||
case OB_CURVES:
|
||||
return state.ctx_mode == CTX_MODE_EDIT_CURVES;
|
||||
case OB_POINTCLOUD:
|
||||
case OB_VOLUME:
|
||||
/* No edit mode yet. */
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/* Instantiation. */
|
||||
extern template void Instance<>::init();
|
||||
extern template void Instance<>::begin_sync();
|
||||
extern template void Instance<>::object_sync(ObjectRef &ob_ref, Manager &manager);
|
||||
extern template void Instance<>::end_sync();
|
||||
extern template void Instance<>::draw(Manager &manager);
|
||||
|
||||
extern template void Instance<select::Instance>::init();
|
||||
extern template void Instance<select::Instance>::begin_sync();
|
||||
extern template void Instance<select::Instance>::object_sync(ObjectRef &ob_ref, Manager &manager);
|
||||
extern template void Instance<select::Instance>::end_sync();
|
||||
extern template void Instance<select::Instance>::draw(Manager &manager);
|
||||
|
||||
} // namespace blender::draw::overlay
|
116
source/blender/draw/engines/overlay/overlay_metaball.hh
Normal file
116
source/blender/draw/engines/overlay/overlay_metaball.hh
Normal file
@ -0,0 +1,116 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup overlay
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "DEG_depsgraph_query.h"
|
||||
#include "DNA_space_types.h"
|
||||
#include "ED_mball.h"
|
||||
#include "ED_view3d.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
#include "draw_cache.h"
|
||||
#include "draw_pass.hh"
|
||||
#include "overlay_private.hh"
|
||||
#include "overlay_shader_shared.h"
|
||||
|
||||
namespace blender::draw::overlay {
|
||||
|
||||
template<typename SelectEngineT> class Metaballs {
|
||||
using SelectID = typename SelectEngineT::ID;
|
||||
using ResourcesT = Resources<SelectEngineT>;
|
||||
using SphereOutlineInstanceBuf = ShapeInstanceBuf<SelectEngineT, BoneInstanceData>;
|
||||
|
||||
private:
|
||||
PassSimple metaball_ps_ = {"MetaBalls"};
|
||||
PassSimple metaball_in_front_ps_ = {"MetaBalls_In_front"};
|
||||
|
||||
SphereOutlineInstanceBuf circle_buf_ = {"metaball_data_buf"};
|
||||
SphereOutlineInstanceBuf circle_in_front_buf_ = {"metaball_data_buf"};
|
||||
|
||||
public:
|
||||
void begin_sync()
|
||||
{
|
||||
circle_buf_.clear();
|
||||
circle_in_front_buf_.clear();
|
||||
}
|
||||
|
||||
void edit_object_sync(const ObjectRef &ob_ref, ResourcesT &res)
|
||||
{
|
||||
SphereOutlineInstanceBuf &circle_buf = (ob_ref.object->dtx & OB_DRAW_IN_FRONT) != 0 ?
|
||||
circle_in_front_buf_ :
|
||||
circle_buf_;
|
||||
MetaBall *mb = static_cast<MetaBall *>(ob_ref.object->data);
|
||||
|
||||
const float *color;
|
||||
const float *col_radius = res.theme_settings.color_mball_radius;
|
||||
const float *col_radius_select = res.theme_settings.color_mball_radius_select;
|
||||
const float *col_stiffness = res.theme_settings.color_mball_stiffness;
|
||||
const float *col_stiffness_select = res.theme_settings.color_mball_stiffness_select;
|
||||
|
||||
LISTBASE_FOREACH (MetaElem *, ml, mb->editelems) {
|
||||
const bool is_selected = (ml->flag & SELECT) != 0;
|
||||
const bool is_scale_radius = (ml->flag & MB_SCALE_RAD) != 0;
|
||||
float stiffness_radius = ml->rad * atanf(ml->s) / float(M_PI_2);
|
||||
|
||||
const SelectID radius_id = res.select_id(ob_ref, MBALLSEL_RADIUS);
|
||||
color = (is_selected && is_scale_radius) ? col_radius_select : col_radius;
|
||||
circle_buf.append({ob_ref.object, &ml->x, ml->rad, color}, radius_id);
|
||||
|
||||
const SelectID stiff_id = res.select_id(ob_ref, MBALLSEL_STIFF);
|
||||
color = (is_selected && !is_scale_radius) ? col_stiffness_select : col_stiffness;
|
||||
circle_buf.append({ob_ref.object, &ml->x, stiffness_radius, color}, stiff_id);
|
||||
}
|
||||
}
|
||||
|
||||
void object_sync(const ObjectRef &ob_ref, ResourcesT &res, const State &state)
|
||||
{
|
||||
SphereOutlineInstanceBuf &circle_buf = (ob_ref.object->dtx & OB_DRAW_IN_FRONT) != 0 ?
|
||||
circle_in_front_buf_ :
|
||||
circle_buf_;
|
||||
MetaBall *mb = static_cast<MetaBall *>(ob_ref.object->data);
|
||||
|
||||
const float4 &color = res.object_wire_color(ob_ref, state);
|
||||
const SelectID select_id = res.select_id(ob_ref);
|
||||
|
||||
LISTBASE_FOREACH (MetaElem *, ml, &mb->elems) {
|
||||
/* Draw radius only. */
|
||||
circle_buf.append({ob_ref.object, &ml->x, ml->rad, color}, select_id);
|
||||
}
|
||||
}
|
||||
|
||||
void end_sync(ResourcesT &res, ShapeCache &shapes, const State &state)
|
||||
{
|
||||
auto init_pass = [&](PassSimple &pass, SphereOutlineInstanceBuf &call_buf) {
|
||||
pass.init();
|
||||
pass.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
|
||||
state.clipping_state);
|
||||
/* NOTE: Use armature sphere outline shader to have perspective correct outline instead of
|
||||
* just a circle facing the camera. */
|
||||
pass.shader_set(res.shaders.armature_sphere_outline);
|
||||
pass.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
res.select_bind(pass);
|
||||
|
||||
call_buf.end_sync(pass, shapes.metaball_wire_circle);
|
||||
};
|
||||
init_pass(metaball_ps_, circle_buf_);
|
||||
init_pass(metaball_in_front_ps_, circle_in_front_buf_);
|
||||
}
|
||||
|
||||
void draw(ResourcesT &res, Manager &manager, View &view)
|
||||
{
|
||||
GPU_framebuffer_bind(res.overlay_line_fb);
|
||||
manager.submit(metaball_ps_, view);
|
||||
}
|
||||
|
||||
void draw_in_front(ResourcesT &res, Manager &manager, View &view)
|
||||
{
|
||||
GPU_framebuffer_bind(res.overlay_line_in_front_fb);
|
||||
manager.submit(metaball_in_front_ps_, view);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace blender::draw::overlay
|
68
source/blender/draw/engines/overlay/overlay_prepass.hh
Normal file
68
source/blender/draw/engines/overlay/overlay_prepass.hh
Normal file
@ -0,0 +1,68 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup overlay
|
||||
*
|
||||
* A depth pass that write surface depth when it is needed.
|
||||
* It is also used for selecting non overlay-only objects.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "draw_cache.h"
|
||||
|
||||
#include "overlay_private.hh"
|
||||
|
||||
namespace blender::draw::overlay {
|
||||
|
||||
template<typename SelectEngineT> class Prepass {
|
||||
using SelectID = typename SelectEngineT::ID;
|
||||
using ResourcesT = Resources<SelectEngineT>;
|
||||
|
||||
private:
|
||||
PassMain prepass_ps_ = {"prepass"};
|
||||
PassMain prepass_in_front_ps_ = {"prepass_in_front"};
|
||||
|
||||
public:
|
||||
void begin_sync(ResourcesT &res, const State &state)
|
||||
{
|
||||
auto init_pass = [&](PassMain &pass) {
|
||||
pass.init();
|
||||
pass.state_set(DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | state.clipping_state);
|
||||
pass.shader_set(res.shaders.depth_mesh);
|
||||
res.select_bind(pass);
|
||||
};
|
||||
init_pass(prepass_ps_);
|
||||
init_pass(prepass_in_front_ps_);
|
||||
}
|
||||
|
||||
void object_sync(Manager &manager, const ObjectRef &ob_ref, ResourcesT &res)
|
||||
{
|
||||
PassMain &pass = (ob_ref.object->dtx & OB_DRAW_IN_FRONT) != 0 ? prepass_in_front_ps_ :
|
||||
prepass_ps_;
|
||||
|
||||
/* TODO(fclem) This function should contain what `basic_cache_populate` contained. */
|
||||
|
||||
GPUBatch *geom = DRW_cache_object_surface_get(ob_ref.object);
|
||||
if (geom) {
|
||||
ResourceHandle res_handle = manager.resource_handle(ob_ref);
|
||||
pass.draw(geom, res_handle, res.select_id(ob_ref).get());
|
||||
}
|
||||
}
|
||||
|
||||
void draw(ResourcesT &res, Manager &manager, View &view)
|
||||
{
|
||||
/* Should be fine to use the line buffer since the prepass only writes to the depth buffer. */
|
||||
GPU_framebuffer_bind(res.overlay_line_fb);
|
||||
manager.submit(prepass_ps_, view);
|
||||
}
|
||||
|
||||
void draw_in_front(ResourcesT &res, Manager &manager, View &view)
|
||||
{
|
||||
/* Should be fine to use the line buffer since the prepass only writes to the depth buffer. */
|
||||
GPU_framebuffer_bind(res.overlay_line_in_front_fb);
|
||||
manager.submit(prepass_in_front_ps_, view);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace blender::draw::overlay
|
@ -7,13 +7,17 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BKE_global.h"
|
||||
|
||||
#include "DRW_gpu_wrapper.hh"
|
||||
#include "DRW_render.h"
|
||||
|
||||
#include "overlay_shader_shared.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "draw_handle.hh"
|
||||
|
||||
#include "overlay_shader.hh"
|
||||
#include "overlay_shader_shared.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||