Overlay-Next: Make grease pencil depth plane follow design

This move depth plane computation to right before drawing.
Making sync cycles not rely on view.
This commit is contained in:
Clément Foucault
2024-11-24 19:35:14 +01:00
parent 4587a87b6e
commit d8b6b2b1b7
5 changed files with 68 additions and 62 deletions

View File

@@ -52,6 +52,9 @@ class GreasePencil : Overlay {
{
enabled_ = state.is_space_v3d();
res.depth_planes.clear();
res.depth_planes_count = 0;
if (!enabled_) {
return;
}
@@ -226,6 +229,20 @@ class GreasePencil : Overlay {
}
}
static void compute_depth_planes(Manager &manager,
View &view,
Resources &res,
const State & /*state*/)
{
for (auto i : IndexRange(res.depth_planes_count)) {
GreasePencilDepthPlane &plane = res.depth_planes[i];
const float4x4 &object_to_world =
manager.matrix_buf.current().get_or_resize(plane.handle.resource_index()).model;
plane.plane = GreasePencil::depth_plane_get(object_to_world, plane.bounds, view);
std::cout << "plane.plane " << plane.plane << std::endl;
}
}
void draw_line(Framebuffer &framebuffer, Manager &manager, View &view) final
{
if (!enabled_) {
@@ -248,29 +265,8 @@ class GreasePencil : Overlay {
manager.submit(edit_grease_pencil_ps_, view_edit_cage);
}
struct ViewParameters {
bool is_perspective;
union {
/* Z axis if ortho or position if perspective. */
float3 z_axis;
float3 location;
};
ViewParameters() = default;
ViewParameters(bool is_perspective, const float4x4 &viewinv)
{
if (is_perspective) {
location = viewinv.location();
}
else {
z_axis = viewinv.z_axis();
}
}
};
static void draw_grease_pencil(PassMain::Sub &pass,
const ViewParameters &view,
static void draw_grease_pencil(Resources &res,
PassMain::Sub &pass,
const Scene *scene,
Object *ob,
ResourceHandle res_handle,
@@ -280,15 +276,25 @@ class GreasePencil : Overlay {
using namespace blender::ed::greasepencil;
::GreasePencil &grease_pencil = *static_cast<::GreasePencil *>(ob->data);
float4 plane = (grease_pencil.flag & GREASE_PENCIL_STROKE_ORDER_3D) ?
float4(0.0f) :
depth_plane_get(ob, view);
pass.push_constant("gpDepthPlane", plane);
const bool is_stroke_order_3d = (grease_pencil.flag & GREASE_PENCIL_STROKE_ORDER_3D) != 0;
if (is_stroke_order_3d) {
pass.push_constant("gpDepthPlane", float4(0.0f));
}
else {
int64_t index = res.depth_planes.append_and_get_index({});
res.depth_planes_count++;
GreasePencilDepthPlane &plane = res.depth_planes[index];
plane.bounds = BKE_object_boundbox_get(ob).value_or(blender::Bounds(float3(0)));
plane.handle = res_handle;
pass.push_constant("gpDepthPlane", &plane.plane);
}
int t_offset = 0;
const Vector<DrawingInfo> drawings = retrieve_visible_drawings(*scene, grease_pencil, true);
for (const DrawingInfo info : drawings) {
const bool is_stroke_order_3d = (grease_pencil.flag & GREASE_PENCIL_STROKE_ORDER_3D) != 0;
const float object_scale = mat4_to_scale(ob->object_to_world().ptr());
const float thickness_scale = bke::greasepencil::LEGACY_RADIUS_CONVERSION_FACTOR;
@@ -359,7 +365,9 @@ class GreasePencil : Overlay {
private:
/* Returns the normal plane in NDC space. */
static float4 depth_plane_get(const Object *ob, const ViewParameters &view)
static float4 depth_plane_get(const float4x4 &object_to_world,
const blender::Bounds<float3> &bounds,
const View &view)
{
using namespace blender::math;
@@ -368,19 +376,17 @@ class GreasePencil : Overlay {
* strokes not aligned with the object axes. Maybe we could try to
* compute the minimum axis of all strokes. But this would be more
* computationally heavy and should go into the GPData evaluation. */
const std::optional<blender::Bounds<float3>> bounds = BKE_object_boundbox_get(ob).value_or(
blender::Bounds(float3(0)));
float3 center = midpoint(bounds->min, bounds->max);
float3 size = (bounds->max - bounds->min) * 0.5f;
float3 center = bounds.center();
float3 size = bounds.size();
/* Avoid division by 0.0 later. */
size += 1e-8f;
/* Convert Bbox unit space to object space. */
float4x4 bbox_to_object = from_loc_scale<float4x4>(center, size);
float4x4 bbox_to_world = ob->object_to_world() * bbox_to_object;
float4x4 bbox_to_object = from_loc_scale<float4x4>(center, size * 0.5f);
float4x4 bbox_to_world = object_to_world * bbox_to_object;
float3 bbox_center = bbox_to_world.location();
float3 view_vector = (view.is_perspective) ? view.location - bbox_center : view.z_axis;
float3 view_vector = (view.is_persp()) ? (view.location() - bbox_center) : view.forward();
float3x3 world_to_bbox = invert(float3x3(bbox_to_world));

View File

@@ -386,6 +386,8 @@ void Instance::draw(Manager &manager)
pre_draw(regular);
pre_draw(infront);
outline.pre_draw_ex(manager, view, resources, state);
GreasePencil::compute_depth_planes(manager, view, resources, state);
}
resources.depth_tx.wrap(DRW_viewport_texture_list_get()->depth);

View File

@@ -37,8 +37,6 @@ class Outline : Overlay {
Framebuffer prepass_fb_ = {"outline.prepass_fb"};
overlay::GreasePencil::ViewParameters grease_pencil_view;
Vector<FlatObjectRef> flat_objects_;
PassMain outline_prepass_flat_ps_ = {"PrepassFlat"};
@@ -55,14 +53,6 @@ class Outline : Overlay {
return;
}
{
/* TODO(fclem): This is against design. We should not sync depending on view position.
* Eventually, we should do this in a compute shader prepass. */
float4x4 viewinv;
DRW_view_viewmat_get(nullptr, viewinv.ptr(), true);
grease_pencil_view = {DRW_view_is_persp_get(nullptr), viewinv};
}
const float outline_width = UI_GetThemeValuef(TH_OUTLINE_WIDTH);
const bool do_smooth_lines = (U.gpu_flag & USER_GPU_FLAG_OVERLAY_SMOOTH_WIRE) != 0;
const bool do_expand = (U.pixelsize > 1.0) || (outline_width > 2.0f);
@@ -133,7 +123,7 @@ class Outline : Overlay {
void object_sync(Manager &manager,
const ObjectRef &ob_ref,
Resources & /*res*/,
Resources &res,
const State &state) final
{
if (!enabled_) {
@@ -155,8 +145,8 @@ class Outline : Overlay {
prepass_curves_ps_->draw(geom, manager.unique_handle(ob_ref));
break;
case OB_GREASE_PENCIL:
GreasePencil::draw_grease_pencil(*prepass_gpencil_ps_,
grease_pencil_view,
GreasePencil::draw_grease_pencil(res,
*prepass_gpencil_ps_,
state.scene,
ob_ref.object,
manager.unique_handle(ob_ref));

View File

@@ -36,8 +36,6 @@ class Prepass : Overlay {
bool use_material_slot_selection_ = false;
overlay::GreasePencil::ViewParameters grease_pencil_view;
public:
void begin_sync(Resources &res, const State &state) final
{
@@ -52,14 +50,6 @@ class Prepass : Overlay {
return;
}
{
/* TODO(fclem): This is against design. We should not sync depending on view position.
* Eventually, we should do this in a compute shader prepass. */
float4x4 viewinv;
DRW_view_viewmat_get(nullptr, viewinv.ptr(), true);
grease_pencil_view = {DRW_view_is_persp_get(nullptr), viewinv};
}
use_material_slot_selection_ = state.is_material_select;
const View3DShading &shading = state.v3d->shading;
@@ -226,8 +216,8 @@ class Prepass : Overlay {
* The grease pencil engine already renders it properly. */
return;
}
GreasePencil::draw_grease_pencil(*grease_pencil_ps_,
grease_pencil_view,
GreasePencil::draw_grease_pencil(res,
*grease_pencil_ps_,
state.scene,
ob_ref.object,
manager.unique_handle(ob_ref),

View File

@@ -409,6 +409,16 @@ class ShaderModule {
FunctionRef<void(gpu::shader::ShaderCreateInfo &info)> patch);
};
struct GreasePencilDepthPlane {
/* Plane data to reference as push constant.
* Will be computed just before drawing. */
float4 plane;
/* Center and size of the bounding box of the Grease Pencil object. */
Bounds<float3> bounds;
/* Gpencil object resource handle. */
ResourceHandle handle;
};
struct Resources : public select::SelectMap {
ShaderModule &shaders;
@@ -451,6 +461,14 @@ struct Resources : public select::SelectMap {
* texture is not available or not needed. */
Texture dummy_depth_tx = {"dummy_depth_tx"};
/* Global vector for all grease pencil depth planes.
* Managed by the grease pencil overlay module.
* This is to avoid passing the grease pencil overlay class to other overlay and
* keep draw_grease_pencil as a static function.
* Memory is reference, so we have to use a container with fixed memory. */
detail::SubPassVector<GreasePencilDepthPlane, 16> depth_planes;
int64_t depth_planes_count = 0;
/** TODO(fclem): Copy of G_data.block that should become theme colors only and managed by the
* engine. */
GlobalsUboStorage theme_settings;