Overlay-Next: Initial implementation #107045

Closed
Clément Foucault wants to merge 28 commits from fclem/blender:overlay-next into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
13 changed files with 235 additions and 120 deletions
Showing only changes of commit 84ff44769f - Show all commits

View File

@ -19,12 +19,14 @@
namespace blender::draw::overlay { namespace blender::draw::overlay {
class Background { template<typename SelectEngineT> class Background {
using ResourcesT = Resources<SelectEngineT>;
private: private:
PassSimple bg_ps_ = {"Background"}; PassSimple bg_ps_ = {"Background"};
public: public:
void begin_sync(Resources &res, const State &state) void begin_sync(ResourcesT &res, const State &state)
{ {
DRWState pass_state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_BACKGROUND; DRWState pass_state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_BACKGROUND;
float4 color_override(0.0f, 0.0f, 0.0f, 0.0f); float4 color_override(0.0f, 0.0f, 0.0f, 0.0f);
@ -92,7 +94,7 @@ class Background {
} }
} }
void draw(Resources &res, Manager &manager) void draw(ResourcesT &res, Manager &manager)
{ {
GPU_framebuffer_bind(res.overlay_color_only_fb); GPU_framebuffer_bind(res.overlay_color_only_fb);
manager.submit(bg_ps_); manager.submit(bg_ps_);

View File

@ -15,14 +15,15 @@
namespace blender::draw::overlay { namespace blender::draw::overlay {
class Empties { template<typename SelectEngineT> class Empties {
using SelectID = typename SelectEngineT::ID;
using ResourcesT = Resources<SelectEngineT>;
using EmptyInstanceBuf = ShapeInstanceBuf<SelectEngineT, ExtraInstanceData>;
private: private:
PassSimple empty_ps_ = {"Empties"}; PassSimple empty_ps_ = {"Empties"};
PassSimple empty_in_front_ps_ = {"Empties_In_front"}; PassSimple empty_in_front_ps_ = {"Empties_In_front"};
using EmptyInstanceBuf = StorageVectorBuffer<ExtraInstanceData>;
struct CallBuffers { struct CallBuffers {
EmptyInstanceBuf plain_axes_buf = {"plain_axes_buf"}; EmptyInstanceBuf plain_axes_buf = {"plain_axes_buf"};
EmptyInstanceBuf single_arrow_buf = {"single_arrow_buf"}; EmptyInstanceBuf single_arrow_buf = {"single_arrow_buf"};
@ -49,7 +50,7 @@ class Empties {
} }
} }
void object_sync(const ObjectRef &ob_ref, const Resources &res, const State &state) 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)]; CallBuffers &call_bufs = call_buffers_[int((ob_ref.object->dtx & OB_DRAW_IN_FRONT) != 0)];
@ -57,36 +58,39 @@ class Empties {
ExtraInstanceData data( ExtraInstanceData data(
float4x4(ob_ref.object->object_to_world), color, ob_ref.object->empty_drawsize); float4x4(ob_ref.object->object_to_world), color, ob_ref.object->empty_drawsize);
/* TODO(fclem): Get selection ID from the selection engine. */
const SelectID select_id = res.select_id(ob_ref);
switch (ob_ref.object->empty_drawtype) { switch (ob_ref.object->empty_drawtype) {
case OB_PLAINAXES: case OB_PLAINAXES:
call_bufs.plain_axes_buf.append(data); call_bufs.plain_axes_buf.append(data, select_id);
break; break;
case OB_SINGLE_ARROW: case OB_SINGLE_ARROW:
call_bufs.single_arrow_buf.append(data); call_bufs.single_arrow_buf.append(data, select_id);
break; break;
case OB_CUBE: case OB_CUBE:
call_bufs.cube_buf.append(data); call_bufs.cube_buf.append(data, select_id);
break; break;
case OB_CIRCLE: case OB_CIRCLE:
call_bufs.circle_buf.append(data); call_bufs.circle_buf.append(data, select_id);
break; break;
case OB_EMPTY_SPHERE: case OB_EMPTY_SPHERE:
call_bufs.sphere_buf.append(data); call_bufs.sphere_buf.append(data, select_id);
break; break;
case OB_EMPTY_CONE: case OB_EMPTY_CONE:
call_bufs.cone_buf.append(data); call_bufs.cone_buf.append(data, select_id);
break; break;
case OB_ARROWS: case OB_ARROWS:
call_bufs.arrows_buf.append(data); call_bufs.arrows_buf.append(data, select_id);
break; break;
case OB_EMPTY_IMAGE: case OB_EMPTY_IMAGE:
/* This only show the frame. See OVERLAY_image_empty_cache_populate() for the image. */ /* This only show the frame. See OVERLAY_image_empty_cache_populate() for the image. */
call_bufs.image_buf.append(data); call_bufs.image_buf.append(data, select_id);
break; break;
} }
} }
void end_sync(Resources &res, ShapeCache &shapes, const State &state) void end_sync(ResourcesT &res, ShapeCache &shapes, const State &state)
{ {
auto init_pass = [&](PassSimple &pass, CallBuffers &call_bufs) { auto init_pass = [&](PassSimple &pass, CallBuffers &call_bufs) {
pass.init(); pass.init();
@ -95,49 +99,26 @@ class Empties {
pass.shader_set(OVERLAY_shader_extra(false)); pass.shader_set(OVERLAY_shader_extra(false));
pass.bind_ubo("globalsBlock", &res.globals_buf); pass.bind_ubo("globalsBlock", &res.globals_buf);
call_bufs.plain_axes_buf.push_update(); call_bufs.plain_axes_buf.end_sync(pass, shapes.plain_axes);
pass.bind_ssbo("data_buf", &call_bufs.plain_axes_buf); call_bufs.single_arrow_buf.end_sync(pass, shapes.single_arrow);
pass.draw(shapes.plain_axes, call_bufs.plain_axes_buf.size()); call_bufs.cube_buf.end_sync(pass, shapes.cube);
call_bufs.circle_buf.end_sync(pass, shapes.circle);
call_bufs.single_arrow_buf.push_update(); call_bufs.sphere_buf.end_sync(pass, shapes.empty_sphere);
pass.bind_ssbo("data_buf", &call_bufs.single_arrow_buf); call_bufs.cone_buf.end_sync(pass, shapes.empty_cone);
pass.draw(shapes.single_arrow, call_bufs.single_arrow_buf.size()); call_bufs.arrows_buf.end_sync(pass, shapes.arrows);
call_bufs.image_buf.end_sync(pass, shapes.quad_wire);
call_bufs.cube_buf.push_update();
pass.bind_ssbo("data_buf", &call_bufs.cube_buf);
pass.draw(shapes.cube, call_bufs.cube_buf.size());
call_bufs.circle_buf.push_update();
pass.bind_ssbo("data_buf", &call_bufs.circle_buf);
pass.draw(shapes.circle, call_bufs.circle_buf.size());
call_bufs.sphere_buf.push_update();
pass.bind_ssbo("data_buf", &call_bufs.sphere_buf);
pass.draw(shapes.empty_sphere, call_bufs.sphere_buf.size());
call_bufs.cone_buf.push_update();
pass.bind_ssbo("data_buf", &call_bufs.cone_buf);
pass.draw(shapes.empty_cone, call_bufs.cone_buf.size());
call_bufs.arrows_buf.push_update();
pass.bind_ssbo("data_buf", &call_bufs.arrows_buf);
pass.draw(shapes.arrows, call_bufs.arrows_buf.size());
call_bufs.image_buf.push_update();
pass.bind_ssbo("data_buf", &call_bufs.image_buf);
pass.draw(shapes.quad_wire, call_bufs.image_buf.size());
}; };
init_pass(empty_ps_, call_buffers_[0]); init_pass(empty_ps_, call_buffers_[0]);
init_pass(empty_in_front_ps_, call_buffers_[1]); init_pass(empty_in_front_ps_, call_buffers_[1]);
} }
void draw(Resources &res, Manager &manager, View &view) void draw(ResourcesT &res, Manager &manager, View &view)
{ {
GPU_framebuffer_bind(res.overlay_line_fb); GPU_framebuffer_bind(res.overlay_line_fb);
manager.submit(empty_ps_, view); manager.submit(empty_ps_, view);
} }
void draw_in_front(Resources &res, Manager &manager, View &view) void draw_in_front(ResourcesT &res, Manager &manager, View &view)
{ {
GPU_framebuffer_bind(res.overlay_line_in_front_fb); GPU_framebuffer_bind(res.overlay_line_in_front_fb);
manager.submit(empty_in_front_ps_, view); manager.submit(empty_in_front_ps_, view);

View File

@ -30,6 +30,10 @@
#include "overlay_engine.h" #include "overlay_engine.h"
#include "overlay_private.hh" #include "overlay_private.hh"
using namespace blender::draw;
using Instance = blender::draw::overlay::Instance<>;
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/** \name Engine Callbacks /** \name Engine Callbacks
* \{ */ * \{ */
@ -51,7 +55,7 @@ static void OVERLAY_engine_init(void *vedata)
/* Allocate instance. */ /* Allocate instance. */
if (data->instance == nullptr) { if (data->instance == nullptr) {
data->instance = new blender::draw::overlay::Instance(); data->instance = new Instance();
} }
OVERLAY_PrivateData *pd = stl->pd; OVERLAY_PrivateData *pd = stl->pd;
@ -737,7 +741,7 @@ static void OVERLAY_engine_free()
static void OVERLAY_instance_free(void *instance_) static void OVERLAY_instance_free(void *instance_)
{ {
blender::draw::overlay::Instance *instance = (blender::draw::overlay::Instance *)instance_; auto *instance = (Instance *)instance_;
if (instance != nullptr) { if (instance != nullptr) {
delete instance; delete instance;
} }
@ -748,8 +752,6 @@ static void OVERLAY_instance_free(void *instance_)
/** \name Engine Instance /** \name Engine Instance
* \{ */ * \{ */
using namespace blender::draw;
static void OVERLAY_next_engine_init(void *vedata) static void OVERLAY_next_engine_init(void *vedata)
{ {
if (!GPU_shader_storage_buffer_objects_support()) { if (!GPU_shader_storage_buffer_objects_support()) {
@ -759,10 +761,10 @@ static void OVERLAY_next_engine_init(void *vedata)
OVERLAY_Data *ved = reinterpret_cast<OVERLAY_Data *>(vedata); OVERLAY_Data *ved = reinterpret_cast<OVERLAY_Data *>(vedata);
if (ved->instance == nullptr) { if (ved->instance == nullptr) {
ved->instance = new overlay::Instance(); ved->instance = new Instance();
} }
ved->instance->init(); reinterpret_cast<Instance *>(ved->instance)->init();
} }
static void OVERLAY_next_cache_init(void *vedata) static void OVERLAY_next_cache_init(void *vedata)
@ -770,7 +772,7 @@ static void OVERLAY_next_cache_init(void *vedata)
if (!GPU_shader_storage_buffer_objects_support()) { if (!GPU_shader_storage_buffer_objects_support()) {
return; return;
} }
reinterpret_cast<OVERLAY_Data *>(vedata)->instance->begin_sync(); reinterpret_cast<Instance *>(reinterpret_cast<OVERLAY_Data *>(vedata)->instance)->begin_sync();
} }
static void OVERLAY_next_cache_populate(void *vedata, Object *object) static void OVERLAY_next_cache_populate(void *vedata, Object *object)
@ -783,7 +785,8 @@ static void OVERLAY_next_cache_populate(void *vedata, Object *object)
ref.dupli_object = DRW_object_get_dupli(object); ref.dupli_object = DRW_object_get_dupli(object);
ref.dupli_parent = DRW_object_get_dupli_parent(object); ref.dupli_parent = DRW_object_get_dupli_parent(object);
reinterpret_cast<OVERLAY_Data *>(vedata)->instance->object_sync(ref); reinterpret_cast<Instance *>(reinterpret_cast<OVERLAY_Data *>(vedata)->instance)
->object_sync(ref);
} }
static void OVERLAY_next_cache_finish(void *vedata) static void OVERLAY_next_cache_finish(void *vedata)
@ -791,7 +794,7 @@ static void OVERLAY_next_cache_finish(void *vedata)
if (!GPU_shader_storage_buffer_objects_support()) { if (!GPU_shader_storage_buffer_objects_support()) {
return; return;
} }
reinterpret_cast<OVERLAY_Data *>(vedata)->instance->end_sync(); reinterpret_cast<Instance *>(reinterpret_cast<OVERLAY_Data *>(vedata)->instance)->end_sync();
} }
static void OVERLAY_next_draw_scene(void *vedata) static void OVERLAY_next_draw_scene(void *vedata)
@ -800,7 +803,8 @@ static void OVERLAY_next_draw_scene(void *vedata)
return; return;
} }
reinterpret_cast<OVERLAY_Data *>(vedata)->instance->draw(*DRW_manager_get()); reinterpret_cast<Instance *>(reinterpret_cast<OVERLAY_Data *>(vedata)->instance)
->draw(*DRW_manager_get());
} }
/** \} */ /** \} */

View File

@ -20,6 +20,10 @@
#include "overlay_instance.hh" #include "overlay_instance.hh"
#include "overlay_private.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, "") BLI_STATIC_ASSERT(SI_GRID_STEPS_LEN == OVERLAY_GRID_STEPS_LEN, "")
void OVERLAY_grid_init(OVERLAY_Data *vedata) void OVERLAY_grid_init(OVERLAY_Data *vedata)
@ -226,10 +230,11 @@ void OVERLAY_grid_cache_init(OVERLAY_Data *ved)
return; return;
} }
if (ved->instance->grid_ubo == nullptr) { GPUUniformBuf *&grid_ubo = reinterpret_cast<Instance *>(ved->instance)->grid_ubo;
ved->instance->grid_ubo = GPU_uniformbuf_create(sizeof(OVERLAY_GridData)); 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; DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA;
DRW_PASS_CREATE(psl->grid_ps, state); DRW_PASS_CREATE(psl->grid_ps, state);
@ -259,7 +264,7 @@ void OVERLAY_grid_cache_init(OVERLAY_Data *ved)
/* Create 3 quads to render ordered transparency Z axis */ /* Create 3 quads to render ordered transparency Z axis */
grp = DRW_shgroup_create(sh, psl->grid_ps); 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_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_texture_ref(grp, "depth_tx", &dtxl->depth); DRW_shgroup_uniform_texture_ref(grp, "depth_tx", &dtxl->depth);

View File

@ -18,7 +18,9 @@
namespace blender::draw::overlay { namespace blender::draw::overlay {
class Grid { template<typename SelectEngineT> class Grid {
using ResourcesT = Resources<SelectEngineT>;
private: private:
UniformBuffer<OVERLAY_GridData> data_; UniformBuffer<OVERLAY_GridData> data_;
@ -164,7 +166,7 @@ class Grid {
data_.push_update(); data_.push_update();
} }
void begin_sync(Resources &res, const State &state, const View &view) void begin_sync(ResourcesT &res, const State &state, const View &view)
{ {
this->update_ubo(state, view); this->update_ubo(state, view);
@ -195,7 +197,7 @@ class Grid {
} }
} }
void draw(Resources &res, Manager &manager, View &view) void draw(ResourcesT &res, Manager &manager, View &view)
{ {
if (!enabled_) { if (!enabled_) {
return; return;

View File

@ -10,7 +10,7 @@
namespace blender::draw::overlay { namespace blender::draw::overlay {
void Instance::init() template<typename T> void Instance<T>::init()
{ {
resources.depth_tx.wrap(DRW_viewport_texture_list_get()->depth); 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.depth_in_front_tx.wrap(DRW_viewport_texture_list_get()->depth_in_front);
@ -65,7 +65,7 @@ void Instance::init()
resources.theme_settings = G_draw.block; resources.theme_settings = G_draw.block;
} }
void Instance::begin_sync() template<typename T> void Instance<T>::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);
@ -76,7 +76,7 @@ void Instance::begin_sync()
grid.begin_sync(resources, state, view); grid.begin_sync(resources, state, view);
} }
void Instance::object_sync(ObjectRef &ob_ref) template<typename T> void Instance<T>::object_sync(ObjectRef &ob_ref)
{ {
const bool in_edit_mode = object_is_edit_mode(ob_ref.object); const bool in_edit_mode = object_is_edit_mode(ob_ref.object);
@ -120,13 +120,13 @@ void Instance::object_sync(ObjectRef &ob_ref)
} }
} }
void Instance::end_sync() template<typename T> void Instance<T>::end_sync()
{ {
metaballs.end_sync(resources, state); metaballs.end_sync(resources, state);
empties.end_sync(resources, shapes, state); empties.end_sync(resources, shapes, state);
} }
void Instance::draw(Manager &manager) template<typename T> void Instance<T>::draw(Manager &manager)
{ {
/* WORKAROUND: This is to prevent crashes when using depth picking or selection. /* WORKAROUND: This is to prevent crashes when using depth picking or selection.
* The selection engine should handle theses cases instead. */ * The selection engine should handle theses cases instead. */
@ -182,4 +182,11 @@ void Instance::draw(Manager &manager)
resources.depth_in_front_alloc_tx.release(); resources.depth_in_front_alloc_tx.release();
} }
/* Instantiation. */
template void Instance<>::init();
template void Instance<>::begin_sync();
template void Instance<>::object_sync(ObjectRef &ob_ref);
template void Instance<>::end_sync();
template void Instance<>::draw(Manager &manager);
} // namespace blender::draw::overlay } // namespace blender::draw::overlay

View File

@ -14,6 +14,9 @@
#include "overlay_metaball.hh" #include "overlay_metaball.hh"
#include "overlay_shape.hh" #include "overlay_shape.hh"
#include "../select/select_empty.hh"
#include "../select/select_object.hh"
namespace blender::draw::overlay { namespace blender::draw::overlay {
class ShaderCache { class ShaderCache {
@ -22,32 +25,12 @@ class ShaderCache {
int clipping_enabled = 0; int clipping_enabled = 0;
}; };
class SceneResources { template<
ShaderCache shaders; /* Selection engine reuse most of the Overlay engine by creating selection IDs for each
* selectable component and using a special shaders for drawing.
// UniformBuffer<ThemeColorData> theme_colors; * Making the select engine templated makes it easier to phase out any overhead of the
// Texture color_ramp = {"color_ramp"}; * selection for the regular non-selection case.*/
typename SelectEngineT = select::EngineEmpty>
void weight_ramp_init()
{
/* Weight Painting color ramp texture */
// bool user_weight_ramp = (U.flag & USER_CUSTOM_RANGE) != 0;
// if (weight_ramp_custom != user_weight_ramp ||
// (user_weight_ramp && memcmp(&weight_ramp_copy, &U.coba_weight, sizeof(ColorBand)) != 0))
// {
// DRW_TEXTURE_FREE_SAFE(G_draw.weight_ramp);
// }
// if (G_draw.weight_ramp == NULL) {
// weight_ramp_custom = user_weight_ramp;
// memcpy(&weight_ramp_copy, &U.coba_weight, sizeof(ColorBand));
// G_draw.weight_ramp = DRW_create_weight_colorramp_texture();
// }
}
};
class Instance { class Instance {
public: public:
ShaderCache shaders; ShaderCache shaders;
@ -57,14 +40,14 @@ class Instance {
GPUUniformBuf *grid_ubo = nullptr; GPUUniformBuf *grid_ubo = nullptr;
/** Global types. */ /** Global types. */
Resources resources; Resources<SelectEngineT> resources;
State state; State state;
/** Overlay types. */ /** Overlay types. */
Background background; Background<SelectEngineT> background;
Metaballs metaballs; Metaballs<SelectEngineT> metaballs;
Empties empties; Empties<SelectEngineT> empties;
Grid grid; Grid<SelectEngineT> grid;
~Instance() ~Instance()
{ {
@ -109,4 +92,11 @@ class Instance {
} }
}; };
/* Instantiation. */
extern template void Instance<>::init();
extern template void Instance<>::begin_sync();
extern template void Instance<>::object_sync(ObjectRef &ob_ref);
extern template void Instance<>::end_sync();
extern template void Instance<>::draw(Manager &manager);
} // namespace blender::draw::overlay } // namespace blender::draw::overlay

View File

@ -19,7 +19,8 @@
namespace blender::draw::overlay { namespace blender::draw::overlay {
class Metaballs { template<typename SelectEngineT> class Metaballs {
using ResourcesT = Resources<SelectEngineT>;
private: private:
PassSimple metaball_ps_ = {"MetaBalls"}; PassSimple metaball_ps_ = {"MetaBalls"};
@ -50,7 +51,7 @@ class Metaballs {
OVERLAY_bone_instance_data_set_color(data, color); OVERLAY_bone_instance_data_set_color(data, color);
} }
void edit_object_sync(const ObjectRef &ob_ref, const Resources &res) void edit_object_sync(const ObjectRef &ob_ref, const ResourcesT &res)
{ {
ArmatureSphereBuf &data_buf = (ob_ref.object->dtx & OB_DRAW_IN_FRONT) != 0 ? ArmatureSphereBuf &data_buf = (ob_ref.object->dtx & OB_DRAW_IN_FRONT) != 0 ?
data_in_front_buf_ : data_in_front_buf_ :
@ -79,7 +80,7 @@ class Metaballs {
} }
} }
void object_sync(const ObjectRef &ob_ref, const Resources &res, const State &state) void object_sync(const ObjectRef &ob_ref, const ResourcesT &res, const State &state)
{ {
ArmatureSphereBuf &data_buf = (ob_ref.object->dtx & OB_DRAW_IN_FRONT) != 0 ? ArmatureSphereBuf &data_buf = (ob_ref.object->dtx & OB_DRAW_IN_FRONT) != 0 ?
data_in_front_buf_ : data_in_front_buf_ :
@ -96,7 +97,7 @@ class Metaballs {
} }
} }
void end_sync(Resources &res, const State &state) void end_sync(ResourcesT &res, const State &state)
{ {
auto init_pass = [&](PassSimple &pass, ArmatureSphereBuf &data_buf) { auto init_pass = [&](PassSimple &pass, ArmatureSphereBuf &data_buf) {
data_buf.push_update(); data_buf.push_update();
@ -113,13 +114,13 @@ class Metaballs {
init_pass(metaball_in_front_ps_, data_in_front_buf_); init_pass(metaball_in_front_ps_, data_in_front_buf_);
} }
void draw(Resources &res, Manager &manager, View &view) void draw(ResourcesT &res, Manager &manager, View &view)
{ {
GPU_framebuffer_bind(res.overlay_line_fb); GPU_framebuffer_bind(res.overlay_line_fb);
manager.submit(metaball_ps_, view); manager.submit(metaball_ps_, view);
} }
void draw_in_front(Resources &res, Manager &manager, View &view) void draw_in_front(ResourcesT &res, Manager &manager, View &view)
{ {
GPU_framebuffer_bind(res.overlay_line_in_front_fb); GPU_framebuffer_bind(res.overlay_line_in_front_fb);
manager.submit(metaball_in_front_ps_, view); manager.submit(metaball_in_front_ps_, view);

View File

@ -18,10 +18,6 @@
#include "overlay_shader_shared.h" #include "overlay_shader_shared.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __APPLE__ #ifdef __APPLE__
# define USE_GEOM_SHADER_WORKAROUND 1 # define USE_GEOM_SHADER_WORKAROUND 1
#else #else
@ -35,7 +31,7 @@ extern "C" {
struct ImBuf; struct ImBuf;
namespace blender::draw::overlay { namespace blender::draw::overlay {
class Instance; template<typename SelectEngineT> class Instance;
struct State { struct State {
Depsgraph *depsgraph; Depsgraph *depsgraph;
@ -68,7 +64,7 @@ using blender::draw::TextureFromPool;
using blender::draw::TextureRef; using blender::draw::TextureRef;
using ArmatureSphereBuf = StorageVectorBuffer<float4x4>; using ArmatureSphereBuf = StorageVectorBuffer<float4x4>;
struct Resources { template<typename SelectEngineT> struct Resources : public SelectEngineT::SelectMap {
Framebuffer overlay_fb = {"overlay_fb"}; Framebuffer overlay_fb = {"overlay_fb"};
Framebuffer overlay_in_front_fb = {"overlay_in_front_fb"}; Framebuffer overlay_in_front_fb = {"overlay_in_front_fb"};
Framebuffer overlay_color_only_fb = {"overlay_color_only_fb"}; Framebuffer overlay_color_only_fb = {"overlay_color_only_fb"};
@ -578,7 +574,7 @@ typedef struct OVERLAY_Data {
OVERLAY_PassList *psl; OVERLAY_PassList *psl;
OVERLAY_StorageList *stl; OVERLAY_StorageList *stl;
blender::draw::overlay::Instance *instance; void *instance;
} OVERLAY_Data; } OVERLAY_Data;
typedef struct OVERLAY_DupliData { typedef struct OVERLAY_DupliData {
@ -927,7 +923,3 @@ GPUShader *OVERLAY_shader_xray_fade(void);
OVERLAY_InstanceFormats *OVERLAY_shader_instance_formats_get(void); OVERLAY_InstanceFormats *OVERLAY_shader_instance_formats_get(void);
void OVERLAY_shader_free(void); void OVERLAY_shader_free(void);
#ifdef __cplusplus
}
#endif

View File

@ -192,7 +192,6 @@ struct ThemeColorData {
}; };
BLI_STATIC_ASSERT_ALIGN(ThemeColorData, 16) BLI_STATIC_ASSERT_ALIGN(ThemeColorData, 16)
/* TODO Move to overlay engine. */
struct ExtraInstanceData { struct ExtraInstanceData {
float4 color_; float4 color_;
float4x4 object_to_world_; float4x4 object_to_world_;

View File

@ -12,6 +12,41 @@
namespace blender::draw::overlay { namespace blender::draw::overlay {
/**
* Buffer containing instances of a certain shape.
*/
template<typename SelectEngineT, typename InstanceDataT>
struct ShapeInstanceBuf : private SelectEngineT::SelectBuf {
using SelectID = typename SelectEngineT::ID;
StorageVectorBuffer<InstanceDataT> data_buf;
ShapeInstanceBuf(const char *name = nullptr) : data_buf(name){};
void clear()
{
this->select_clear();
data_buf.clear();
}
void append(const InstanceDataT &data, SelectID select_id)
{
this->select_append(select_id);
data_buf.append(data);
}
void end_sync(PassSimple &pass, GPUBatch *shape)
{
if (data_buf.size() == 0) {
return;
}
this->select_bind(pass);
data_buf.push_update();
pass.bind_ssbo("data_buf", &data_buf);
pass.draw(shape, data_buf.size());
}
};
/** /**
* Contains all overlay generic geometry batches. * Contains all overlay generic geometry batches.
*/ */

View File

@ -0,0 +1,34 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2023 Blender Foundation. */
/** \file
* \ingroup draw_engine
*
* Dummy implementation of the select engine types to avoid any overhead.
*/
#pragma once
#include "draw_manager.hh"
namespace blender::draw::select {
struct EngineEmpty {
/* Add type safety to selection ID. Only the select engine should provide them. */
struct ID {};
struct SelectBuf {
void select_clear(){};
void select_append(ID){};
void select_bind(PassSimple &){};
};
struct SelectMap {
[[nodiscard]] constexpr ID select_id(const ObjectRef &)
{
return {};
}
};
};
} // namespace blender::draw::select

View File

@ -0,0 +1,63 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2023 Blender Foundation. */
/** \file
* \ingroup draw_engine
*
* This is an implementation of the Select engine specialized for selecting object.
* Should plug seamlessly inside the overlay engine logic.
*/
#pragma once
#include "DRW_gpu_wrapper.hh"
#include "draw_manager.hh"
namespace blender::draw::select {
struct EngineObject {
/* Add type safety to selection ID. Only the select engine should provide them. */
struct ID {
uint32_t value;
};
/**
* Add a dedicated selection id buffer to a pass.
* Use this when not using a #PassMain which can pass the select ID via CustomID.
*/
struct SelectBuf {
StorageVectorBuffer<uint32_t> select_buf = {"select_buf"};
void select_clear()
{
select_buf.clear();
}
void select_append(ID select_id)
{
select_buf.append(select_id.value);
}
void select_bind(PassSimple &pass)
{
select_buf.push_update();
pass.bind_ssbo("select_buf", &select_buf);
}
};
/**
* Generate selection IDs from objects and keep record of the mapping between them.
*/
struct SelectMap {
uint next_id = 0;
Map<uint, ObjectRef> map;
[[nodiscard]] const ID select_id(const ObjectRef &)
{
/* TODO Insert Ref into the map. */
return {next_id++};
}
};
};
} // namespace blender::draw::select