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:
@@ -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));
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user