GPv3: Add option to disable masks in viewlayer #120561
|
@ -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"
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue