GPv3: Add option to disable masks in viewlayer #120561

Merged
Falk David merged 3 commits from filedescriptor/blender:gpv3-disable-masks-in-viewlayer into main 2024-04-12 14:44:24 +02:00
7 changed files with 125 additions and 32 deletions

View File

@ -233,6 +233,11 @@ class DATA_PT_grease_pencil_layer_relations(LayerDataButtonsPanel, Panel):
col = layout.row(align=True)
col.prop_search(layer, "viewlayer_render", context.scene, "view_layers", text="View Layer")
col = layout.row(align=True)
# Only enable this property when a view layer is selected.
col.enabled = bool(layer.viewlayer_render)
col.prop(layer, "use_viewlayer_masks")
class DATA_PT_grease_pencil_onion_skinning(DataButtonsPanel, Panel):
bl_label = "Onion Skinning"

View File

@ -613,6 +613,9 @@ void legacy_gpencil_to_grease_pencil(Main &bmain, GreasePencil &grease_pencil, b
copy_v3_v3(new_layer.scale, gpl->scale);
new_layer.set_view_layer_name(gpl->viewlayername);
SET_FLAG_FROM_TEST(new_layer.base.flag,
(gpl->flag & GP_LAYER_DISABLE_MASKS_IN_VIEWLAYER) != 0,
GP_LAYER_TREE_NODE_DISABLE_MASKS_IN_VIEWLAYER);
/* Convert the layer masks. */
LISTBASE_FOREACH (bGPDlayer_Mask *, mask, &gpl->mask_layers) {

View File

@ -517,6 +517,7 @@ GPENCIL_tLayer *grease_pencil_layer_cache_add(GPENCIL_PrivateData *pd,
const Object *ob,
const blender::bke::greasepencil::Layer &layer,
const int onion_id,
const bool is_used_as_mask,
GPENCIL_tObject *tgp_ob)
{
@ -532,17 +533,22 @@ GPENCIL_tLayer *grease_pencil_layer_cache_add(GPENCIL_PrivateData *pd,
const bool is_viewlayer_render = pd->is_render && !layer.view_layer_name().is_empty() &&
STREQ(pd->view_layer->name, layer.view_layer_name().c_str());
const bool disable_masks_render = is_viewlayer_render &&
(layer.base.flag & GP_LAYER_DISABLE_MASKS_IN_VIEWLAYER) != 0;
(layer.base.flag &
GP_LAYER_TREE_NODE_DISABLE_MASKS_IN_VIEWLAYER) != 0;
bool is_masked = !disable_masks_render && layer.use_masks() &&
!BLI_listbase_is_empty(&layer.masks);
float vert_col_opacity = (override_vertcol) ?
(is_vert_col_mode ? pd->vertex_paint_opacity : 0.0f) :
pd->vertex_paint_opacity;
const float vert_col_opacity = (override_vertcol) ?
(is_vert_col_mode ? pd->vertex_paint_opacity : 0.0f) :
pd->vertex_paint_opacity;
/* Negate thickness sign to tag that strokes are in screen space.
* Convert to world units (by default, 1 meter = 1000 pixels). */
float thickness_scale = (is_screenspace) ? -1.0f : 1.0f / 1000.0f;
float layer_opacity = grease_pencil_layer_final_opacity_get(pd, ob, grease_pencil, layer);
const float thickness_scale = (is_screenspace) ? -1.0f : 1.0f / 1000.0f;
/* If the layer is used as a mask (but is otherwise not visible in the render), render it with a
* opacity of 0 so that it can still mask other layers. */
const float layer_opacity = !is_used_as_mask ? grease_pencil_layer_final_opacity_get(
pd, ob, grease_pencil, layer) :
0.0f;
float layer_alpha = pd->xray_alpha;
const float4 layer_tint = grease_pencil_layer_final_tint_and_alpha_get(

View File

@ -339,6 +339,7 @@ GPENCIL_tLayer *grease_pencil_layer_cache_add(GPENCIL_PrivateData *pd,
const Object *ob,
const blender::bke::greasepencil::Layer &layer,
int onion_id,
bool is_used_as_mask,
GPENCIL_tObject *tgp_ob);
/**
* Creates a linked list of material pool containing all materials assigned for a given object.

View File

@ -602,6 +602,53 @@ static void gpencil_sbuffer_cache_populate_fast(GPENCIL_Data *vedata, gpIterPopu
iter->pd->scene_depth_tx = depth_texture;
}
/* Check if the passed in layer is used by any other layer as a mask (in the viewlayer). */
static bool is_used_as_layer_mask_in_viewlayer(const GreasePencil &grease_pencil,
const blender::bke::greasepencil::Layer &mask_layer,
const ViewLayer &view_layer)
{
using namespace blender::bke::greasepencil;
for (const Layer *layer : grease_pencil.layers()) {
if (layer->view_layer_name().is_empty() ||
!STREQ(view_layer.name, layer->view_layer_name().c_str()))
{
continue;
}
if ((layer->base.flag & GP_LAYER_TREE_NODE_DISABLE_MASKS_IN_VIEWLAYER) != 0) {
continue;
}
LISTBASE_FOREACH (GreasePencilLayerMask *, mask, &layer->masks) {
if (STREQ(mask->layer_name, mask_layer.name().c_str())) {
return true;
}
}
}
return false;
}
/* Returns true if this layer should be rendered (as part of the viewlayer). */
static bool use_layer_in_render(const GreasePencil &grease_pencil,
const blender::bke::greasepencil::Layer &layer,
const ViewLayer &view_layer,
bool &r_is_used_as_mask)
{
if (!layer.view_layer_name().is_empty() &&
!STREQ(view_layer.name, layer.view_layer_name().c_str()))
{
/* Do not skip layers that are masks when rendering the viewlayer so that it can still be used
* to clip/mask other layers. */
if (is_used_as_layer_mask_in_viewlayer(grease_pencil, layer, view_layer)) {
r_is_used_as_mask = true;
}
else {
return false;
}
}
return true;
}
static GPENCIL_tObject *grease_pencil_object_cache_populate(GPENCIL_PrivateData *pd,
GPENCIL_TextureList *txl,
Object *ob)
@ -668,10 +715,48 @@ static GPENCIL_tObject *grease_pencil_object_cache_populate(GPENCIL_PrivateData
for (const DrawingInfo info : drawings) {
const Layer &layer = *layers[info.layer_index];
const bke::CurvesGeometry &curves = info.drawing.strokes();
const OffsetIndices<int> points_by_curve = curves.points_by_curve();
const bke::AttributeAccessor attributes = curves.attributes();
const VArray<bool> cyclic = *attributes.lookup_or_default<bool>(
"cyclic", bke::AttrDomain::Curve, false);
IndexMaskMemory memory;
const IndexMask visible_strokes = ed::greasepencil::retrieve_visible_strokes(
*ob, info.drawing, memory);
/* Precompute all the triangle and vertex counts.
* In case the drawing should not be rendered, we need to compute the offset where the next
* drawing begins. */
Array<int> num_triangles_per_stroke(visible_strokes.size());
Array<int> num_vertices_per_stroke(visible_strokes.size());
int total_num_triangles = 0;
int total_num_vertices = 0;
visible_strokes.foreach_index([&](const int stroke_i) {
const IndexRange points = points_by_curve[stroke_i];
const int num_stroke_triangles = (points.size() >= 3) ? (points.size() - 2) : 0;
const int num_stroke_vertices = (points.size() +
int(cyclic[stroke_i] && (points.size() >= 3)));
num_triangles_per_stroke[stroke_i] = num_stroke_triangles;
num_vertices_per_stroke[stroke_i] = num_stroke_vertices;
total_num_triangles += num_stroke_triangles;
total_num_vertices += num_stroke_vertices;
});
bool is_layer_used_as_mask = false;
const bool show_drawing_in_render = use_layer_in_render(
grease_pencil, layer, *pd->view_layer, is_layer_used_as_mask);
if (!show_drawing_in_render) {
/* Skip over the entire drawing. */
t_offset += total_num_triangles;
t_offset += total_num_vertices * 2;
continue;
}
drawcall_flush();
GPENCIL_tLayer *tgp_layer = grease_pencil_layer_cache_add(
pd, ob, layer, info.onion_id, tgp_ob);
pd, ob, layer, info.onion_id, is_layer_used_as_mask, tgp_ob);
const bool use_lights = pd->use_lighting &&
((layer.base.flag & GP_LAYER_TREE_NODE_USE_LIGHTS) != 0) &&
@ -693,17 +778,13 @@ static GPENCIL_tObject *grease_pencil_object_cache_populate(GPENCIL_PrivateData
DRW_shgroup_uniform_float_copy(grp, "gpStrokeIndexOffset", 0.0f);
DRW_shgroup_uniform_vec2_copy(grp, "viewportSize", DRW_viewport_size_get());
const bke::CurvesGeometry &curves = info.drawing.strokes();
const OffsetIndices<int> points_by_curve = curves.points_by_curve();
const bke::AttributeAccessor attributes = curves.attributes();
const VArray<int> stroke_materials = *attributes.lookup_or_default<int>(
"material_index", bke::AttrDomain::Curve, 0);
const VArray<bool> cyclic = *attributes.lookup_or_default<bool>(
"cyclic", bke::AttrDomain::Curve, false);
IndexMaskMemory memory;
const IndexMask visible_strokes = ed::greasepencil::retrieve_visible_strokes(
*ob, info.drawing, memory);
const bool only_lines =
!ELEM(ob->mode, OB_MODE_PAINT_GREASE_PENCIL, OB_MODE_WEIGHT_PAINT, OB_MODE_VERTEX_PAINT) &&
info.frame_number != pd->cfra && pd->use_multiedit_lines_only;
const bool is_onion = info.onion_id != 0;
visible_strokes.foreach_index([&](const int stroke_i) {
const IndexRange points = points_by_curve[stroke_i];
@ -715,25 +796,14 @@ static GPENCIL_tObject *grease_pencil_object_cache_populate(GPENCIL_PrivateData
const bool show_fill = (points.size() >= 3) &&
((gp_style->flag & GP_MATERIAL_FILL_SHOW) != 0) &&
(!pd->simplify_fill);
const bool only_lines = !ELEM(ob->mode,
OB_MODE_PAINT_GREASE_PENCIL,
OB_MODE_WEIGHT_PAINT,
OB_MODE_VERTEX_PAINT) &&
info.frame_number != pd->cfra && pd->use_multiedit_lines_only;
const bool is_onion = info.onion_id != 0;
const bool hide_onion = is_onion && ((gp_style->flag & GP_MATERIAL_HIDE_ONIONSKIN) != 0 ||
(!do_onion && !do_multi_frame));
const int num_stroke_triangles = (points.size() >= 3) ? (points.size() - 2) : 0;
const int num_stroke_vertices = (points.size() +
int(cyclic[stroke_i] && (points.size() >= 3)));
const bool skip_stroke = hide_material || (!show_stroke && !show_fill) ||
(only_lines && !is_onion) || hide_onion;
if (skip_stroke) {
t_offset += num_stroke_triangles;
t_offset += num_stroke_vertices * 2;
t_offset += num_triangles_per_stroke[stroke_i];
t_offset += num_vertices_per_stroke[stroke_i] * 2;
return;
}
@ -779,19 +849,19 @@ static GPENCIL_tObject *grease_pencil_object_cache_populate(GPENCIL_PrivateData
if (show_fill) {
const int v_first = t_offset * 3;
const int v_count = num_stroke_triangles * 3;
const int v_count = num_triangles_per_stroke[stroke_i] * 3;
drawcall_add(geom, v_first, v_count);
}
t_offset += num_stroke_triangles;
t_offset += num_triangles_per_stroke[stroke_i];
if (show_stroke) {
const int v_first = t_offset * 3;
const int v_count = num_stroke_vertices * 2 * 3;
const int v_count = num_vertices_per_stroke[stroke_i] * 2 * 3;
drawcall_add(geom, v_first, v_count);
}
t_offset += num_stroke_vertices * 2;
t_offset += num_vertices_per_stroke[stroke_i] * 2;
});
}

View File

@ -241,6 +241,7 @@ typedef enum GreasePencilLayerTreeNodeFlag {
GP_LAYER_TREE_NODE_HIDE_ONION_SKINNING = (1 << 5),
GP_LAYER_TREE_NODE_EXPANDED = (1 << 6),
GP_LAYER_TREE_NODE_HIDE_MASKS = (1 << 7),
GP_LAYER_TREE_NODE_DISABLE_MASKS_IN_VIEWLAYER = (1 << 8),
} GreasePencilLayerTreeNodeFlag;
struct GreasePencilLayerTreeGroup;

View File

@ -475,6 +475,13 @@ static void rna_def_grease_pencil_layer(BlenderRNA *brna)
"ViewLayer",
"Only include Layer in this View Layer render output (leave blank to include always)");
prop = RNA_def_property(srna, "use_viewlayer_masks", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(
prop, "GreasePencilLayerTreeNode", "flag", GP_LAYER_TREE_NODE_DISABLE_MASKS_IN_VIEWLAYER);
RNA_def_property_ui_text(
prop, "Use Masks in Render", "Include the mask layers when rendering the view-layer");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_grease_pencil_update");
prop = RNA_def_property(srna, "blend_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, nullptr, "blend_mode");
RNA_def_property_enum_items(prop, rna_enum_layer_blend_modes_items);