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.
9 changed files with 513 additions and 10 deletions
Showing only changes of commit 279774ad0b - Show all commits

View File

@ -192,6 +192,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
@ -291,6 +292,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
)

View File

@ -20,8 +20,13 @@
#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"
@ -46,8 +51,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 blender::draw::overlay::Instance();
}
OVERLAY_PrivateData *pd = stl->pd;
@ -731,9 +735,70 @@ static void OVERLAY_engine_free()
static void OVERLAY_instance_free(void *instance_)
{
OVERLAY_Instance *instance = (OVERLAY_Instance *)instance_;
DRW_UBO_FREE_SAFE(instance->grid_ubo);
MEM_freeN(instance);
blender::draw::overlay::Instance *instance = (blender::draw::overlay::Instance *)instance_;
if (instance != nullptr) {
delete instance;
}
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Engine Instance
* \{ */
using namespace blender::draw;
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 overlay::Instance();
}
ved->instance->init();
}
static void OVERLAY_next_cache_init(void *vedata)
{
if (!GPU_shader_storage_buffer_objects_support()) {
return;
}
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<OVERLAY_Data *>(vedata)->instance->object_sync(ref);
}
static void OVERLAY_next_cache_finish(void *vedata)
{
if (!GPU_shader_storage_buffer_objects_support()) {
return;
}
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<OVERLAY_Data *>(vedata)->instance->draw(*DRW_manager_get());
}
/** \} */
@ -762,6 +827,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

View File

@ -12,6 +12,7 @@ extern "C" {
#endif
extern DrawEngineType draw_engine_overlay_type;
extern DrawEngineType draw_engine_overlay_next_type;
#ifdef __cplusplus
}

View File

@ -17,6 +17,7 @@
#include "UI_resources.h"
#include "overlay_instance.hh"
#include "overlay_private.hh"
BLI_STATIC_ASSERT(SI_GRID_STEPS_LEN == OVERLAY_GRID_STEPS_LEN, "")

View File

@ -0,0 +1,198 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup overlay
*/
#pragma once
#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 {
class Grid {
private:
UniformBuffer<OVERLAY_GridData> data_;
bool enabled = false;
PassSimple grid_ps_ = {"grid_ps_"};
float3 grid_axes = float3(0.0f);
float3 zplane_axes = float3(0.0f);
OVERLAY_GridBits grid_flag_;
OVERLAY_GridBits zneg_flag_;
OVERLAY_GridBits zpos_flag_;
public:
void update_ubo()
{
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);
/* SPACE_VIEW3D */
Scene *scene = DRW_context_state_get()->scene;
View3D *v3d = DRW_context_state_get()->v3d;
RegionView3D *rv3d = DRW_context_state_get()->rv3d;
const bool show_axis_x = true; //(pd->v3d_gridflag & V3D_SHOW_X) != 0;
const bool show_axis_y = true; //(pd->v3d_gridflag & V3D_SHOW_Y) != 0;
const bool show_axis_z = true; //(pd->v3d_gridflag & V3D_SHOW_Z) != 0;
const bool show_floor = true; //(pd->v3d_gridflag & V3D_SHOW_FLOOR) != 0;
const bool show_ortho_grid = true; //(pd->v3d_gridflag & V3D_SHOW_ORTHO_GRID) != 0;
// if (pd->hide_overlays || !(pd->v3d_gridflag & (V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_Z |
// V3D_SHOW_FLOOR | V3D_SHOW_ORTHO_GRID))) {
// return;
// }
float viewinv[4][4], wininv[4][4];
float viewmat[4][4], winmat[4][4];
DRW_view_winmat_get(nullptr, winmat, false);
DRW_view_winmat_get(nullptr, wininv, true);
DRW_view_viewmat_get(nullptr, viewmat, false);
DRW_view_viewmat_get(nullptr, viewinv, true);
/* If perspective view or non-axis aligned view. */
if (winmat[3][3] == 0.0f || 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;
float zvec[3], campos[3];
negate_v3_v3(zvec, viewinv[2]);
copy_v3_v3(campos, 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 (((winmat[3][3] == 0.0f) && (campos[2] > 0.0f)) ||
((winmat[3][3] != 0.0f) && (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(draw_ctx->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 (winmat[3][3] == 0.0f) {
copy_v3_fl(data_.size, dist);
}
else {
float viewdist = 1.0f / min_ff(fabsf(winmat[0][0]), fabsf(winmat[1][1]));
copy_v3_fl(data_.size, viewdist * dist);
}
data_.distance = dist / 2.0f;
ED_view3d_grid_steps(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(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()
{
update_ubo();
grid_ps_.init();
grid_ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA);
grid_ps_.shader_set(OVERLAY_shader_grid());
grid_ps_.bind_ubo("grid_buf", &data_);
grid_ps_.bind_ubo("globalsBlock", &G_draw.block_ubo);
grid_ps_.bind_texture("depth_tx", &DRW_viewport_texture_list_get()->depth);
grid_ps_.push_constant("grid_flag", grid_flag_);
grid_ps_.push_constant("plane_axes", grid_axes);
grid_ps_.clear_color(float4(0.0f, 0.0f, 0.0f, 0.0f));
grid_ps_.draw(DRW_cache_grid_get());
}
void draw(Manager &manager, View &view)
{
manager.submit(grid_ps_, view);
}
};
} // namespace blender::draw::overlay

View File

@ -0,0 +1,41 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup overlay
*/
#include "overlay_instance.hh"
namespace blender::draw::overlay {
void Instance::init()
{
GPUTexture *viewport_depth_tx = DRW_viewport_texture_list_get()->depth;
GPUTexture *viewport_color_tx = DRW_viewport_texture_list_get()->color_overlay;
overlay_fb.ensure(GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(viewport_color_tx));
}
void Instance::begin_sync()
{
grid.begin_sync();
}
void Instance::object_sync(ObjectRef &ob_ref)
{
UNUSED_VARS(ob_ref);
}
void Instance::end_sync()
{
}
void Instance::draw(Manager &manager)
{
const DRWView *view_old = DRW_view_default_get();
View view("OverlayView", view_old);
GPU_framebuffer_bind(overlay_fb);
grid.draw(manager, view);
}
} // namespace blender::draw::overlay

View File

@ -0,0 +1,70 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup overlay
*/
#pragma once
#include "draw_manager.hh"
#include "overlay_grid.hh"
namespace blender::draw::overlay {
class ShaderCache {
Map<StringRefNull, std::array<GPUShader *, 2>> cache;
int clipping_enabled = 0;
};
class SceneResources {
ShaderCache shaders;
// UniformBuffer<ThemeColorData> theme_colors;
// Texture color_ramp = {"color_ramp"};
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 {
public:
ShaderCache shaders;
/* WORKAROUND: Legacy. Move to grid pass. */
GPUUniformBuf *grid_ubo = nullptr;
Framebuffer overlay_fb = {"overlay_fb"};
Grid grid;
~Instance()
{
DRW_UBO_FREE_SAFE(grid_ubo);
}
void init();
void begin_sync();
void object_sync(ObjectRef &ob_ref);
void end_sync();
void draw(Manager &manager);
};
} // namespace blender::draw::overlay

View File

@ -27,6 +27,10 @@ extern "C" {
/* Forward declarations */
struct ImBuf;
namespace blender::draw::overlay {
class Instance;
}
typedef struct OVERLAY_FramebufferList {
struct GPUFrameBuffer *overlay_default_fb;
struct GPUFrameBuffer *overlay_line_fb;
@ -428,10 +432,6 @@ typedef struct OVERLAY_StorageList {
struct OVERLAY_PrivateData *pd;
} OVERLAY_StorageList;
typedef struct OVERLAY_Instance {
GPUUniformBuf *grid_ubo;
} OVERLAY_Instance;
typedef struct OVERLAY_Data {
void *engine_type;
OVERLAY_FramebufferList *fbl;
@ -439,7 +439,7 @@ typedef struct OVERLAY_Data {
OVERLAY_PassList *psl;
OVERLAY_StorageList *stl;
OVERLAY_Instance *instance;
blender::draw::overlay::Instance *instance;
} OVERLAY_Data;
typedef struct OVERLAY_DupliData {

View File

@ -1,6 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#ifndef GPU_SHADER
# pragma once
# include "GPU_shader_shared_utils.h"
# include "DNA_action_types.h"
@ -12,6 +14,7 @@ extern "C" {
typedef enum OVERLAY_GridBits OVERLAY_GridBits;
# endif
typedef struct OVERLAY_GridData OVERLAY_GridData;
typedef struct ThemeColorData ThemeColorData;
#endif
/* TODO(fclem): Should eventually become OVERLAY_BackgroundType.
@ -84,6 +87,110 @@ BLI_STATIC_ASSERT(MOTIONPATH_VERT_SEL == (1 << 0), "Ensure value is sync");
BLI_STATIC_ASSERT(MOTIONPATH_VERT_KEY == (1 << 1), "Ensure value is sync");
#endif
struct ThemeColorData {
float4 color_wire;
float4 color_wire_edit;
float4 color_active;
float4 color_select;
float4 color_library_select;
float4 color_library;
float4 color_transform;
float4 color_light;
float4 color_speaker;
float4 color_camera;
float4 color_camera_path;
float4 color_empty;
float4 color_vertex;
float4 color_vertex_select;
float4 color_vertex_unreferenced;
float4 color_vertex_missing_data;
float4 color_edit_mesh_active;
float4 color_edge_select;
float4 color_edge_seam;
float4 color_edge_sharp;
float4 color_edge_crease;
float4 color_edge_bweight;
float4 color_edge_face_select;
float4 color_edge_freestyle;
float4 color_face;
float4 color_face_select;
float4 color_face_freestyle;
float4 color_gpencil_vertex;
float4 color_gpencil_vertex_select;
float4 color_normal;
float4 color_vnormal;
float4 color_lnormal;
float4 color_facedot;
float4 color_skinroot;
float4 color_deselect;
float4 color_outline;
float4 color_light_no_alpha;
float4 color_background;
float4 color_background_gradient;
float4 color_checker_primary;
float4 color_checker_secondary;
float4 color_clipping_border;
float4 color_edit_mesh_middle;
float4 color_handle_free;
float4 color_handle_auto;
float4 color_handle_vect;
float4 color_handle_align;
float4 color_handle_autoclamp;
float4 color_handle_sel_free;
float4 color_handle_sel_auto;
float4 color_handle_sel_vect;
float4 color_handle_sel_align;
float4 color_handle_sel_autoclamp;
float4 color_nurb_uline;
float4 color_nurb_vline;
float4 color_nurb_sel_uline;
float4 color_nurb_sel_vline;
float4 color_active_spline;
float4 color_bone_pose;
float4 color_bone_pose_active;
float4 color_bone_pose_active_unsel;
float4 color_bone_pose_constraint;
float4 color_bone_pose_ik;
float4 color_bone_pose_spline_ik;
float4 color_bone_pose_target;
float4 color_bone_solid;
float4 color_bone_locked;
float4 color_bone_active;
float4 color_bone_active_unsel;
float4 color_bone_select;
float4 color_bone_ik_line;
float4 color_bone_ik_line_no_target;
float4 color_bone_ik_line_spline;
float4 color_text;
float4 color_text_hi;
float4 color_bundle_solid;
float4 color_mball_radius;
float4 color_mball_radius_select;
float4 color_mball_stiffness;
float4 color_mball_stiffness_select;
float4 color_current_frame;
float4 color_grid;
float4 color_grid_emphasis;
float4 color_grid_axis_x;
float4 color_grid_axis_y;
float4 color_grid_axis_z;
float4 color_face_back;
float4 color_face_front;
float4 color_uv_shadow;
};
BLI_STATIC_ASSERT_ALIGN(ThemeColorData, 16)
#ifndef GPU_SHADER
# ifdef __cplusplus
}