Blender  V3.3
overlay_wireframe.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2019 Blender Foundation. */
3 
8 #include "DNA_collection_types.h"
9 #include "DNA_mesh_types.h"
10 #include "DNA_particle_types.h"
11 #include "DNA_view3d_types.h"
12 #include "DNA_volume_types.h"
13 
14 #include "BKE_curve.h"
15 #include "BKE_displist.h"
16 #include "BKE_duplilist.h"
17 #include "BKE_editmesh.h"
18 #include "BKE_global.h"
19 #include "BKE_object.h"
20 #include "BKE_paint.h"
21 #include "BKE_particle.h"
22 
23 #include "BLI_hash.h"
24 
25 #include "DRW_render.h"
26 #include "GPU_shader.h"
27 
28 #include "ED_view3d.h"
29 
30 #include "overlay_private.h"
31 
33 {
34  OVERLAY_PrivateData *pd = vedata->stl->pd;
35  const DRWContextState *draw_ctx = DRW_context_state_get();
36  DRWView *default_view = (DRWView *)DRW_view_default_get();
37  pd->view_wires = DRW_view_create_with_zoffset(default_view, draw_ctx->rv3d, 0.5f);
38 }
39 
41 {
42  OVERLAY_PassList *psl = vedata->psl;
43  OVERLAY_TextureList *txl = vedata->txl;
44  OVERLAY_PrivateData *pd = vedata->stl->pd;
45  const DRWContextState *draw_ctx = DRW_context_state_get();
46  DRWShadingGroup *grp = NULL;
47 
48  View3DShading *shading = &draw_ctx->v3d->shading;
49 
50  pd->shdata.wire_step_param = pd->overlay.wireframe_threshold - 254.0f / 255.0f;
52 
53  bool is_wire_shmode = (shading->type == OB_WIRE);
54  bool is_material_shmode = (shading->type > OB_SOLID);
55  bool is_object_color = is_wire_shmode && (shading->wire_color_type == V3D_SHADING_OBJECT_COLOR);
56  bool is_random_color = is_wire_shmode && (shading->wire_color_type == V3D_SHADING_RANDOM_COLOR);
57 
58  const bool use_select = (DRW_state_is_select() || DRW_state_is_depth());
59  GPUShader *wires_sh = use_select ? OVERLAY_shader_wireframe_select() :
61 
62  for (int xray = 0; xray < (is_material_shmode ? 1 : 2); xray++) {
65  DRWPass *pass;
66  GPUTexture **depth_tx = ((!pd->xray_enabled || pd->xray_opacity > 0.0f) &&
67  DRW_state_is_fbo()) ?
68  &txl->temp_depth_tx :
69  &txl->dummy_depth_tx;
70 
71  if (xray == 0) {
73  pass = psl->wireframe_ps;
74  }
75  else {
77  pass = psl->wireframe_xray_ps;
78  }
79 
80  for (int use_coloring = 0; use_coloring < 2; use_coloring++) {
81  pd->wires_grp[xray][use_coloring] = grp = DRW_shgroup_create(wires_sh, pass);
82  DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
83  DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tx);
84  DRW_shgroup_uniform_float_copy(grp, "wireStepParam", pd->shdata.wire_step_param);
85  DRW_shgroup_uniform_float_copy(grp, "wireOpacity", pd->shdata.wire_opacity);
86  DRW_shgroup_uniform_bool_copy(grp, "useColoring", use_coloring);
87  DRW_shgroup_uniform_bool_copy(grp, "isTransform", (G.moving & G_TRANSFORM_OBJ) != 0);
88  DRW_shgroup_uniform_bool_copy(grp, "isObjectColor", is_object_color);
89  DRW_shgroup_uniform_bool_copy(grp, "isRandomColor", is_random_color);
90  DRW_shgroup_uniform_bool_copy(grp, "isHair", false);
91 
92  pd->wires_all_grp[xray][use_coloring] = grp = DRW_shgroup_create(wires_sh, pass);
93  DRW_shgroup_uniform_float_copy(grp, "wireStepParam", 1.0f);
94 
95  pd->wires_hair_grp[xray][use_coloring] = grp = DRW_shgroup_create(wires_sh, pass);
96  DRW_shgroup_uniform_bool_copy(grp, "isHair", true);
97  DRW_shgroup_uniform_float_copy(grp, "wireStepParam", 10.0f);
98  }
99 
100  pd->wires_sculpt_grp[xray] = grp = DRW_shgroup_create(wires_sh, pass);
101  DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tx);
102  DRW_shgroup_uniform_float_copy(grp, "wireStepParam", 10.0f);
103  DRW_shgroup_uniform_bool_copy(grp, "useColoring", false);
104  DRW_shgroup_uniform_bool_copy(grp, "isHair", false);
105  }
106 
107  if (is_material_shmode) {
108  /* Make all drawcalls go into the non-xray shading groups. */
109  for (int use_coloring = 0; use_coloring < 2; use_coloring++) {
110  pd->wires_grp[1][use_coloring] = pd->wires_grp[0][use_coloring];
111  pd->wires_all_grp[1][use_coloring] = pd->wires_all_grp[0][use_coloring];
112  pd->wires_hair_grp[1][use_coloring] = pd->wires_hair_grp[0][use_coloring];
113  }
114  pd->wires_sculpt_grp[1] = pd->wires_sculpt_grp[0];
115  psl->wireframe_xray_ps = NULL;
116  }
117 }
118 
120 {
121  OVERLAY_PrivateData *pd = vedata->stl->pd;
122  const bool is_xray = (ob->dtx & OB_DRAW_IN_FRONT) != 0;
123 
124  Object *dupli_parent = DRW_object_get_dupli_parent(ob);
125  DupliObject *dupli_object = DRW_object_get_dupli(ob);
126 
127  float dupli_mat[4][4];
128  if ((dupli_parent != NULL) && (dupli_object != NULL)) {
129  if (dupli_object->type & OB_DUPLICOLLECTION) {
130  unit_m4(dupli_mat);
131  Collection *collection = dupli_parent->instance_collection;
132  if (collection != NULL) {
133  sub_v3_v3(dupli_mat[3], collection->instance_offset);
134  }
135  mul_m4_m4m4(dupli_mat, dupli_parent->obmat, dupli_mat);
136  }
137  else {
138  copy_m4_m4(dupli_mat, dupli_object->ob->obmat);
139  invert_m4(dupli_mat);
140  mul_m4_m4m4(dupli_mat, ob->obmat, dupli_mat);
141  }
142  }
143  else {
144  unit_m4(dupli_mat);
145  }
146 
147  struct GPUBatch *hairs = DRW_cache_particles_get_hair(ob, psys, NULL);
148 
149  const bool use_coloring = true;
150  DRWShadingGroup *shgrp = DRW_shgroup_create_sub(pd->wires_hair_grp[is_xray][use_coloring]);
151  DRW_shgroup_uniform_mat4_copy(shgrp, "hairDupliMatrix", dupli_mat);
152  DRW_shgroup_call_no_cull(shgrp, hairs, ob);
153 }
154 
156  Object *ob,
157  OVERLAY_DupliData *dupli,
158  bool init_dupli)
159 {
160  OVERLAY_PrivateData *pd = vedata->stl->pd;
161  const DRWContextState *draw_ctx = DRW_context_state_get();
162  const bool all_wires = (ob->dtx & OB_DRAW_ALL_EDGES) != 0;
163  const bool is_xray = (ob->dtx & OB_DRAW_IN_FRONT) != 0;
164  const bool is_mesh = ob->type == OB_MESH;
165  const bool is_edit_mode = DRW_object_is_in_edit_mode(ob);
166  bool has_edit_mesh_cage = false;
167  bool is_mesh_verts_only = false;
168  if (is_mesh) {
169  /* TODO: Should be its own function. */
170  Mesh *me = ob->data;
171  if (is_edit_mode) {
172  BLI_assert(me->edit_mesh);
173  Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob);
174  Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob);
175  has_edit_mesh_cage = editmesh_eval_cage && (editmesh_eval_cage != editmesh_eval_final);
176  if (editmesh_eval_final) {
177  me = editmesh_eval_final;
178  }
179  }
180  is_mesh_verts_only = me->totedge == 0 && me->totvert > 0;
181  }
182 
183  const bool use_wire = !is_mesh_verts_only && ((pd->overlay.flag & V3D_OVERLAY_WIREFRAMES) ||
184  (ob->dtx & OB_DRAWWIRE) || (ob->dt == OB_WIRE));
185 
186  if (use_wire && pd->wireframe_mode && ob->particlesystem.first) {
187  for (ParticleSystem *psys = ob->particlesystem.first; psys != NULL; psys = psys->next) {
189  continue;
190  }
191  ParticleSettings *part = psys->part;
192  const int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as;
193  if (draw_as == PART_DRAW_PATH) {
194  wireframe_hair_cache_populate(vedata, ob, psys);
195  }
196  }
197  }
198 
199  if (ELEM(ob->type, OB_CURVES_LEGACY, OB_FONT, OB_SURF)) {
201  float *color;
202  DRW_object_wire_theme_get(ob, draw_ctx->view_layer, &color);
203 
204  struct GPUBatch *geom = NULL;
205  switch (ob->type) {
206  case OB_CURVES_LEGACY:
208  break;
209  case OB_FONT:
210  geom = DRW_cache_text_edge_wire_get(ob);
211  break;
212  case OB_SURF:
213  geom = DRW_cache_surf_edge_wire_get(ob);
214  break;
215  }
216 
217  if (geom) {
218  OVERLAY_extra_wire(cb, geom, ob->obmat, color);
219  }
220  }
221 
222  /* Fast path for duplis. */
223  if (dupli && !init_dupli) {
224  if (dupli->wire_shgrp && dupli->wire_geom) {
225  if (dupli->base_flag == ob->base_flag) {
226  /* Check for the special cases used below, assign specific theme colors to the shaders. */
228  if (dupli->wire_shgrp == cb->extra_loose_points) {
229  float *color;
230  DRW_object_wire_theme_get(ob, draw_ctx->view_layer, &color);
232  }
233  else if (dupli->wire_shgrp == cb->extra_wire) {
234  float *color;
235  DRW_object_wire_theme_get(ob, draw_ctx->view_layer, &color);
236  OVERLAY_extra_wire(cb, dupli->wire_geom, ob->obmat, color);
237  }
238  else {
239  DRW_shgroup_call(dupli->wire_shgrp, dupli->wire_geom, ob);
240  }
241  return;
242  }
243  }
244  else {
245  /* Nothing to draw for this dupli. */
246  return;
247  }
248  }
249 
250  if (use_wire && ELEM(ob->type, OB_VOLUME, OB_POINTCLOUD)) {
251  bool draw_as_points = true;
252  if (ob->type == OB_VOLUME) {
253  /* Volume object as points exception. */
254  Volume *volume = ob->data;
255  draw_as_points = volume->display.wireframe_type == VOLUME_WIREFRAME_POINTS;
256  }
257 
258  if (draw_as_points) {
259  float *color;
261  DRW_object_wire_theme_get(ob, draw_ctx->view_layer, &color);
262 
264  if (geom) {
265  OVERLAY_extra_loose_points(cb, geom, ob->obmat, color);
266  }
267  return;
268  }
269  }
270 
271  DRWShadingGroup *shgrp = NULL;
272  struct GPUBatch *geom = NULL;
273 
274  /* Don't do that in edit Mesh mode, unless there is a modifier preview. */
275  if (use_wire && (!is_mesh || (!is_edit_mode || has_edit_mesh_cage))) {
276  const bool is_sculpt_mode = ((ob->mode & OB_MODE_SCULPT) != 0) && (ob->sculpt != NULL);
277  const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->rv3d) &&
279  const bool is_instance = (ob->base_flag & BASE_FROM_DUPLI);
280  const bool instance_parent_in_edit_mode = is_instance ? DRW_object_is_in_edit_mode(
282  false;
283  const bool use_coloring = (use_wire && !is_edit_mode && !is_sculpt_mode &&
284  !has_edit_mesh_cage && !instance_parent_in_edit_mode);
286 
287  if (geom || use_sculpt_pbvh) {
288  if (use_sculpt_pbvh) {
289  shgrp = pd->wires_sculpt_grp[is_xray];
290  }
291  else if (all_wires) {
292  shgrp = pd->wires_all_grp[is_xray][use_coloring];
293  }
294  else {
295  shgrp = pd->wires_grp[is_xray][use_coloring];
296  }
297 
298  if (ob->type == OB_GPENCIL) {
299  /* TODO(fclem): Make GPencil objects have correct bound-box. */
300  DRW_shgroup_call_no_cull(shgrp, geom, ob);
301  }
302  else if (use_sculpt_pbvh) {
303  DRW_shgroup_call_sculpt(shgrp, ob, true, false);
304  }
305  else {
306  DRW_shgroup_call(shgrp, geom, ob);
307  }
308  }
309  }
310  else if (is_mesh && (!is_edit_mode || has_edit_mesh_cage)) {
312  float *color;
313  DRW_object_wire_theme_get(ob, draw_ctx->view_layer, &color);
314 
315  /* Draw loose geometry. */
316  if (is_mesh_verts_only) {
317  geom = DRW_cache_mesh_all_verts_get(ob);
318  if (geom) {
319  OVERLAY_extra_loose_points(cb, geom, ob->obmat, color);
320  shgrp = cb->extra_loose_points;
321  }
322  }
323  else {
325  if (geom) {
326  OVERLAY_extra_wire(cb, geom, ob->obmat, color);
327  shgrp = cb->extra_wire;
328  }
329  }
330  }
331 
332  if (dupli) {
333  dupli->wire_shgrp = shgrp;
334  dupli->wire_geom = geom;
335  }
336 }
337 
339 {
340  OVERLAY_PassList *psl = data->psl;
341  OVERLAY_PrivateData *pd = data->stl->pd;
342 
345 
347 }
348 
350 {
351  OVERLAY_PassList *psl = data->psl;
352  OVERLAY_PrivateData *pd = data->stl->pd;
353 
354  if (psl->wireframe_xray_ps) {
357 
359  }
360 }
display list (or rather multi purpose list) stuff.
@ G_TRANSFORM_OBJ
Definition: BKE_global.h:247
General operations, lookup, etc. for blender objects.
struct Mesh * BKE_object_get_editmesh_eval_final(const struct Object *object)
struct Mesh * BKE_object_get_editmesh_eval_cage(const struct Object *object)
bool BKE_sculptsession_use_pbvh_draw(const struct Object *ob, const struct RegionView3D *rv3d)
#define BLI_assert(a)
Definition: BLI_assert.h:46
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:259
bool invert_m4(float R[4][4])
Definition: math_matrix.c:1206
void unit_m4(float m[4][4])
Definition: rct.c:1090
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:77
MINLINE void sub_v3_v3(float r[3], const float a[3])
#define ELEM(...)
Object groups, one object can be in many groups at once.
@ BASE_FROM_DUPLI
@ OB_WIRE
@ OB_SOLID
@ OB_MODE_SCULPT
@ OB_SURF
@ OB_FONT
@ OB_MESH
@ OB_POINTCLOUD
@ OB_VOLUME
@ OB_CURVES_LEGACY
@ OB_GPENCIL
@ OB_DRAW_ALL_EDGES
@ OB_DRAW_IN_FRONT
@ OB_DRAWWIRE
@ OB_DUPLICOLLECTION
#define PART_DRAW_PATH
#define PART_DRAW_REND
@ V3D_SHADING_OBJECT_COLOR
@ V3D_SHADING_RANDOM_COLOR
@ V3D_OVERLAY_WIREFRAMES
@ VOLUME_WIREFRAME_POINTS
#define DRW_shgroup_call_no_cull(shgroup, geom, ob)
Definition: DRW_render.h:431
DRWState
Definition: DRW_render.h:298
@ DRW_STATE_WRITE_DEPTH
Definition: DRW_render.h:302
@ DRW_STATE_WRITE_COLOR
Definition: DRW_render.h:303
@ DRW_STATE_DEPTH_LESS_EQUAL
Definition: DRW_render.h:311
@ DRW_STATE_FIRST_VERTEX_CONVENTION
Definition: DRW_render.h:343
#define DRW_PASS_CREATE(pass, state)
Definition: DRW_render.h:690
#define DRW_shgroup_uniform_block(shgroup, name, ubo)
Definition: DRW_render.h:651
#define DRW_shgroup_call(shgroup, geom, ob)
Definition: DRW_render.h:414
GPUBatch
Definition: GPU_batch.h:78
struct GPUShader GPUShader
Definition: GPU_shader.h:20
struct GPUTexture GPUTexture
Definition: GPU_texture.h:17
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a color
GPUBatch * DRW_cache_curve_edge_wire_get(Object *ob)
Definition: draw_cache.c:2926
GPUBatch * DRW_cache_text_edge_wire_get(Object *ob)
Definition: draw_cache.c:2995
GPUBatch * DRW_cache_mesh_all_verts_get(Object *ob)
Definition: draw_cache.c:2834
GPUBatch * DRW_cache_object_face_wireframe_get(Object *ob)
Definition: draw_cache.c:836
GPUBatch * DRW_cache_surf_edge_wire_get(Object *ob)
Definition: draw_cache.c:3008
GPUBatch * DRW_cache_mesh_loose_edges_get(Object *ob)
Definition: draw_cache.c:2846
GPUBatch * DRW_cache_particles_get_hair(Object *object, ParticleSystem *psys, ModifierData *md)
Definition: draw_cache.c:3093
int DRW_object_wire_theme_get(Object *ob, ViewLayer *view_layer, float **r_color)
Definition: draw_common.c:279
struct DRW_Global G_draw
Definition: draw_common.c:32
DRWView * DRW_view_create_with_zoffset(const DRWView *parent_view, const RegionView3D *rv3d, float offset)
Definition: draw_common.c:255
struct Object * DRW_object_get_dupli_parent(const Object *UNUSED(ob))
Definition: draw_manager.c:264
bool DRW_state_is_select(void)
bool DRW_state_is_depth(void)
bool DRW_object_is_in_edit_mode(const Object *ob)
Definition: draw_manager.c:196
bool DRW_state_is_fbo(void)
struct DupliObject * DRW_object_get_dupli(const Object *UNUSED(ob))
Definition: draw_manager.c:269
bool DRW_object_is_visible_psys_in_active_context(const Object *object, const ParticleSystem *psys)
Definition: draw_manager.c:234
const DRWContextState * DRW_context_state_get(void)
bool DRW_state_is_image_render(void)
void DRW_shgroup_uniform_float_copy(DRWShadingGroup *shgroup, const char *name, const float value)
const DRWView * DRW_view_default_get(void)
void DRW_shgroup_call_sculpt(DRWShadingGroup *shgroup, Object *ob, bool use_wire, bool use_mask)
DRWShadingGroup * DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass)
DRWShadingGroup * DRW_shgroup_create_sub(DRWShadingGroup *shgroup)
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_uniform_mat4_copy(DRWShadingGroup *shgroup, const char *name, const float(*value)[4])
void DRW_draw_pass(DRWPass *pass)
void DRW_view_set_active(const DRWView *view)
const int state
#define G(x, y, z)
OVERLAY_ExtraCallBuffers * OVERLAY_extra_call_buffer_get(OVERLAY_Data *vedata, Object *ob)
void OVERLAY_extra_loose_points(OVERLAY_ExtraCallBuffers *cb, struct GPUBatch *geom, const float mat[4][4], const float color[4])
void OVERLAY_extra_wire(OVERLAY_ExtraCallBuffers *cb, struct GPUBatch *geom, const float mat[4][4], const float color[4])
GPUShader * OVERLAY_shader_wireframe(bool custom_bias)
GPUShader * OVERLAY_shader_wireframe_select(void)
static void wireframe_hair_cache_populate(OVERLAY_Data *vedata, Object *ob, ParticleSystem *psys)
void OVERLAY_wireframe_in_front_draw(OVERLAY_Data *data)
void OVERLAY_wireframe_draw(OVERLAY_Data *data)
void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata, Object *ob, OVERLAY_DupliData *dupli, bool init_dupli)
void OVERLAY_wireframe_cache_init(OVERLAY_Data *vedata)
void OVERLAY_wireframe_init(OVERLAY_Data *vedata)
float instance_offset[3]
struct ViewLayer * view_layer
Definition: DRW_render.h:980
struct View3D * v3d
Definition: DRW_render.h:976
struct RegionView3D * rv3d
Definition: DRW_render.h:975
struct GPUUniformBuf * block_ubo
Definition: draw_common.h:129
struct Object * ob
Definition: BKE_duplilist.h:34
void * first
Definition: DNA_listBase.h:31
struct BMEditMesh * edit_mesh
int totedge
int totvert
OVERLAY_PassList * psl
OVERLAY_StorageList * stl
OVERLAY_TextureList * txl
struct GPUBatch * wire_geom
DRWShadingGroup * wire_shgrp
DRWShadingGroup * extra_wire
DRWShadingGroup * extra_loose_points
DRWPass * wireframe_ps
DRWPass * wireframe_xray_ps
OVERLAY_ShadingData shdata
struct OVERLAY_PrivateData::@249 antialiasing
View3DOverlay overlay
DRWShadingGroup * wires_all_grp[2][2]
DRWShadingGroup * wires_hair_grp[2][2]
DRWShadingGroup * wires_grp[2][2]
DRWShadingGroup * wires_sculpt_grp[2]
struct OVERLAY_PrivateData * pd
struct GPUTexture * dummy_depth_tx
struct GPUTexture * temp_depth_tx
ListBase particlesystem
struct Collection * instance_collection
short base_flag
float obmat[4][4]
struct SculptSession * sculpt
void * data
View3DShading shading
VolumeDisplay display