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.
6 changed files with 248 additions and 8 deletions
Showing only changes of commit 2abc4d0538 - Show all commits

View File

@ -74,7 +74,6 @@ class Background {
}
bg_ps_.init();
bg_ps_.clear_color(float4());
bg_ps_.state_set(pass_state);
bg_ps_.shader_set(OVERLAY_shader_background());
bg_ps_.bind_ubo("globalsBlock", &res.globals_buf);
@ -95,9 +94,7 @@ class Background {
void draw(Resources &res, Manager &manager)
{
if (DRW_state_is_fbo()) {
GPU_framebuffer_bind(res.overlay_color_only_fb);
}
GPU_framebuffer_bind(res.overlay_color_only_fb);
manager.submit(bg_ps_);
}
};

View File

@ -12,6 +12,7 @@ namespace blender::draw::overlay {
void Instance::init()
{
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);
@ -19,6 +20,7 @@ void Instance::init()
const DRWContextState *ctx = DRW_context_state_get();
state.depsgraph = ctx->depsgraph;
state.view_layer = ctx->view_layer;
state.scene = ctx->scene;
state.v3d = ctx->v3d;
state.rv3d = ctx->rv3d;
@ -64,16 +66,54 @@ void Instance::begin_sync()
View view("OverlayView", view_legacy);
background.begin_sync(resources, state);
metaballs.begin_sync();
grid.begin_sync(resources, state, view);
}
void Instance::object_sync(ObjectRef &ob_ref)
{
UNUSED_VARS(ob_ref);
const bool in_edit_mode = object_is_edit_mode(ob_ref.object);
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_ARMATURE:
break;
case OB_MBALL:
if (!in_edit_mode) {
metaballs.object_sync(ob_ref, resources, state);
}
break;
case OB_GPENCIL:
break;
}
}
}
void Instance::end_sync()
{
metaballs.end_sync(resources, state);
}
void Instance::draw(Manager &manager)
@ -84,18 +124,32 @@ void Instance::draw(Manager &manager)
return;
}
int2 render_size = int2(resources.depth_tx.size());
const DRWView *view_legacy = DRW_view_default_get();
View view("OverlayView", view_legacy);
resources.line_tx.acquire(int2(resources.depth_tx.size()), GPU_RGBA8);
resources.line_tx.acquire(render_size, GPU_RGBA8);
resources.overlay_color_only_fb.ensure(GPU_ATTACHMENT_NONE,
GPU_ATTACHMENT_TEXTURE(resources.color_overlay_tx));
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);
@ -103,11 +157,17 @@ void Instance::draw(Manager &manager)
GPU_framebuffer_clear_color(resources.overlay_color_only_fb, clear_color);
background.draw(resources, manager);
metaballs.draw(resources, manager, view);
grid.draw(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();
}
} // namespace blender::draw::overlay

View File

@ -10,6 +10,7 @@
#include "overlay_background.hh"
#include "overlay_grid.hh"
#include "overlay_metaball.hh"
namespace blender::draw::overlay {
@ -58,6 +59,7 @@ class Instance {
/** Overlay types. */
Background background;
Metaballs metaballs;
Grid grid;
~Instance()
@ -70,6 +72,37 @@ class Instance {
void object_sync(ObjectRef &ob_ref);
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;
}
};
} // namespace blender::draw::overlay

View File

@ -0,0 +1,132 @@
/* 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 {
class Metaballs {
private:
PassSimple metaball_ps_ = {"MetaBalls"};
PassSimple metaball_in_front_ps_ = {"MetaBalls_In_front"};
ArmatureSphereBuf data_buf_ = {"metaball_data_buf"};
ArmatureSphereBuf data_in_front_buf_ = {"metaball_data_buf"};
public:
void begin_sync()
{
data_buf_.clear();
data_in_front_buf_.clear();
}
void metaball_instance_data_set(BoneInstanceData *data,
Object *ob,
const float *pos,
const float radius,
const float color[4])
{
/* Bone point radius is 0.05. Compensate for that. */
mul_v3_v3fl(data->mat[0], ob->obmat[0], radius / 0.05f);
mul_v3_v3fl(data->mat[1], ob->obmat[1], radius / 0.05f);
mul_v3_v3fl(data->mat[2], ob->obmat[2], radius / 0.05f);
mul_v3_m4v3(data->mat[3], ob->obmat, pos);
/* WATCH: Reminder, alpha is wire-size. */
OVERLAY_bone_instance_data_set_color(data, color);
}
void edit_object_sync(const ObjectRef &ob_ref, const Resources &res)
{
ArmatureSphereBuf &data_buf = (ob_ref.object->dtx & OB_DRAW_IN_FRONT) != 0 ?
data_in_front_buf_ :
data_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);
BoneInstanceData instdata;
color = (is_selected && is_scale_radius) ? col_radius_select : col_radius;
metaball_instance_data_set(&instdata, ob_ref.object, &ml->x, ml->rad, color);
data_buf.append(*reinterpret_cast<float4x4 *>(&instdata));
color = (is_selected && !is_scale_radius) ? col_stiffness_select : col_stiffness;
metaball_instance_data_set(&instdata, ob_ref.object, &ml->x, stiffness_radius, color);
data_buf.append(*reinterpret_cast<float4x4 *>(&instdata));
}
}
void object_sync(const ObjectRef &ob_ref, const Resources &res, const State &state)
{
ArmatureSphereBuf &data_buf = (ob_ref.object->dtx & OB_DRAW_IN_FRONT) != 0 ?
data_in_front_buf_ :
data_buf_;
MetaBall *mb = static_cast<MetaBall *>(ob_ref.object->data);
float *color;
/* TODO(fclem): Remove DRW global usage. */
UNUSED_VARS(res);
DRW_object_wire_theme_get(ob_ref.object, state.view_layer, &color);
LISTBASE_FOREACH (MetaElem *, ml, &mb->elems) {
/* Draw radius only. */
BoneInstanceData instdata;
metaball_instance_data_set(&instdata, ob_ref.object, &ml->x, ml->rad, color);
data_buf.append(*reinterpret_cast<float4x4 *>(&instdata));
}
}
void end_sync(Resources &res, const State &state)
{
auto init_pass = [&](PassSimple &pass, ArmatureSphereBuf &data_buf) {
data_buf.push_update();
pass.init();
pass.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
state.clipping_state);
pass.shader_set(OVERLAY_shader_armature_sphere(true));
pass.bind_ubo("globalsBlock", &res.globals_buf);
pass.bind_ssbo("data_buf", &data_buf);
pass.draw(DRW_cache_bone_point_wire_outline_get(), data_buf.size());
};
init_pass(metaball_ps_, data_buf_);
init_pass(metaball_in_front_ps_, data_in_front_buf_);
}
void draw(Resources &res, Manager &manager, View &view)
{
GPU_framebuffer_bind(res.overlay_line_fb);
manager.submit(metaball_ps_, view);
}
void draw_in_front(Resources &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

View File

@ -33,6 +33,7 @@ class Instance;
struct State {
Depsgraph *depsgraph;
ViewLayer *view_layer;
Scene *scene;
View3D *v3d;
RegionView3D *rv3d;
@ -53,9 +54,11 @@ struct State {
};
using blender::draw::Framebuffer;
using blender::draw::StorageVectorBuffer;
using blender::draw::Texture;
using blender::draw::TextureFromPool;
using blender::draw::TextureRef;
using ArmatureSphereBuf = StorageVectorBuffer<float4x4>;
struct Resources {
Framebuffer overlay_fb = {"overlay_fb"};
@ -65,6 +68,7 @@ struct Resources {
Framebuffer overlay_line_in_front_fb = {"overlay_line_in_front_fb"};
TextureFromPool line_tx = {"line_tx"};
TextureFromPool depth_in_front_alloc_tx = {"overlay_depth_in_front_tx"};
/** TODO(fclem): Copy of G_data.block that should become theme colors only and managed by the
* engine. */
@ -72,6 +76,7 @@ struct Resources {
/* References, not owned. */
GPUUniformBuf *globals_buf;
TextureRef depth_tx;
TextureRef depth_in_front_tx;
TextureRef color_overlay_tx;
TextureRef color_render_tx;
};

View File

@ -11,6 +11,8 @@
#include "UI_resources.h"
#include "gpu_shader_create_info.hh"
#include "overlay_private.hh"
typedef struct OVERLAY_Shaders {
@ -182,6 +184,17 @@ GPUShader *OVERLAY_shader_armature_sphere(bool use_outline)
const DRWContextState *draw_ctx = DRW_context_state_get();
OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
if (use_outline && !sh_data->armature_sphere_outline) {
using namespace blender::gpu::shader;
ShaderCreateInfo &info = const_cast<ShaderCreateInfo &>(
*reinterpret_cast<const ShaderCreateInfo *>(
GPU_shader_create_info_get("overlay_armature_sphere_outline")));
if (U.experimental.enable_overlay_next) {
info.storage_buf(0, Qualifier::READ, "mat4", "data_buf[]");
info.define("inst_obmat", "data_buf[gl_InstanceID]");
info.vertex_inputs_.pop_last();
}
sh_data->armature_sphere_outline = GPU_shader_create_from_info_name(
draw_ctx->sh_cfg ? "overlay_armature_sphere_outline_clipped" :
"overlay_armature_sphere_outline");