Blender V4.3
gpencil_cache_utils.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2017 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "DRW_engine.hh"
10#include "DRW_render.hh"
11
12#include "ED_gpencil_legacy.hh"
13#include "ED_view3d.hh"
14
16#include "DNA_view3d_types.h"
17
19#include "BKE_gpencil_legacy.h"
20#include "BKE_grease_pencil.hh"
21#include "BKE_lib_id.hh"
22#include "BKE_object.hh"
23
24#include "BLI_hash.h"
25#include "BLI_link_utils.h"
26#include "BLI_math_color.h"
27#include "BLI_math_vector.hh"
28#include "BLI_memblock.h"
29
30#include "gpencil_engine.h"
31
32#include "draw_cache_impl.hh"
33
34#include "DEG_depsgraph.hh"
35
36#include "UI_resources.hh"
37
38/* -------------------------------------------------------------------- */
43 Object *ob,
44 const bool is_stroke_order_3d,
46{
47 using namespace blender;
49
50 tgp_ob->layers.first = tgp_ob->layers.last = nullptr;
51 tgp_ob->vfx.first = tgp_ob->vfx.last = nullptr;
52 tgp_ob->camera_z = dot_v3v3(pd->camera_z_axis, ob->object_to_world().location());
53 tgp_ob->is_drawmode3d = is_stroke_order_3d || pd->draw_depth_only;
54 tgp_ob->object_scale = mat4_to_scale(ob->object_to_world().ptr());
55
56 /* Check if any material with holdout flag enabled. */
57 tgp_ob->do_mat_holdout = false;
58 const int tot_materials = BKE_object_material_count_eval(ob);
59 for (int i = 0; i < tot_materials; i++) {
61 if (((gp_style != nullptr) && (gp_style->flag & GP_MATERIAL_IS_STROKE_HOLDOUT)) ||
63 {
64 tgp_ob->do_mat_holdout = true;
65 break;
66 }
67 }
68
69 /* Find the normal most likely to represent the gpObject. */
70 /* TODO: This does not work quite well if you use
71 * strokes not aligned with the object axes. Maybe we could try to
72 * compute the minimum axis of all strokes. But this would be more
73 * computationally heavy and should go into the GPData evaluation. */
74 float3 size = (bounds.max - bounds.min) * 0.5f;
75 float3 center = math::midpoint(bounds.min, bounds.max);
76 /* Convert bbox to matrix */
77 float mat[4][4];
78 unit_m4(mat);
79 copy_v3_v3(mat[3], center);
80 /* Avoid division by 0.0 later. */
81 add_v3_fl(size, 1e-8f);
82 rescale_m4(mat, size);
83 /* BBox space to World. */
84 mul_m4_m4m4(mat, ob->object_to_world().ptr(), mat);
85 if (DRW_view_is_persp_get(nullptr)) {
86 /* BBox center to camera vector. */
87 sub_v3_v3v3(tgp_ob->plane_normal, pd->camera_pos, mat[3]);
88 }
89 else {
91 }
92 /* World to BBox space. */
93 invert_m4(mat);
94 /* Normalize the vector in BBox space. */
95 mul_mat3_m4_v3(mat, tgp_ob->plane_normal);
97
98 transpose_m4(mat);
99 /* mat is now a "normal" matrix which will transform
100 * BBox space normal to world space. */
101 mul_mat3_m4_v3(mat, tgp_ob->plane_normal);
102 normalize_v3(tgp_ob->plane_normal);
103
104 /* Define a matrix that will be used to render a triangle to merge the depth of the rendered
105 * gpencil object with the rest of the scene. */
106 unit_m4(tgp_ob->plane_mat);
107 copy_v3_v3(tgp_ob->plane_mat[2], tgp_ob->plane_normal);
108 orthogonalize_m4(tgp_ob->plane_mat, 2);
109 mul_mat3_m4_v3(ob->object_to_world().ptr(), size);
110 float radius = len_v3(size);
111 mul_m4_v3(ob->object_to_world().ptr(), center);
112 rescale_m4(tgp_ob->plane_mat, blender::float3{radius, radius, radius});
113 copy_v3_v3(tgp_ob->plane_mat[3], center);
114
115 /* Add to corresponding list if is in front. */
116 if (ob->dtx & OB_DRAW_IN_FRONT) {
118 }
119 else {
120 BLI_LINKS_APPEND(&pd->tobjects, tgp_ob);
121 }
122
123 return tgp_ob;
124}
125
126#define SORT_IMPL_LINKTYPE GPENCIL_tObject
127
128#define SORT_IMPL_FUNC gpencil_tobject_sort_fn_r
130#undef SORT_IMPL_FUNC
131
132#undef SORT_IMPL_LINKTYPE
133
134static int gpencil_tobject_dist_sort(const void *a, const void *b)
135{
136 const GPENCIL_tObject *ob_a = (const GPENCIL_tObject *)a;
137 const GPENCIL_tObject *ob_b = (const GPENCIL_tObject *)b;
138 /* Reminder, camera_z is negative in front of the camera. */
139 if (ob_a->camera_z > ob_b->camera_z) {
140 return 1;
141 }
142 if (ob_a->camera_z < ob_b->camera_z) {
143 return -1;
144 }
145
146 return 0;
147}
148
150{
151 /* Sort object by distance to the camera. */
152 if (pd->tobjects.first) {
153 pd->tobjects.first = gpencil_tobject_sort_fn_r(pd->tobjects.first, gpencil_tobject_dist_sort);
154 /* Relink last pointer. */
155 while (pd->tobjects.last->next) {
156 pd->tobjects.last = pd->tobjects.last->next;
157 }
158 }
159 if (pd->tobjects_infront.first) {
160 pd->tobjects_infront.first = gpencil_tobject_sort_fn_r(pd->tobjects_infront.first,
162 /* Relink last pointer. */
163 while (pd->tobjects_infront.last->next) {
165 }
166 }
167
168 /* Join both lists, adding in front. */
169 if (pd->tobjects_infront.first != nullptr) {
170 if (pd->tobjects.last != nullptr) {
173 }
174 else {
175 /* Only in front objects. */
178 }
179 }
180}
181
184/* -------------------------------------------------------------------- */
189 const Object *ob,
190 const bGPDlayer *gpl)
191{
192 const bool is_obact = ((pd->obact) && (pd->obact == ob));
193 const bool is_fade = ((pd->fade_layer_opacity > -1.0f) && (is_obact) &&
194 ((gpl->flag & GP_LAYER_ACTIVE) == 0));
195
196 /* Defines layer opacity. For active object depends of layer opacity factor, and
197 * for no active object, depends if the fade grease pencil objects option is enabled. */
198 if (!pd->is_render) {
199 if (is_obact && is_fade) {
200 return gpl->opacity * pd->fade_layer_opacity;
201 }
202 if (!is_obact && (pd->fade_gp_object_opacity > -1.0f)) {
203 return gpl->opacity * pd->fade_gp_object_opacity;
204 }
205 }
206 return gpl->opacity;
207}
208
210 const Object *ob,
211 const GreasePencil &grease_pencil,
213{
214 const bool is_obact = ((pd->obact) && (pd->obact == ob));
215 const bool is_fade = (pd->fade_layer_opacity > -1.0f) && (is_obact) &&
216 !grease_pencil.is_layer_active(&layer);
217
218 /* Defines layer opacity. For active object depends of layer opacity factor, and
219 * for no active object, depends if the fade grease pencil objects option is enabled. */
220 if (!pd->is_render) {
221 if (is_obact && is_fade) {
222 return layer.opacity * pd->fade_layer_opacity;
223 }
224 if (!is_obact && (pd->fade_gp_object_opacity > -1.0f)) {
225 return layer.opacity * pd->fade_gp_object_opacity;
226 }
227 }
228 return layer.opacity;
229}
230
232 const bGPdata *gpd,
233 const bGPDlayer *gpl,
234 const bGPDframe *gpf,
235 float r_tint[4],
236 float *r_alpha)
237{
238 const bool use_onion = (gpf != nullptr) && (gpf->runtime.onion_id != 0.0f);
239 if (use_onion) {
240 const bool use_onion_custom_col = (gpd->onion_flag & GP_ONION_GHOST_PREVCOL) != 0;
241 const bool use_onion_fade = (gpd->onion_flag & GP_ONION_FADE) != 0;
242 const bool use_next_col = gpf->runtime.onion_id > 0.0f;
243
244 float color_next[3];
245 float color_prev[3];
246 if (use_onion_custom_col) {
247 copy_v3_v3(color_next, gpd->gcolor_next);
248 copy_v3_v3(color_prev, gpd->gcolor_prev);
249 }
250 else {
253 }
254 const float *onion_col_custom = use_next_col ? color_next : color_prev;
255
256 copy_v4_fl4(r_tint, UNPACK3(onion_col_custom), 1.0f);
257
258 *r_alpha = use_onion_fade ? (1.0f / abs(gpf->runtime.onion_id)) : 0.5f;
259 *r_alpha *= gpd->onion_factor;
260 *r_alpha = (gpd->onion_factor > 0.0f) ? clamp_f(*r_alpha, 0.1f, 1.0f) :
261 clamp_f(*r_alpha, 0.01f, 1.0f);
262 }
263 else {
264 copy_v4_v4(r_tint, gpl->tintcolor);
265 if (GPENCIL_SIMPLIFY_TINT(pd->scene)) {
266 r_tint[3] = 0.0f;
267 }
268 *r_alpha = 1.0f;
269 }
270
271 *r_alpha *= pd->xray_alpha;
272}
273
275 const GreasePencil &grease_pencil,
276 const int onion_id,
277 float *r_alpha)
278{
279 const bool use_onion = (onion_id != 0);
280 if (use_onion && pd->do_onion) {
281 const bool use_onion_custom_col = (grease_pencil.onion_skinning_settings.flag &
283 const bool use_onion_fade = (grease_pencil.onion_skinning_settings.flag &
285 const bool use_next_col = onion_id > 0;
286
287 const float onion_factor = grease_pencil.onion_skinning_settings.opacity;
288
289 float3 color_next, color_prev;
290 if (use_onion_custom_col) {
291 color_next = float3(grease_pencil.onion_skinning_settings.color_after);
292 color_prev = float3(grease_pencil.onion_skinning_settings.color_before);
293 }
294 else {
297 }
298
299 const float4 onion_col_custom = use_next_col ? float4(color_next, 1.0f) :
300 float4(color_prev, 1.0f);
301
302 *r_alpha = use_onion_fade ? (1.0f / abs(onion_id)) : 0.5f;
303 *r_alpha *= onion_factor;
304 *r_alpha = (onion_factor > 0.0f) ? clamp_f(*r_alpha, 0.1f, 1.0f) :
305 clamp_f(*r_alpha, 0.01f, 1.0f);
306 *r_alpha *= pd->xray_alpha;
307
308 return onion_col_custom;
309 }
310
311 /* Layer tint is not a property in GPv3 anymore. It's only used for onion skinning. The previous
312 * property is replaced by a tint modifier during conversion. */
313 float4 layer_tint(0.0f);
314 if (GPENCIL_SIMPLIFY_TINT(pd->scene)) {
315 layer_tint[3] = 0.0f;
316 }
317 *r_alpha = 1.0f;
318 *r_alpha *= pd->xray_alpha;
319
320 return layer_tint;
321}
322
323/* Random color by layer. */
325 const bGPDlayer *gpl,
326 float r_color[3])
327{
328 const float hsv_saturation = 0.7f;
329 const float hsv_value = 0.6f;
330
333 float hue = BLI_hash_int_01(ob_hash * gpl_hash);
334 const float hsv[3] = {hue, hsv_saturation, hsv_value};
335 hsv_to_rgb_v(hsv, r_color);
336}
337
340 float r_color[3])
341{
342 const float hsv_saturation = 0.7f;
343 const float hsv_value = 0.6f;
344
346 uint gpl_hash = BLI_ghashutil_strhash_p_murmur(layer.name().c_str());
347 float hue = BLI_hash_int_01(ob_hash * gpl_hash);
348 const float hsv[3] = {hue, hsv_saturation, hsv_value};
349 hsv_to_rgb_v(hsv, r_color);
350}
351
353 const Object *ob,
354 const bGPDlayer *gpl,
355 const bGPDframe *gpf,
356 GPENCIL_tObject *tgp_ob)
357{
358 bGPdata *gpd = (bGPdata *)ob->data;
359
360 const bool is_in_front = (ob->dtx & OB_DRAW_IN_FRONT);
361 const bool is_screenspace = (gpd->flag & GP_DATA_STROKE_KEEPTHICKNESS) != 0;
362 const bool override_vertcol = (pd->v3d_color_type != -1);
363 const bool is_vert_col_mode = (pd->v3d_color_type == V3D_SHADING_VERTEX_COLOR) ||
364 GPENCIL_VERTEX_MODE(gpd) || pd->is_render;
365 const bool is_viewlayer_render = pd->is_render && (gpl->viewlayername[0] != '\0') &&
367 const bool disable_masks_render = is_viewlayer_render &&
369 bool is_masked = disable_masks_render ? false :
370 (gpl->flag & GP_LAYER_USE_MASK) &&
372
373 float vert_col_opacity = (override_vertcol) ?
374 (is_vert_col_mode ? pd->vertex_paint_opacity : 0.0f) :
375 (pd->is_render ? gpl->vertex_paint_opacity :
377 /* Negate thickness sign to tag that strokes are in screen space.
378 * Convert to world units (by default, 1 meter = 2000 pixels). */
379 float thickness_scale = (is_screenspace) ? -1.0f : (gpd->pixfactor / GPENCIL_PIXEL_FACTOR);
380 float layer_opacity = gpencil_layer_final_opacity_get(pd, ob, gpl);
381 float layer_tint[4];
382 float layer_alpha;
383 gpencil_layer_final_tint_and_alpha_get(pd, gpd, gpl, gpf, layer_tint, &layer_alpha);
384
385 /* Create the new layer descriptor. */
386 GPENCIL_tLayer *tgp_layer = static_cast<GPENCIL_tLayer *>(BLI_memblock_alloc(pd->gp_layer_pool));
387 BLI_LINKS_APPEND(&tgp_ob->layers, tgp_layer);
388 tgp_layer->layer_id = BLI_findindex(&gpd->layers, gpl);
389 tgp_layer->mask_bits = nullptr;
390 tgp_layer->mask_invert_bits = nullptr;
391 tgp_layer->blend_ps = nullptr;
392
393 /* Masking: Go through mask list and extract valid masks in a bitmap. */
394 if (is_masked) {
395 bool valid_mask = false;
396 /* WARNING: only #GP_MAX_MASKBITS amount of bits.
397 * TODO(fclem): Find a better system without any limitation. */
398 tgp_layer->mask_bits = static_cast<BLI_bitmap *>(BLI_memblock_alloc(pd->gp_maskbit_pool));
399 tgp_layer->mask_invert_bits = static_cast<BLI_bitmap *>(
401 BLI_bitmap_set_all(tgp_layer->mask_bits, false, GP_MAX_MASKBITS);
402
404 bGPDlayer *gpl_mask = BKE_gpencil_layer_named_get(gpd, mask->name);
405 if (gpl_mask && (gpl_mask != gpl) && ((gpl_mask->flag & GP_LAYER_HIDE) == 0) &&
406 ((mask->flag & GP_MASK_HIDE) == 0))
407 {
408 int index = BLI_findindex(&gpd->layers, gpl_mask);
409 if (index < GP_MAX_MASKBITS) {
410 const bool invert = (mask->flag & GP_MASK_INVERT) != 0;
411 BLI_BITMAP_SET(tgp_layer->mask_bits, index, true);
412 BLI_BITMAP_SET(tgp_layer->mask_invert_bits, index, invert);
413 valid_mask = true;
414 }
415 }
416 }
417
418 if (valid_mask) {
419 pd->use_mask_fb = true;
420 }
421 else {
422 tgp_layer->mask_bits = nullptr;
423 }
424 is_masked = valid_mask;
425 }
426
427 /* Blending: Force blending for masked layer. */
428 if (is_masked || (gpl->blend_mode != eGplBlendMode_Regular) || (layer_opacity < 1.0f)) {
430 switch (gpl->blend_mode) {
433 break;
436 break;
439 break;
444 break;
445 }
446
448 /* For these effect to propagate, we need a signed floating point buffer. */
449 pd->use_signed_fb = true;
450 }
451
452 tgp_layer->blend_ps = DRW_pass_create("GPencil Blend Layer", state);
453
455 DRWShadingGroup *grp = DRW_shgroup_create(sh, tgp_layer->blend_ps);
456 DRW_shgroup_uniform_int_copy(grp, "blendMode", gpl->blend_mode);
457 DRW_shgroup_uniform_float_copy(grp, "blendOpacity", layer_opacity);
458 DRW_shgroup_uniform_texture_ref(grp, "colorBuf", &pd->color_layer_tx);
459 DRW_shgroup_uniform_texture_ref(grp, "revealBuf", &pd->reveal_layer_tx);
460 DRW_shgroup_uniform_texture_ref(grp, "maskBuf", (is_masked) ? &pd->mask_tx : &pd->dummy_tx);
461 DRW_shgroup_stencil_mask(grp, 0xFF);
463
465 /* We cannot do custom blending on Multi-Target frame-buffers.
466 * Workaround by doing 2 passes. */
467 grp = DRW_shgroup_create(sh, tgp_layer->blend_ps);
470 DRW_shgroup_uniform_int_copy(grp, "blendMode", 999);
472 }
473
474 pd->use_layer_fb = true;
475 }
476
477 /* Geometry pass */
478 {
479 GPUTexture *depth_tex = (is_in_front) ? pd->dummy_tx : pd->scene_depth_tx;
480 GPUTexture **mask_tex = (is_masked) ? &pd->mask_tx : &pd->dummy_tx;
481
483 /* For 2D mode, we render all strokes with uniform depth (increasing with stroke id). */
485 /* Always write stencil. Only used as optimization for blending. */
487
488 tgp_layer->geom_ps = DRW_pass_create("GPencil Layer", state);
489
491 DRWShadingGroup *grp = tgp_layer->base_shgrp = DRW_shgroup_create(sh, tgp_layer->geom_ps);
492
493 DRW_shgroup_uniform_texture(grp, "gpSceneDepthTexture", depth_tex);
494 DRW_shgroup_uniform_texture_ref(grp, "gpMaskTexture", mask_tex);
495 DRW_shgroup_uniform_vec3_copy(grp, "gpNormal", tgp_ob->plane_normal);
496 DRW_shgroup_uniform_bool_copy(grp, "gpStrokeOrder3d", tgp_ob->is_drawmode3d);
497 DRW_shgroup_uniform_float_copy(grp, "gpThicknessScale", tgp_ob->object_scale);
498 DRW_shgroup_uniform_float_copy(grp, "gpThicknessOffset", float(gpl->line_change));
499 DRW_shgroup_uniform_float_copy(grp, "gpThicknessWorldScale", thickness_scale);
500 DRW_shgroup_uniform_float_copy(grp, "gpVertexColorOpacity", vert_col_opacity);
501
502 /* If random color type, need color by layer. */
503 float gpl_color[4];
504 copy_v4_v4(gpl_color, layer_tint);
506 gpencil_layer_random_color_get(ob, gpl, gpl_color);
507 gpl_color[3] = 1.0f;
508 }
509 DRW_shgroup_uniform_vec4_copy(grp, "gpLayerTint", gpl_color);
510
511 DRW_shgroup_uniform_float_copy(grp, "gpLayerOpacity", layer_alpha);
512 DRW_shgroup_stencil_mask(grp, 0xFF);
513 }
514
515 return tgp_layer;
516}
517
519 int layer_id,
520 const bool skip_onion)
521{
522 BLI_assert(layer_id >= 0);
523 for (GPENCIL_tLayer *layer = tgp_ob->layers.first; layer != nullptr; layer = layer->next) {
524 if (skip_onion && layer->is_onion) {
525 continue;
526 }
527 if (layer->layer_id == layer_id) {
528 return layer;
529 }
530 }
531 return nullptr;
532}
533
535 const Object *ob,
537 const int onion_id,
538 const bool is_used_as_mask,
539 GPENCIL_tObject *tgp_ob)
540
541{
542 using namespace blender::bke::greasepencil;
543 const GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob->data);
544
545 const bool is_in_front = (ob->dtx & OB_DRAW_IN_FRONT);
546
547 const bool override_vertcol = (pd->v3d_color_type != -1);
548 /* In draw mode and vertex paint mode it's possible to draw vertex colors so we want to make sure
549 * to render them. Otherwise this can lead to unexpected behavior. */
550 const bool is_vert_col_mode = (pd->v3d_color_type == V3D_SHADING_VERTEX_COLOR) ||
551 (ob->mode & OB_MODE_VERTEX_PAINT) != 0 ||
552 (ob->mode & OB_MODE_PAINT_GREASE_PENCIL) != 0 || pd->is_render;
553 const bool is_viewlayer_render = pd->is_render && !layer.view_layer_name().is_empty() &&
554 STREQ(pd->view_layer->name, layer.view_layer_name().c_str());
555 const bool disable_masks_render = is_viewlayer_render &&
556 (layer.base.flag &
558 bool is_masked = !disable_masks_render && layer.use_masks() &&
559 !BLI_listbase_is_empty(&layer.masks);
560
561 const float vert_col_opacity = (override_vertcol) ?
562 (is_vert_col_mode ? pd->vertex_paint_opacity : 0.0f) :
563 (pd->is_render ? 1.0f : pd->vertex_paint_opacity);
564 /* Negate thickness sign to tag that strokes are in screen space (this is no longer used in
565 * GPv3). Convert to world units (by default, 1 meter = 1000 pixels). */
567 /* If the layer is used as a mask (but is otherwise not visible in the render), render it with a
568 * opacity of 0 so that it can still mask other layers. */
569 const float layer_opacity = !is_used_as_mask ? grease_pencil_layer_final_opacity_get(
570 pd, ob, grease_pencil, layer) :
571 0.0f;
572
573 float layer_alpha = pd->xray_alpha;
575 pd, grease_pencil, onion_id, &layer_alpha);
576
577 /* Create the new layer descriptor. */
578 GPENCIL_tLayer *tgp_layer = static_cast<GPENCIL_tLayer *>(BLI_memblock_alloc(pd->gp_layer_pool));
579 BLI_LINKS_APPEND(&tgp_ob->layers, tgp_layer);
580 tgp_layer->layer_id = *grease_pencil.get_layer_index(layer);
581 tgp_layer->is_onion = onion_id != 0;
582 tgp_layer->mask_bits = nullptr;
583 tgp_layer->mask_invert_bits = nullptr;
584 tgp_layer->blend_ps = nullptr;
585
586 /* Masking: Go through mask list and extract valid masks in a bitmap. */
587 if (is_masked) {
588 bool valid_mask = false;
589 /* WARNING: only #GP_MAX_MASKBITS amount of bits.
590 * TODO(fclem): Find a better system without any limitation. */
591 tgp_layer->mask_bits = static_cast<BLI_bitmap *>(BLI_memblock_alloc(pd->gp_maskbit_pool));
592 tgp_layer->mask_invert_bits = static_cast<BLI_bitmap *>(
594 BLI_bitmap_set_all(tgp_layer->mask_bits, false, GP_MAX_MASKBITS);
595
596 LISTBASE_FOREACH (GreasePencilLayerMask *, mask, &layer.masks) {
597 if (mask->flag & GP_LAYER_MASK_HIDE) {
598 continue;
599 }
600 const TreeNode *node = grease_pencil.find_node_by_name(mask->layer_name);
601 if (node == nullptr) {
602 continue;
603 }
604 const Layer &mask_layer = node->as_layer();
605 if ((&mask_layer == &layer) || !mask_layer.is_visible()) {
606 continue;
607 }
608 const int index = *grease_pencil.get_layer_index(mask_layer);
609 if (index < GP_MAX_MASKBITS) {
610 const bool invert = (mask->flag & GP_LAYER_MASK_INVERT) != 0;
611 BLI_BITMAP_SET(tgp_layer->mask_bits, index, true);
612 BLI_BITMAP_SET(tgp_layer->mask_invert_bits, index, invert);
613 valid_mask = true;
614 }
615 }
616
617 if (valid_mask) {
618 pd->use_mask_fb = true;
619 }
620 else {
621 tgp_layer->mask_bits = nullptr;
622 }
623 is_masked = valid_mask;
624 }
625
626 /* Blending: Force blending for masked layer. */
627 if (is_masked || (layer.blend_mode != GP_LAYER_BLEND_NONE) || (layer_opacity < 1.0f)) {
629 switch (layer.blend_mode) {
632 break;
635 break;
638 break;
643 break;
644 }
645
646 if (ELEM(layer.blend_mode, GP_LAYER_BLEND_SUBTRACT, GP_LAYER_BLEND_HARDLIGHT)) {
647 /* For these effect to propagate, we need a signed floating point buffer. */
648 pd->use_signed_fb = true;
649 }
650
651 tgp_layer->blend_ps = DRW_pass_create("GPencil Blend Layer", state);
652
654 DRWShadingGroup *grp = DRW_shgroup_create(sh, tgp_layer->blend_ps);
655 DRW_shgroup_uniform_int_copy(grp, "blendMode", layer.blend_mode);
656 DRW_shgroup_uniform_float_copy(grp, "blendOpacity", layer_opacity);
657 DRW_shgroup_uniform_texture_ref(grp, "colorBuf", &pd->color_layer_tx);
658 DRW_shgroup_uniform_texture_ref(grp, "revealBuf", &pd->reveal_layer_tx);
659 DRW_shgroup_uniform_texture_ref(grp, "maskBuf", (is_masked) ? &pd->mask_tx : &pd->dummy_tx);
660 DRW_shgroup_stencil_mask(grp, 0xFF);
662
663 if (layer.blend_mode == GP_LAYER_BLEND_HARDLIGHT) {
664 /* We cannot do custom blending on Multi-Target frame-buffers.
665 * Workaround by doing 2 passes. */
666 grp = DRW_shgroup_create(sh, tgp_layer->blend_ps);
669 DRW_shgroup_uniform_int_copy(grp, "blendMode", 999);
671 }
672
673 pd->use_layer_fb = true;
674 }
675
676 /* Geometry pass */
677 {
678 GPUTexture *depth_tex = (is_in_front) ? pd->dummy_tx : pd->scene_depth_tx;
679 GPUTexture **mask_tex = (is_masked) ? &pd->mask_tx : &pd->dummy_tx;
680
682 /* For 2D mode, we render all strokes with uniform depth (increasing with stroke id). */
684 /* Always write stencil. Only used as optimization for blending. */
686
687 tgp_layer->geom_ps = DRW_pass_create("GPencil Layer", state);
688
690 DRWShadingGroup *grp = tgp_layer->base_shgrp = DRW_shgroup_create(sh, tgp_layer->geom_ps);
691
692 DRW_shgroup_uniform_texture(grp, "gpSceneDepthTexture", depth_tex);
693 DRW_shgroup_uniform_texture_ref(grp, "gpMaskTexture", mask_tex);
694 DRW_shgroup_uniform_vec3_copy(grp, "gpNormal", tgp_ob->plane_normal);
695 DRW_shgroup_uniform_bool_copy(grp, "gpStrokeOrder3d", tgp_ob->is_drawmode3d);
696 DRW_shgroup_uniform_float_copy(grp, "gpThicknessScale", tgp_ob->object_scale);
697 /* Replaced by a modifier in GPv3. */
698 DRW_shgroup_uniform_float_copy(grp, "gpThicknessOffset", 0.0f);
699 DRW_shgroup_uniform_float_copy(grp, "gpThicknessWorldScale", thickness_scale);
700 DRW_shgroup_uniform_float_copy(grp, "gpVertexColorOpacity", vert_col_opacity);
701
702 /* If random color type, need color by layer. */
703 float gpl_color[4];
704 copy_v4_v4(gpl_color, layer_tint);
706 grease_pencil_layer_random_color_get(ob, layer, gpl_color);
707 gpl_color[3] = 1.0f;
708 }
709 DRW_shgroup_uniform_vec4_copy(grp, "gpLayerTint", gpl_color);
710
711 DRW_shgroup_uniform_float_copy(grp, "gpLayerOpacity", layer_alpha);
712 DRW_shgroup_stencil_mask(grp, 0xFF);
713 }
714
715 return tgp_layer;
716}
struct bGPDlayer * BKE_gpencil_layer_named_get(struct bGPdata *gpd, const char *name)
#define GPENCIL_SIMPLIFY_TINT(scene)
Low-level operations for grease pencil.
int BKE_object_material_count_eval(const struct Object *ob)
struct MaterialGPencilStyle * BKE_gpencil_material_settings(struct Object *ob, short act)
General operations, lookup, etc. for blender objects.
#define BLI_assert(a)
Definition BLI_assert.h:50
void BLI_bitmap_set_all(BLI_bitmap *bitmap, bool set, size_t bits)
Definition bitmap.c:18
#define BLI_BITMAP_SET(_bitmap, _index, _set)
Definition BLI_bitmap.h:103
unsigned int BLI_bitmap
Definition BLI_bitmap.h:17
unsigned int BLI_ghashutil_strhash_p_murmur(const void *ptr)
BLI_INLINE float BLI_hash_int_01(unsigned int k)
Definition BLI_hash.h:96
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
#define LISTBASE_FOREACH(type, var, list)
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
MINLINE float clamp_f(float value, float min, float max)
void hsv_to_rgb_v(const float hsv[3], float r_rgb[3])
Definition math_color.cc:57
float mat4_to_scale(const float mat[4][4])
void orthogonalize_m4(float R[4][4], int axis)
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void unit_m4(float m[4][4])
Definition rct.c:1127
void rescale_m4(float mat[4][4], const float scale[3])
void mul_m4_v3(const float M[4][4], float r[3])
bool invert_m4(float mat[4][4])
void transpose_m4(float R[4][4])
void mul_mat3_m4_v3(const float mat[4][4], float r[3])
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void add_v3_fl(float r[3], float f)
MINLINE void copy_v4_fl4(float v[4], float x, float y, float z, float w)
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float normalize_v3(float n[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
void * BLI_memblock_alloc(BLI_memblock *mblk) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
unsigned int uint
#define UNPACK3(a)
#define ELEM(...)
#define STREQ(a, b)
#define GPENCIL_VERTEX_MODE(gpd)
@ GP_LAYER_DISABLE_MASKS_IN_VIEWLAYER
@ GP_ONION_GHOST_PREVCOL
@ GP_DATA_STROKE_KEEPTHICKNESS
@ eGplBlendMode_Regular
@ eGplBlendMode_Multiply
@ eGplBlendMode_Subtract
@ eGplBlendMode_HardLight
@ GP_LAYER_BLEND_HARDLIGHT
@ GP_LAYER_BLEND_NONE
@ GP_LAYER_BLEND_MULTIPLY
@ GP_LAYER_BLEND_DIVIDE
@ GP_LAYER_BLEND_SUBTRACT
@ GP_LAYER_MASK_INVERT
@ GP_LAYER_TREE_NODE_DISABLE_MASKS_IN_VIEWLAYER
@ GP_ONION_SKINNING_USE_FADE
@ GP_ONION_SKINNING_USE_CUSTOM_COLORS
@ GP_MATERIAL_IS_STROKE_HOLDOUT
@ GP_MATERIAL_IS_FILL_HOLDOUT
@ OB_MODE_PAINT_GREASE_PENCIL
@ OB_MODE_VERTEX_PAINT
@ OB_DRAW_IN_FRONT
@ V3D_SHADING_VERTEX_COLOR
@ V3D_SHADING_RANDOM_COLOR
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its hue
void UI_GetThemeColor3fv(int colorid, float col[3])
@ TH_FRAME_AFTER
@ TH_FRAME_BEFORE
struct GPUShader GPUShader
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition btDbvt.cpp:299
local_group_size(16, 16) .push_constant(Type b
DRWShadingGroup * DRW_shgroup_create(GPUShader *shader, DRWPass *pass)
void DRW_shgroup_uniform_float_copy(DRWShadingGroup *shgroup, const char *name, const float value)
void DRW_shgroup_state_disable(DRWShadingGroup *shgroup, DRWState state)
void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex)
DRWPass * DRW_pass_create(const char *name, DRWState state)
void DRW_shgroup_state_enable(DRWShadingGroup *shgroup, DRWState state)
void DRW_shgroup_uniform_vec3_copy(DRWShadingGroup *shgroup, const char *name, const float *value)
bool DRW_view_is_persp_get(const DRWView *view)
void DRW_shgroup_uniform_int_copy(DRWShadingGroup *shgroup, const char *name, const int value)
void DRW_shgroup_call_procedural_triangles(DRWShadingGroup *shgroup, const Object *ob, uint tri_count)
void DRW_shgroup_uniform_vec4_copy(DRWShadingGroup *shgroup, const char *name, const float *value)
void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex)
void DRW_shgroup_uniform_bool_copy(DRWShadingGroup *shgroup, const char *name, const bool value)
void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, uint mask)
DRWState
Definition draw_state.hh:25
@ DRW_STATE_STENCIL_EQUAL
Definition draw_state.hh:47
@ DRW_STATE_STENCIL_ALWAYS
Definition draw_state.hh:46
@ DRW_STATE_BLEND_SUB
Definition draw_state.hh:61
@ DRW_STATE_WRITE_DEPTH
Definition draw_state.hh:29
@ DRW_STATE_BLEND_ADD_FULL
Definition draw_state.hh:53
@ DRW_STATE_WRITE_COLOR
Definition draw_state.hh:30
@ DRW_STATE_DEPTH_LESS_EQUAL
Definition draw_state.hh:38
@ DRW_STATE_BLEND_ALPHA_PREMUL
Definition draw_state.hh:57
@ DRW_STATE_DEPTH_GREATER
Definition draw_state.hh:40
@ DRW_STATE_BLEND_MUL
Definition draw_state.hh:60
@ DRW_STATE_WRITE_STENCIL
Definition draw_state.hh:32
static void grease_pencil_layer_random_color_get(const Object *ob, const blender::bke::greasepencil::Layer &layer, float r_color[3])
static float4 grease_pencil_layer_final_tint_and_alpha_get(const GPENCIL_PrivateData *pd, const GreasePencil &grease_pencil, const int onion_id, float *r_alpha)
static float grease_pencil_layer_final_opacity_get(const GPENCIL_PrivateData *pd, const Object *ob, const GreasePencil &grease_pencil, const blender::bke::greasepencil::Layer &layer)
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)
static float gpencil_layer_final_opacity_get(const GPENCIL_PrivateData *pd, const Object *ob, const bGPDlayer *gpl)
GPENCIL_tLayer * grease_pencil_layer_cache_get(GPENCIL_tObject *tgp_ob, int layer_id, const bool skip_onion)
GPENCIL_tObject * gpencil_object_cache_add(GPENCIL_PrivateData *pd, Object *ob, const bool is_stroke_order_3d, const blender::Bounds< float3 > bounds)
static int gpencil_tobject_dist_sort(const void *a, const void *b)
static void gpencil_layer_final_tint_and_alpha_get(const GPENCIL_PrivateData *pd, const bGPdata *gpd, const bGPDlayer *gpl, const bGPDframe *gpf, float r_tint[4], float *r_alpha)
static void gpencil_layer_random_color_get(const Object *ob, const bGPDlayer *gpl, float r_color[3])
void gpencil_object_cache_sort(GPENCIL_PrivateData *pd)
GPENCIL_tLayer * gpencil_layer_cache_add(GPENCIL_PrivateData *pd, const Object *ob, const bGPDlayer *gpl, const bGPDframe *gpf, GPENCIL_tObject *tgp_ob)
#define GP_MAX_MASKBITS
#define GPENCIL_PIXEL_FACTOR
struct GPUShader * GPENCIL_shader_layer_blend_get(void)
struct GPUShader * GPENCIL_shader_geometry_get(void)
CCL_NAMESPACE_BEGIN ccl_device float invert(float color, float factor)
Definition invert.h:9
static ulong state[N]
constexpr float LEGACY_RADIUS_CONVERSION_FACTOR
T midpoint(const T &a, const T &b)
GPUTexture * scene_depth_tx
struct BLI_memblock * gp_layer_pool
struct ViewLayer * view_layer
struct GPENCIL_PrivateData::@202 tobjects_infront
struct BLI_memblock * gp_maskbit_pool
struct BLI_memblock * gp_object_pool
GPENCIL_tObject * first
struct GPENCIL_PrivateData::@202 tobjects
struct Scene * scene
GPENCIL_tObject * last
GPUTexture * reveal_layer_tx
GPUTexture * color_layer_tx
DRWShadingGroup * base_shgrp
BLI_bitmap * mask_invert_bits
BLI_bitmap * mask_bits
float plane_mat[4][4]
GPENCIL_tLayer * last
struct GPENCIL_tObject::@201 vfx
struct GPENCIL_tObject * next
GPENCIL_tLayer * first
struct GPENCIL_tObject::@200 layers
GreasePencilOnionSkinningSettings onion_skinning_settings
char name[66]
Definition DNA_ID.h:425
char name[64]
bGPDframe_Runtime runtime
ccl_device_inline int abs(int x)
Definition util/math.h:120