Blender  V3.3
select_engine.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2019 Blender Foundation. */
3 
10 #include "DNA_screen_types.h"
11 
12 #include "UI_resources.h"
13 
14 #include "DRW_engine.h"
15 #include "DRW_select_buffer.h"
16 
17 #include "draw_cache_impl.h"
18 #include "draw_manager.h"
19 
20 #include "select_engine.h"
21 #include "select_private.h"
22 
23 #define SELECT_ENGINE "SELECT_ENGINE"
24 
25 /* *********** STATIC *********** */
26 
27 static struct {
30 
34 } e_data = {NULL}; /* Engine data */
35 
36 /* -------------------------------------------------------------------- */
41 {
43  int size[2];
44  size[0] = GPU_texture_width(dtxl->depth);
45  size[1] = GPU_texture_height(dtxl->depth);
46 
47  if (e_data.framebuffer_select_id == NULL) {
48  e_data.framebuffer_select_id = GPU_framebuffer_create("framebuffer_select_id");
49  }
50 
51  if ((e_data.texture_u32 != NULL) && ((GPU_texture_width(e_data.texture_u32) != size[0]) ||
52  (GPU_texture_height(e_data.texture_u32) != size[1]))) {
53  GPU_texture_free(e_data.texture_u32);
54  e_data.texture_u32 = NULL;
55  }
56 
57  /* Make sure the depth texture is attached.
58  * It may disappear when loading another Blender session. */
59  GPU_framebuffer_texture_attach(e_data.framebuffer_select_id, dtxl->depth, 0, 0);
60 
61  if (e_data.texture_u32 == NULL) {
62  e_data.texture_u32 = GPU_texture_create_2d(
63  "select_buf_ids", size[0], size[1], 1, GPU_R32UI, NULL);
64  GPU_framebuffer_texture_attach(e_data.framebuffer_select_id, e_data.texture_u32, 0, 0);
65 
66  GPU_framebuffer_check_valid(e_data.framebuffer_select_id, NULL);
67  }
68 }
69 
72 /* -------------------------------------------------------------------- */
76 static void select_engine_init(void *vedata)
77 {
78  const DRWContextState *draw_ctx = DRW_context_state_get();
79  eGPUShaderConfig sh_cfg = draw_ctx->sh_cfg;
80 
81  SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl;
82  SELECTID_Shaders *sh_data = &e_data.sh_data[sh_cfg];
83 
84  /* Prepass */
85  if (!sh_data->select_id_flat) {
87  sh_cfg == GPU_SHADER_CFG_CLIPPED ? "select_id_flat_clipped" : "select_id_flat");
88  }
89  if (!sh_data->select_id_uniform) {
91  sh_cfg == GPU_SHADER_CFG_CLIPPED ? "select_id_uniform_clipped" : "select_id_uniform");
92  }
93 
94  if (!stl->g_data) {
95  /* Alloc transient pointers */
96  stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
97  }
98 
99  {
100  /* Create view from a subregion */
101  const DRWView *view_default = DRW_view_default_get();
102  float viewmat[4][4], winmat[4][4], winmat_subregion[4][4];
103  DRW_view_viewmat_get(view_default, viewmat, false);
104  DRW_view_winmat_get(view_default, winmat, false);
105  projmat_from_subregion(winmat,
106  (int[2]){draw_ctx->region->winx, draw_ctx->region->winy},
107  e_data.context.last_rect.xmin,
108  e_data.context.last_rect.xmax,
109  e_data.context.last_rect.ymin,
110  e_data.context.last_rect.ymax,
111  winmat_subregion);
112 
113  stl->g_data->view_subregion = DRW_view_create(viewmat, winmat_subregion, NULL, NULL, NULL);
114 
115  /* Create view with depth offset */
116  stl->g_data->view_faces = (DRWView *)view_default;
117  stl->g_data->view_edges = DRW_view_create_with_zoffset(view_default, draw_ctx->rv3d, 1.0f);
118  stl->g_data->view_verts = DRW_view_create_with_zoffset(view_default, draw_ctx->rv3d, 1.1f);
119  }
120 }
121 
122 static void select_cache_init(void *vedata)
123 {
124  SELECTID_PassList *psl = ((SELECTID_Data *)vedata)->psl;
125  SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl;
126  SELECTID_PrivateData *pd = stl->g_data;
127 
128  const DRWContextState *draw_ctx = DRW_context_state_get();
129  SELECTID_Shaders *sh = &e_data.sh_data[draw_ctx->sh_cfg];
130 
131  if (e_data.context.select_mode == -1) {
132  e_data.context.select_mode = select_id_get_object_select_mode(draw_ctx->scene,
133  draw_ctx->obact);
134  BLI_assert(e_data.context.select_mode != 0);
135  }
136 
138  state |= RV3D_CLIPPING_ENABLED(draw_ctx->v3d, draw_ctx->rv3d) ? DRW_STATE_CLIP_PLANES : 0;
139 
140  {
142  pd->shgrp_depth_only = DRW_shgroup_create(sh->select_id_uniform, psl->depth_only_pass);
143 
145  if (e_data.context.select_mode & SCE_SELECT_FACE) {
146  pd->shgrp_face_flat = DRW_shgroup_create(sh->select_id_flat, psl->select_id_face_pass);
147  }
148  else {
149  pd->shgrp_face_unif = DRW_shgroup_create(sh->select_id_uniform, psl->select_id_face_pass);
151  }
152 
153  if (e_data.context.select_mode & SCE_SELECT_EDGE) {
155 
156  pd->shgrp_edge = DRW_shgroup_create(sh->select_id_flat, psl->select_id_edge_pass);
157  }
158 
159  if (e_data.context.select_mode & SCE_SELECT_VERTEX) {
161  pd->shgrp_vert = DRW_shgroup_create(sh->select_id_flat, psl->select_id_vert_pass);
163  }
164  }
165 
166  /* Check if the viewport has changed. */
167  float(*persmat)[4] = draw_ctx->rv3d->persmat;
168  e_data.context.is_dirty = !compare_m4m4(e_data.context.persmat, persmat, FLT_EPSILON);
169 
170  if (!e_data.context.is_dirty) {
171  /* Check if any of the drawn objects have been transformed. */
172  Object **ob = &e_data.context.objects_drawn[0];
173  for (uint i = e_data.context.objects_drawn_len; i--; ob++) {
175  if (data && (data->recalc & ID_RECALC_TRANSFORM) != 0) {
176  data->recalc &= ~ID_RECALC_TRANSFORM;
177  e_data.context.is_dirty = true;
178  }
179  }
180  }
181 
182  if (e_data.context.is_dirty) {
183  /* Remove all tags from drawn or culled objects. */
184  copy_m4_m4(e_data.context.persmat, persmat);
185  e_data.context.objects_drawn_len = 0;
186  e_data.context.index_drawn_len = 1;
188  GPU_framebuffer_bind(e_data.framebuffer_select_id);
189  GPU_framebuffer_clear_color_depth(e_data.framebuffer_select_id, (const float[4]){0.0f}, 1.0f);
190  }
191  e_data.runtime_new_objects = 0;
192 }
193 
194 static void select_cache_populate(void *vedata, Object *ob)
195 {
196  SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl;
197  const DRWContextState *draw_ctx = DRW_context_state_get();
198 
200  &ob->id, &draw_engine_select_type);
201 
202  if (!e_data.context.is_dirty && sel_data && sel_data->is_drawn) {
203  /* The object indices have already been drawn. Fill depth pass.
204  * Opti: Most of the time this depth pass is not used. */
205  struct Mesh *me = ob->data;
206  if (e_data.context.select_mode & SCE_SELECT_FACE) {
208  DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_faces, ob->obmat);
209  }
210  else if (ob->dt >= OB_SOLID) {
211 #ifdef USE_CAGE_OCCLUSION
213 #else
214  struct GPUBatch *geom_faces = DRW_mesh_batch_cache_get_surface(me);
215 #endif
216  DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_faces, ob->obmat);
217  }
218 
219  if (e_data.context.select_mode & SCE_SELECT_EDGE) {
221  DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_edges, ob->obmat);
222  }
223 
224  if (e_data.context.select_mode & SCE_SELECT_VERTEX) {
226  DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_verts, ob->obmat);
227  }
228  return;
229  }
230 
231  float min[3], max[3];
233 
235  if (sel_data == NULL) {
238  }
239  sel_data->dd.recalc = 0;
240  sel_data->drawn_index = e_data.context.objects_drawn_len;
241  sel_data->is_drawn = true;
242 
243  struct ObjectOffsets *ob_offsets =
244  &e_data.context.index_offsets[e_data.context.objects_drawn_len];
245 
246  uint offset = e_data.context.index_drawn_len;
247  select_id_draw_object(vedata,
248  draw_ctx->v3d,
249  ob,
250  e_data.context.select_mode,
251  offset,
252  &ob_offsets->vert,
253  &ob_offsets->edge,
254  &ob_offsets->face);
255 
256  ob_offsets->offset = offset;
257  e_data.context.index_drawn_len = ob_offsets->vert;
258  e_data.context.objects_drawn[e_data.context.objects_drawn_len] = ob;
259  e_data.context.objects_drawn_len++;
260  e_data.runtime_new_objects++;
261  }
262  else if (sel_data) {
263  sel_data->is_drawn = false;
264  }
265 }
266 
267 static void select_draw_scene(void *vedata)
268 {
269  SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl;
270  SELECTID_PassList *psl = ((SELECTID_Data *)vedata)->psl;
271 
272  if (!e_data.runtime_new_objects) {
273  /* Nothing new needs to be drawn. */
274  return;
275  }
276 
278 
279  if (!DRW_pass_is_empty(psl->depth_only_pass)) {
282  GPU_framebuffer_clear_depth(dfbl->depth_only_fb, 1.0f);
284  }
285 
286  /* Setup framebuffer */
287  GPU_framebuffer_bind(e_data.framebuffer_select_id);
288 
290 
291  if (e_data.context.select_mode & SCE_SELECT_EDGE) {
294  }
295 
296  if (e_data.context.select_mode & SCE_SELECT_VERTEX) {
299  }
300 }
301 
302 static void select_engine_free(void)
303 {
304  for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) {
305  SELECTID_Shaders *sh_data = &e_data.sh_data[sh_data_index];
308  }
309 
310  DRW_TEXTURE_FREE_SAFE(e_data.texture_u32);
311  GPU_FRAMEBUFFER_FREE_SAFE(e_data.framebuffer_select_id);
312  MEM_SAFE_FREE(e_data.context.objects);
313  MEM_SAFE_FREE(e_data.context.index_offsets);
314  MEM_SAFE_FREE(e_data.context.objects_drawn);
315 }
316 
319 /* -------------------------------------------------------------------- */
324 
326  NULL,
327  NULL,
328  N_("Select ID"),
332  NULL, /* instance_free */
335  NULL,
337  NULL,
338  NULL,
339  NULL,
340  NULL,
341 };
342 
343 /* NOTE: currently unused, we may want to register so we can see this when debugging the view. */
344 
346  NULL,
347  NULL,
349  N_("Select ID"),
351  NULL,
352  NULL,
353  NULL,
354  NULL,
355  NULL,
356  NULL,
357  NULL,
358  NULL,
359  NULL,
361  {NULL, NULL, NULL},
362 };
363 
366 /* -------------------------------------------------------------------- */
371 {
372  return &e_data.context;
373 }
374 
376 {
377  return e_data.framebuffer_select_id;
378 }
379 
381 {
382  return e_data.texture_u32;
383 }
384 
387 #undef SELECT_ENGINE
typedef float(TangentPoint)[2]
#define BLI_assert(a)
Definition: BLI_assert.h:46
void projmat_from_subregion(const float projmat[4][4], const int win_size[2], int x_min, int x_max, int y_min, int y_max, float r_projmat[4][4])
Definition: math_geom.c:4727
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:77
bool compare_m4m4(const float mat1[4][4], const float mat2[4][4], float limit)
Definition: math_matrix.c:1425
unsigned int uint
Definition: BLI_sys_types.h:67
#define ARRAY_SIZE(arr)
@ ID_RECALC_TRANSFORM
Definition: DNA_ID.h:771
@ OB_SOLID
#define SCE_SELECT_FACE
#define SCE_SELECT_VERTEX
#define SCE_SELECT_EDGE
#define RV3D_CLIPPING_ENABLED(v3d, rv3d)
DRWState
Definition: DRW_render.h:298
@ DRW_STATE_CLIP_PLANES
Definition: DRW_render.h:342
@ DRW_STATE_FIRST_VERTEX_CONVENTION
Definition: DRW_render.h:343
#define DRW_SHADER_FREE_SAFE(shader)
Definition: DRW_render.h:254
#define DRW_PASS_CREATE(pass, state)
Definition: DRW_render.h:690
#define DRW_shgroup_call_obmat(shgroup, geom, obmat)
Definition: DRW_render.h:420
#define DRW_STATE_DEFAULT
Definition: DRW_render.h:350
#define DRW_VIEWPORT_DATA_SIZE(ty)
Definition: DRW_render.h:96
#define DRW_TEXTURE_FREE_SAFE(tex)
Definition: DRW_render.h:183
GPUBatch
Definition: GPU_batch.h:78
struct GPUFrameBuffer GPUFrameBuffer
bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
GPUFrameBuffer * GPU_framebuffer_create(const char *name)
eGPUShaderConfig
Definition: GPU_shader.h:364
@ GPU_SHADER_CFG_CLIPPED
Definition: GPU_shader.h:366
GPUShader * GPU_shader_create_from_info_name(const char *info_name)
Definition: gpu_shader.cc:265
#define GPU_SHADER_CFG_LEN
Definition: GPU_shader.h:368
int GPU_texture_height(const GPUTexture *tex)
Definition: gpu_texture.cc:607
struct GPUTexture GPUTexture
Definition: GPU_texture.h:17
int GPU_texture_width(const GPUTexture *tex)
Definition: gpu_texture.cc:602
void GPU_texture_free(GPUTexture *tex)
Definition: gpu_texture.cc:564
GPUTexture * GPU_texture_create_2d(const char *name, int w, int h, int mip_len, eGPUTextureFormat format, const float *data)
Definition: gpu_texture.cc:291
@ GPU_R32UI
Definition: GPU_texture.h:108
#define MEM_SAFE_FREE(v)
#define RE_USE_STEREO_VIEWPORT
Definition: RE_engine.h:51
#define RE_INTERNAL
Definition: RE_engine.h:43
#define RE_USE_GPU_CONTEXT
Definition: RE_engine.h:52
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
struct GPUBatch * DRW_mesh_batch_cache_get_triangles_with_select_id(struct Mesh *me)
struct GPUBatch * DRW_mesh_batch_cache_get_edges_with_select_id(struct Mesh *me)
struct GPUBatch * DRW_mesh_batch_cache_get_verts_with_select_id(struct Mesh *me)
struct GPUBatch * DRW_mesh_batch_cache_get_surface(struct Mesh *me)
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
DrawData * DRW_drawdata_ensure(ID *id, DrawEngineType *engine_type, size_t size, DrawDataInitCb init_cb, DrawDataFreeCb free_cb)
Definition: draw_manager.c:866
DefaultFramebufferList * DRW_viewport_framebuffer_list_get(void)
Definition: draw_manager.c:633
const DRWContextState * DRW_context_state_get(void)
DrawData * DRW_drawdata_get(ID *id, DrawEngineType *engine_type)
Definition: draw_manager.c:850
DefaultTextureList * DRW_viewport_texture_list_get(void)
Definition: draw_manager.c:638
void DRW_shgroup_uniform_float_copy(DRWShadingGroup *shgroup, const char *name, const float value)
const DRWView * DRW_view_default_get(void)
void DRW_view_winmat_get(const DRWView *view, float mat[4][4], bool inverse)
void DRW_shgroup_uniform_int_copy(DRWShadingGroup *shgroup, const char *name, const int value)
bool DRW_pass_is_empty(DRWPass *pass)
DRWView * DRW_view_create(const float viewmat[4][4], const float winmat[4][4], const float(*culling_viewmat)[4], const float(*culling_winmat)[4], DRWCallVisibilityFn *visibility_fn)
DRWShadingGroup * DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass)
void DRW_view_viewmat_get(const DRWView *view, float mat[4][4], bool inverse)
void DRW_draw_pass(DRWPass *pass)
void DRW_view_set_active(const DRWView *view)
bool DRW_culling_min_max_test(const DRWView *view, float obmat[4][4], float min[3], float max[3])
void GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int mip)
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
const int state
ccl_gpu_kernel_postfix ccl_global float int int int int sh
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
short select_id_get_object_select_mode(Scene *scene, Object *ob)
void select_id_object_min_max(Object *obj, float r_min[3], float r_max[3])
void select_id_draw_object(void *vedata, View3D *v3d, Object *ob, short select_mode, uint initial_offset, uint *r_vert_offset, uint *r_edge_offset, uint *r_face_offset)
DrawEngineType draw_engine_select_type
struct GPUTexture * texture_u32
Definition: select_engine.c:29
SELECTID_Shaders sh_data[GPU_SHADER_CFG_LEN]
Definition: select_engine.c:31
struct SELECTID_Context * DRW_select_engine_context_get(void)
struct GPUFrameBuffer * framebuffer_select_id
Definition: select_engine.c:28
static void select_cache_populate(void *vedata, Object *ob)
static void select_cache_init(void *vedata)
RenderEngineType DRW_engine_viewport_select_type
GPUFrameBuffer * DRW_engine_select_framebuffer_get(void)
static void select_engine_framebuffer_setup(void)
Definition: select_engine.c:40
uint runtime_new_objects
Definition: select_engine.c:33
static const DrawEngineDataSize select_data_size
static void select_engine_free(void)
static struct @268 e_data
GPUTexture * DRW_engine_select_texture_get(void)
static void select_draw_scene(void *vedata)
static void select_engine_init(void *vedata)
Definition: select_engine.c:76
#define SELECT_ENGINE
Definition: select_engine.c:23
struct SELECTID_Context context
Definition: select_engine.c:32
#define min(a, b)
Definition: sort.c:35
struct Object * obact
Definition: DRW_render.h:983
struct Scene * scene
Definition: DRW_render.h:979
eGPUShaderConfig sh_cfg
Definition: DRW_render.h:993
struct View3D * v3d
Definition: DRW_render.h:976
struct ARegion * region
Definition: DRW_render.h:974
struct RegionView3D * rv3d
Definition: DRW_render.h:975
GlobalsUboStorage block
Definition: draw_common.h:127
struct GPUFrameBuffer * depth_only_fb
struct GPUTexture * depth
int recalc
Definition: DNA_ID.h:40
float obmat[4][4]
void * data
float persmat[4][4]
struct DRWPass * depth_only_pass
struct DRWPass * select_id_vert_pass
struct DRWPass * select_id_face_pass
struct DRWPass * select_id_edge_pass
DRWShadingGroup * shgrp_face_unif
DRWShadingGroup * shgrp_edge
DRWShadingGroup * shgrp_depth_only
DRWShadingGroup * shgrp_face_flat
DRWShadingGroup * shgrp_vert
struct GPUShader * select_id_uniform
struct GPUShader * select_id_flat
struct SELECTID_PrivateData * g_data
float max
#define N_(msgid)