c31cd62262f53b619a23b84dcc194fc9dcfebbec
[blender.git] / source / blender / draw / modes / edit_mesh_mode.c
1 /*
2  * Copyright 2016, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Blender Institute
19  *
20  */
21
22 /** \file blender/draw/modes/edit_mesh_mode.c
23  *  \ingroup draw
24  */
25
26 #include "DRW_engine.h"
27 #include "DRW_render.h"
28
29 #include "GPU_shader.h"
30
31 #include "DNA_mesh_types.h"
32 #include "DNA_view3d_types.h"
33
34 #include "draw_common.h"
35
36 #include "draw_cache_impl.h"
37 #include "draw_mode_engines.h"
38
39 #include "edit_mesh_mode_intern.h" /* own include */
40
41 #include "BKE_editmesh.h"
42 #include "BKE_object.h"
43
44 #include "BLI_dynstr.h"
45 #include "BLI_string_utils.h"
46
47
48 extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
49 extern struct GlobalsUboStorage ts; /* draw_common.c */
50
51 extern struct GPUTexture *globals_weight_ramp; /* draw_common.c */
52
53 extern char datatoc_common_world_clip_lib_glsl[];
54
55 extern char datatoc_paint_weight_vert_glsl[];
56 extern char datatoc_paint_weight_frag_glsl[];
57
58 extern char datatoc_edit_mesh_overlay_common_lib_glsl[];
59 extern char datatoc_edit_mesh_overlay_frag_glsl[];
60 extern char datatoc_edit_mesh_overlay_vert_glsl[];
61 extern char datatoc_edit_mesh_overlay_geom_tri_glsl[];
62 extern char datatoc_edit_mesh_overlay_geom_edge_glsl[];
63 extern char datatoc_edit_mesh_overlay_points_vert_glsl[];
64 extern char datatoc_edit_mesh_overlay_facedot_frag_glsl[];
65 extern char datatoc_edit_mesh_overlay_facedot_vert_glsl[];
66 extern char datatoc_edit_mesh_overlay_mix_frag_glsl[];
67 extern char datatoc_edit_mesh_overlay_facefill_vert_glsl[];
68 extern char datatoc_edit_mesh_overlay_facefill_frag_glsl[];
69 extern char datatoc_edit_normals_vert_glsl[];
70 extern char datatoc_edit_normals_geom_glsl[];
71 extern char datatoc_common_globals_lib_glsl[];
72
73 extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
74 extern char datatoc_gpu_shader_flat_color_frag_glsl[];
75 extern char datatoc_gpu_shader_point_varying_color_frag_glsl[];
76 extern char datatoc_gpu_shader_depth_only_frag_glsl[];
77
78 /* *********** LISTS *********** */
79 typedef struct EDIT_MESH_PassList {
80         struct DRWPass *weight_faces;
81         struct DRWPass *depth_hidden_wire;
82         struct DRWPass *ghost_clear_depth;
83         struct DRWPass *edit_face_overlay;
84         struct DRWPass *edit_face_occluded;
85         struct DRWPass *mix_occlude;
86         struct DRWPass *facefill_occlude;
87         struct DRWPass *normals;
88 } EDIT_MESH_PassList;
89
90 typedef struct EDIT_MESH_FramebufferList {
91         struct GPUFrameBuffer *occlude_wire_fb;
92         struct GPUFrameBuffer *ghost_wire_fb;
93 } EDIT_MESH_FramebufferList;
94
95 typedef struct EDIT_MESH_StorageList {
96         struct EDIT_MESH_PrivateData *g_data;
97 } EDIT_MESH_StorageList;
98
99 typedef struct EDIT_MESH_Data {
100         void *engine_type;
101         EDIT_MESH_FramebufferList *fbl;
102         DRWViewportEmptyList *txl;
103         EDIT_MESH_PassList *psl;
104         EDIT_MESH_StorageList *stl;
105 } EDIT_MESH_Data;
106
107 #define MAX_SHADERS 16
108
109 /** Can only contain shaders (freed as array). */
110 typedef struct EDIT_MESH_Shaders {
111         /* weight */
112         GPUShader *weight_face;
113
114         /* Geometry */
115         GPUShader *overlay_tri_cache[MAX_SHADERS];
116         GPUShader *overlay_loose_edge_cache[MAX_SHADERS];
117
118         GPUShader *overlay_vert;
119         GPUShader *overlay_lvert;
120         GPUShader *overlay_facedot;
121         GPUShader *overlay_mix;
122         GPUShader *overlay_facefill;
123         GPUShader *normals_face;
124         GPUShader *normals_loop;
125         GPUShader *normals;
126         GPUShader *depth;
127         GPUShader *ghost_clear_depth;
128 } EDIT_MESH_Shaders;
129
130 /* *********** STATIC *********** */
131 static struct {
132         /* 0: normal, 1: clipped. */
133         EDIT_MESH_Shaders sh_data[2];
134
135         /* temp buffer texture */
136         struct GPUTexture *occlude_wire_depth_tx;
137         struct GPUTexture *occlude_wire_color_tx;
138 } e_data = {NULL}; /* Engine data */
139
140 typedef struct EDIT_MESH_PrivateData {
141         /* weight */
142         DRWShadingGroup *fweights_shgrp;
143         DRWShadingGroup *depth_shgrp_hidden_wire;
144
145         DRWShadingGroup *fnormals_shgrp;
146         DRWShadingGroup *vnormals_shgrp;
147         DRWShadingGroup *lnormals_shgrp;
148
149         DRWShadingGroup *face_shgrp;
150         DRWShadingGroup *face_cage_shgrp;
151
152         DRWShadingGroup *verts_shgrp;
153         DRWShadingGroup *ledges_shgrp;
154         DRWShadingGroup *lverts_shgrp;
155         DRWShadingGroup *facedot_shgrp;
156
157         DRWShadingGroup *facefill_occluded_shgrp;
158
159         int data_mask[4];
160         int ghost_ob;
161         int edit_ob;
162         bool do_zbufclip;
163         bool do_faces;
164         bool do_edges;
165         float edge_width_scale;
166 } EDIT_MESH_PrivateData; /* Transient data */
167
168 /* *********** FUNCTIONS *********** */
169
170 static int EDIT_MESH_sh_data_index_from_rv3d(const RegionView3D *rv3d)
171 {
172         if (rv3d->rflag & RV3D_CLIPPING) {
173                 return 1;
174         }
175         return 0;
176 }
177
178 static int EDIT_MESH_sh_index(ToolSettings *tsettings, RegionView3D *rv3d, bool supports_fast_mode)
179 {
180         int result = tsettings->selectmode << 1;
181         if (supports_fast_mode) {
182                 SET_FLAG_FROM_TEST(result, (rv3d->rflag & RV3D_NAVIGATING), 1 << 0);
183         }
184         return result;
185 }
186
187 static char *EDIT_MESH_sh_defines(ToolSettings *tsettings, RegionView3D *rv3d, bool anti_alias, bool looseedge)
188 {
189         const int selectmode = tsettings->selectmode;
190         const int fast_mode = rv3d->rflag & RV3D_NAVIGATING;
191
192         char *str = NULL;
193         DynStr *ds = BLI_dynstr_new();
194
195         if (selectmode & SCE_SELECT_VERTEX) {
196                 BLI_dynstr_append(ds, "#define VERTEX_SELECTION\n");
197         }
198
199         if (selectmode & SCE_SELECT_EDGE) {
200                 BLI_dynstr_append(ds, "#define EDGE_SELECTION\n");
201         }
202
203         if (selectmode & SCE_SELECT_FACE) {
204                 BLI_dynstr_append(ds, "#define FACE_SELECTION\n");
205         }
206
207         if (!fast_mode || looseedge) {
208                 BLI_dynstr_append(ds, "#define EDGE_FIX\n");
209         }
210
211         if (anti_alias) {
212                 BLI_dynstr_append(ds, "#define ANTI_ALIASING\n");
213         }
214
215         if (!looseedge) {
216                 BLI_dynstr_append(ds, "#define VERTEX_FACING\n");
217         }
218         str = BLI_dynstr_get_cstring(ds);
219         BLI_dynstr_free(ds);
220         return str;
221 }
222 static GPUShader *EDIT_MESH_ensure_shader(
223         EDIT_MESH_Shaders *sh_data,
224         ToolSettings *tsettings, RegionView3D *rv3d, bool supports_fast_mode, bool looseedge)
225 {
226         const int index = EDIT_MESH_sh_index(tsettings, rv3d, supports_fast_mode);
227         const bool fast_mode = (rv3d->rflag & RV3D_NAVIGATING) != 0;
228         const bool is_clip = (rv3d->rflag & RV3D_CLIPPING) != 0;
229         const char *world_clip_lib_or_empty = is_clip ? datatoc_common_world_clip_lib_glsl : "";
230         const char *world_clip_def_or_empty = is_clip ? "#define USE_WORLD_CLIP_PLANES\n" : "";
231
232         if (looseedge) {
233                 if (!sh_data->overlay_loose_edge_cache[index]) {
234                         char *lib = BLI_string_joinN(world_clip_lib_or_empty, datatoc_common_globals_lib_glsl, datatoc_edit_mesh_overlay_common_lib_glsl);
235                         char *defines = EDIT_MESH_sh_defines(tsettings, rv3d, true, true);
236                         sh_data->overlay_loose_edge_cache[index] = DRW_shader_create_from_arrays({
237                                 .vert = (const char *[]){lib, datatoc_edit_mesh_overlay_vert_glsl, NULL},
238                                 .geom = (const char *[]){lib, datatoc_edit_mesh_overlay_geom_edge_glsl, NULL},
239                                 .frag = (const char *[]){lib, datatoc_edit_mesh_overlay_frag_glsl, NULL},
240                                 .defs = (const char *[]){world_clip_def_or_empty, defines, NULL},
241                         });
242                         MEM_freeN(lib);
243                         MEM_freeN(defines);
244                 }
245                 return sh_data->overlay_loose_edge_cache[index];
246         }
247         else {
248                 if (!sh_data->overlay_tri_cache[index]) {
249                         char *lib = BLI_string_joinN(world_clip_lib_or_empty, datatoc_common_globals_lib_glsl, datatoc_edit_mesh_overlay_common_lib_glsl);
250                         char *defines = EDIT_MESH_sh_defines(tsettings, rv3d, true, false);
251                         sh_data->overlay_tri_cache[index] = DRW_shader_create_from_arrays({
252                                 .vert = (const char *[]){lib, datatoc_edit_mesh_overlay_vert_glsl, NULL},
253                                 .geom = fast_mode ? NULL : (const char *[]){lib, datatoc_edit_mesh_overlay_geom_tri_glsl, NULL},
254                                 .frag = (const char *[]){lib, datatoc_edit_mesh_overlay_frag_glsl, NULL},
255                                 .defs = (const char *[]){world_clip_def_or_empty, defines, NULL},
256                         });
257                         MEM_freeN(lib);
258                         MEM_freeN(defines);
259                 }
260                 return sh_data->overlay_tri_cache[index];
261         }
262 }
263
264 static void EDIT_MESH_engine_init(void *vedata)
265 {
266         EDIT_MESH_FramebufferList *fbl = ((EDIT_MESH_Data *)vedata)->fbl;
267
268         const DRWContextState *draw_ctx = DRW_context_state_get();
269         EDIT_MESH_Shaders *sh_data = &e_data.sh_data[EDIT_MESH_sh_data_index_from_rv3d(draw_ctx->rv3d)];
270         const bool is_clip = (draw_ctx->rv3d->rflag & RV3D_CLIPPING) != 0;
271
272         const float *viewport_size = DRW_viewport_size_get();
273         const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
274
275         e_data.occlude_wire_depth_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_DEPTH_COMPONENT24,
276                                                                  &draw_engine_edit_mesh_type);
277         e_data.occlude_wire_color_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_RGBA8,
278                                                                  &draw_engine_edit_mesh_type);
279
280         GPU_framebuffer_ensure_config(&fbl->occlude_wire_fb, {
281                 GPU_ATTACHMENT_TEXTURE(e_data.occlude_wire_depth_tx),
282                 GPU_ATTACHMENT_TEXTURE(e_data.occlude_wire_color_tx)
283         });
284
285         if (is_clip) {
286                 DRW_state_clip_planes_set_from_rv3d(draw_ctx->rv3d);
287         }
288
289         const char *world_clip_lib_or_empty = is_clip ? datatoc_common_world_clip_lib_glsl : "";
290         const char *world_clip_def_or_empty = is_clip ? "#define USE_WORLD_CLIP_PLANES\n" : "";
291
292         if (!sh_data->weight_face) {
293                 sh_data->weight_face = DRW_shader_create_from_arrays({
294                         .vert = (const char *[]){world_clip_lib_or_empty, datatoc_common_globals_lib_glsl, datatoc_paint_weight_vert_glsl, NULL},
295                         .frag = (const char *[]){datatoc_common_globals_lib_glsl, datatoc_paint_weight_frag_glsl, NULL},
296                         .defs = (const char *[]){world_clip_def_or_empty, NULL}});
297         }
298
299         if (!sh_data->overlay_vert) {
300                 char *lib = BLI_string_joinN(world_clip_lib_or_empty, datatoc_common_globals_lib_glsl, datatoc_edit_mesh_overlay_common_lib_glsl);
301                 sh_data->overlay_vert = DRW_shader_create_from_arrays({
302                         .vert = (const char *[]){lib, datatoc_edit_mesh_overlay_points_vert_glsl, NULL},
303                         .frag = (const char *[]){datatoc_gpu_shader_point_varying_color_frag_glsl, NULL},
304                         .defs = (const char *[]){world_clip_def_or_empty, "#define VERTEX_FACING\n", NULL}});
305
306                 sh_data->overlay_lvert = DRW_shader_create_from_arrays({
307                         .vert = (const char *[]){lib, datatoc_edit_mesh_overlay_points_vert_glsl, NULL},
308                         .frag = (const char *[]){datatoc_gpu_shader_point_varying_color_frag_glsl, NULL},
309                         .defs = (const char *[]){world_clip_def_or_empty, NULL}});
310                 MEM_freeN(lib);
311         }
312         if (!sh_data->overlay_facedot) {
313                 sh_data->overlay_facedot = DRW_shader_create_from_arrays({
314                         .vert = (const char *[]){world_clip_lib_or_empty, datatoc_common_globals_lib_glsl, datatoc_edit_mesh_overlay_facedot_vert_glsl, NULL},
315                         .frag = (const char *[]){datatoc_common_globals_lib_glsl, datatoc_edit_mesh_overlay_facedot_frag_glsl, NULL},
316                         .defs = (const char *[]){world_clip_def_or_empty, "#define VERTEX_FACING\n", NULL}});
317         }
318         if (!sh_data->overlay_mix) {
319                 sh_data->overlay_mix = DRW_shader_create_fullscreen(datatoc_edit_mesh_overlay_mix_frag_glsl, NULL);
320         }
321         if (!sh_data->overlay_facefill) {
322                 sh_data->overlay_facefill = DRW_shader_create_from_arrays({
323                         .vert = (const char *[]){world_clip_lib_or_empty, datatoc_common_globals_lib_glsl, datatoc_edit_mesh_overlay_facefill_vert_glsl, NULL},
324                         .frag = (const char *[]){datatoc_common_globals_lib_glsl, datatoc_edit_mesh_overlay_facefill_frag_glsl, NULL},
325                         .defs = (const char *[]){world_clip_def_or_empty, NULL}});
326         }
327         if (!sh_data->normals_face) {
328                 sh_data->normals_face = DRW_shader_create_from_arrays({
329                         .vert = (const char *[]){world_clip_lib_or_empty, datatoc_edit_normals_vert_glsl, NULL},
330                         .geom = (const char *[]){world_clip_lib_or_empty, datatoc_edit_normals_geom_glsl, NULL},
331                         .frag = (const char *[]){datatoc_gpu_shader_uniform_color_frag_glsl, NULL},
332                         .defs = (const char *[]){world_clip_def_or_empty, "#define FACE_NORMALS\n", NULL}});
333         }
334         if (!sh_data->normals_loop) {
335                 sh_data->normals_loop = DRW_shader_create_from_arrays({
336                         .vert = (const char *[]){world_clip_lib_or_empty, datatoc_edit_normals_vert_glsl, NULL},
337                         .geom = (const char *[]){world_clip_lib_or_empty, datatoc_edit_normals_geom_glsl, NULL},
338                         .frag = (const char *[]){datatoc_gpu_shader_uniform_color_frag_glsl, NULL},
339                         .defs = (const char *[]){world_clip_def_or_empty, "#define LOOP_NORMALS\n", NULL}});
340         }
341         if (!sh_data->normals) {
342                 sh_data->normals = DRW_shader_create_from_arrays({
343                         .vert = (const char *[]){world_clip_lib_or_empty, datatoc_edit_normals_vert_glsl, NULL},
344                         .geom = (const char *[]){world_clip_lib_or_empty, datatoc_edit_normals_geom_glsl, NULL},
345                         .frag = (const char *[]){datatoc_gpu_shader_uniform_color_frag_glsl, NULL},
346                         .defs = (const char *[]){world_clip_def_or_empty, NULL}});
347         }
348         if (!sh_data->depth) {
349                 sh_data->depth = DRW_shader_create_3D_depth_only();
350         }
351         if (!sh_data->ghost_clear_depth) {
352                 sh_data->ghost_clear_depth = DRW_shader_create_fullscreen(datatoc_gpu_shader_depth_only_frag_glsl, NULL);
353         }
354
355 }
356
357 static DRWPass *edit_mesh_create_overlay_pass(
358         float *face_alpha, float *edge_width_scale, int *data_mask, bool do_edges, bool xray,
359         DRWState statemod,
360         DRWShadingGroup **r_face_shgrp, DRWShadingGroup **r_face_cage_shgrp,
361         DRWShadingGroup **r_verts_shgrp, DRWShadingGroup **r_ledges_shgrp,
362         DRWShadingGroup **r_lverts_shgrp, DRWShadingGroup **r_facedot_shgrp)
363 {
364         GPUShader *tri_sh, *ledge_sh;
365         const DRWContextState *draw_ctx = DRW_context_state_get();
366         RegionView3D *rv3d = draw_ctx->rv3d;
367         Scene *scene = draw_ctx->scene;
368         ToolSettings *tsettings = scene->toolsettings;
369         const int fast_mode = rv3d->rflag & RV3D_NAVIGATING;
370         EDIT_MESH_Shaders *sh_data = &e_data.sh_data[EDIT_MESH_sh_data_index_from_rv3d(draw_ctx->rv3d)];
371
372         ledge_sh = EDIT_MESH_ensure_shader(sh_data, tsettings, rv3d, false, true);
373         tri_sh = EDIT_MESH_ensure_shader(sh_data, tsettings, rv3d, true, false);
374
375         DRWPass *pass = DRW_pass_create(
376                 "Edit Mesh Face Overlay Pass",
377                 DRW_STATE_WRITE_COLOR | DRW_STATE_POINT | statemod);
378
379         if ((tsettings->selectmode & SCE_SELECT_VERTEX) != 0) {
380                 *r_lverts_shgrp = DRW_shgroup_create(sh_data->overlay_lvert, pass);
381                 DRW_shgroup_uniform_block(*r_lverts_shgrp, "globalsBlock", globals_ubo);
382                 DRW_shgroup_uniform_vec2(*r_lverts_shgrp, "viewportSize", DRW_viewport_size_get(), 1);
383                 DRW_shgroup_uniform_float(*r_lverts_shgrp, "edgeScale", edge_width_scale, 1);
384                 DRW_shgroup_state_enable(*r_lverts_shgrp, DRW_STATE_WRITE_DEPTH);
385                 DRW_shgroup_state_disable(*r_lverts_shgrp, DRW_STATE_BLEND);
386                 if (rv3d->rflag & RV3D_CLIPPING) {
387                         DRW_shgroup_world_clip_planes_from_rv3d(*r_lverts_shgrp, rv3d);
388                 }
389
390                 *r_verts_shgrp = DRW_shgroup_create(sh_data->overlay_vert, pass);
391                 DRW_shgroup_uniform_block(*r_verts_shgrp, "globalsBlock", globals_ubo);
392                 DRW_shgroup_uniform_vec2(*r_verts_shgrp, "viewportSize", DRW_viewport_size_get(), 1);
393                 DRW_shgroup_uniform_float(*r_verts_shgrp, "edgeScale", edge_width_scale, 1);
394                 DRW_shgroup_state_enable(*r_verts_shgrp, DRW_STATE_WRITE_DEPTH);
395                 DRW_shgroup_state_disable(*r_verts_shgrp, DRW_STATE_BLEND);
396                 if (rv3d->rflag & RV3D_CLIPPING) {
397                         DRW_shgroup_world_clip_planes_from_rv3d(*r_verts_shgrp, rv3d);
398                 }
399         }
400
401         if ((tsettings->selectmode & SCE_SELECT_FACE) != 0) {
402                 *r_facedot_shgrp = DRW_shgroup_create(sh_data->overlay_facedot, pass);
403                 DRW_shgroup_uniform_block(*r_facedot_shgrp, "globalsBlock", globals_ubo);
404                 DRW_shgroup_uniform_float(*r_facedot_shgrp, "edgeScale", edge_width_scale, 1);
405                 DRW_shgroup_state_enable(*r_facedot_shgrp, DRW_STATE_WRITE_DEPTH);
406                 if (rv3d->rflag & RV3D_CLIPPING) {
407                         DRW_shgroup_world_clip_planes_from_rv3d(*r_facedot_shgrp, rv3d);
408                 }
409         }
410
411         *r_face_shgrp = DRW_shgroup_create(tri_sh, pass);
412         DRW_shgroup_uniform_block(*r_face_shgrp, "globalsBlock", globals_ubo);
413         DRW_shgroup_uniform_vec2(*r_face_shgrp, "viewportSize", DRW_viewport_size_get(), 1);
414         DRW_shgroup_uniform_float(*r_face_shgrp, "faceAlphaMod", face_alpha, 1);
415         DRW_shgroup_uniform_float(*r_face_shgrp, "edgeScale", edge_width_scale, 1);
416         DRW_shgroup_uniform_ivec4(*r_face_shgrp, "dataMask", data_mask, 1);
417         DRW_shgroup_uniform_bool_copy(*r_face_shgrp, "doEdges", do_edges);
418         if (!fast_mode) {
419                 DRW_shgroup_uniform_bool_copy(*r_face_shgrp, "isXray", xray);
420         }
421         else {
422                 /* To be able to use triple load. */
423                 DRW_shgroup_state_enable(*r_face_shgrp, DRW_STATE_FIRST_VERTEX_CONVENTION);
424         }
425         if (rv3d->rflag & RV3D_CLIPPING) {
426                 DRW_shgroup_world_clip_planes_from_rv3d(*r_face_shgrp, rv3d);
427         }
428
429         /* Cage geom needs to be offseted to avoid Z-fighting. */
430         *r_face_cage_shgrp = DRW_shgroup_create_sub(*r_face_shgrp);
431         DRW_shgroup_state_enable(*r_face_cage_shgrp, DRW_STATE_OFFSET_NEGATIVE);
432
433         *r_ledges_shgrp = DRW_shgroup_create(ledge_sh, pass);
434         DRW_shgroup_uniform_block(*r_ledges_shgrp, "globalsBlock", globals_ubo);
435         DRW_shgroup_uniform_vec2(*r_ledges_shgrp, "viewportSize", DRW_viewport_size_get(), 1);
436         DRW_shgroup_uniform_float(*r_ledges_shgrp, "edgeScale", edge_width_scale, 1);
437         DRW_shgroup_uniform_ivec4(*r_ledges_shgrp, "dataMask", data_mask, 1);
438         DRW_shgroup_uniform_bool_copy(*r_ledges_shgrp, "doEdges", do_edges);
439         if (rv3d->rflag & RV3D_CLIPPING) {
440                 DRW_shgroup_world_clip_planes_from_rv3d(*r_ledges_shgrp, rv3d);
441         }
442
443         return pass;
444 }
445
446 static float backwire_opacity;
447 static float face_mod;
448 static float size_normal;
449
450 static void EDIT_MESH_cache_init(void *vedata)
451 {
452         EDIT_MESH_PassList *psl = ((EDIT_MESH_Data *)vedata)->psl;
453         EDIT_MESH_StorageList *stl = ((EDIT_MESH_Data *)vedata)->stl;
454         DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
455
456         const DRWContextState *draw_ctx = DRW_context_state_get();
457         View3D *v3d = draw_ctx->v3d;
458         RegionView3D *rv3d = draw_ctx->rv3d;
459         Scene *scene = draw_ctx->scene;
460         ToolSettings *tsettings = scene->toolsettings;
461         EDIT_MESH_Shaders *sh_data = &e_data.sh_data[EDIT_MESH_sh_data_index_from_rv3d(draw_ctx->rv3d)];
462         static float zero = 0.0f;
463
464         if (!stl->g_data) {
465                 /* Alloc transient pointers */
466                 stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
467         }
468         stl->g_data->ghost_ob = 0;
469         stl->g_data->edit_ob = 0;
470         stl->g_data->do_faces = true;
471         stl->g_data->do_edges = true;
472
473         stl->g_data->do_zbufclip = ((v3d)->shading.flag & XRAY_FLAG(v3d)) != 0;
474
475         /* Applies on top of the theme edge width, so edge-mode can have thick edges. */
476         stl->g_data->edge_width_scale = (tsettings->selectmode & (SCE_SELECT_EDGE)) ? 1.75f : 1.0f;
477
478         stl->g_data->data_mask[0] = 0xFF; /* Face Flag */
479         stl->g_data->data_mask[1] = 0xFF; /* Edge Flag */
480         stl->g_data->data_mask[2] = 0xFF; /* Crease */
481         stl->g_data->data_mask[3] = 0xFF; /* BWeight */
482
483         if (draw_ctx->object_edit->type == OB_MESH) {
484                 if (BKE_object_is_in_editmode(draw_ctx->object_edit)) {
485                         if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FREESTYLE_FACE) == 0) {
486                                 stl->g_data->data_mask[0] &= ~VFLAG_FACE_FREESTYLE;
487                         }
488                         if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACES) == 0) {
489                                 stl->g_data->data_mask[0] &= ~(VFLAG_FACE_SELECTED & VFLAG_FACE_FREESTYLE);
490                                 stl->g_data->do_faces = false;
491                         }
492                         if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_SEAMS) == 0) {
493                                 stl->g_data->data_mask[1] &= ~VFLAG_EDGE_SEAM;
494                         }
495                         if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_SHARP) == 0) {
496                                 stl->g_data->data_mask[1] &= ~VFLAG_EDGE_SHARP;
497                         }
498                         if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FREESTYLE_EDGE) == 0) {
499                                 stl->g_data->data_mask[1] &= ~VFLAG_EDGE_FREESTYLE;
500                         }
501                         if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_EDGES) == 0) {
502                                 if ((tsettings->selectmode & SCE_SELECT_EDGE) == 0) {
503                                         stl->g_data->data_mask[1] &= ~(VFLAG_EDGE_ACTIVE & VFLAG_EDGE_SELECTED);
504                                         stl->g_data->do_edges = false;
505                                 }
506                         }
507                         if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_CREASES) == 0) {
508                                 stl->g_data->data_mask[2] = 0x0;
509                         }
510                         if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_BWEIGHTS) == 0) {
511                                 stl->g_data->data_mask[3] = 0x0;
512                         }
513                 }
514         }
515
516         {
517                 psl->weight_faces = DRW_pass_create(
518                         "Weight Pass",
519                         DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL);
520
521                 stl->g_data->fweights_shgrp = DRW_shgroup_create(sh_data->weight_face, psl->weight_faces);
522
523                 static float alpha = 1.0f;
524                 DRW_shgroup_uniform_float(stl->g_data->fweights_shgrp, "opacity", &alpha, 1);
525                 DRW_shgroup_uniform_texture(stl->g_data->fweights_shgrp, "colorramp", globals_weight_ramp);
526                 DRW_shgroup_uniform_block(stl->g_data->fweights_shgrp, "globalsBlock", globals_ubo);
527                 if (rv3d->rflag & RV3D_CLIPPING) {
528                         DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->fweights_shgrp, rv3d);
529                 }
530         }
531
532         {
533                 /* Complementary Depth Pass */
534                 psl->depth_hidden_wire = DRW_pass_create(
535                         "Depth Pass Hidden Wire",
536                         DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK);
537                 stl->g_data->depth_shgrp_hidden_wire = DRW_shgroup_create(sh_data->depth, psl->depth_hidden_wire);
538         }
539
540         {
541                 /* Depth clearing for ghosting. */
542                 psl->ghost_clear_depth = DRW_pass_create(
543                         "Ghost Depth Clear",
544                         DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS | DRW_STATE_STENCIL_NEQUAL);
545
546                 DRWShadingGroup *shgrp = DRW_shgroup_create(sh_data->ghost_clear_depth, psl->ghost_clear_depth);
547                 DRW_shgroup_stencil_mask(shgrp, 0x00);
548                 DRW_shgroup_call_add(shgrp, DRW_cache_fullscreen_quad_get(), NULL);
549         }
550
551         {
552                 /* Normals */
553                 psl->normals = DRW_pass_create(
554                         "Edit Mesh Normals Pass",
555                         DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL);
556
557                 stl->g_data->fnormals_shgrp = DRW_shgroup_create(sh_data->normals_face, psl->normals);
558                 DRW_shgroup_uniform_float(stl->g_data->fnormals_shgrp, "normalSize", &size_normal, 1);
559                 DRW_shgroup_uniform_vec4(stl->g_data->fnormals_shgrp, "color", ts.colorNormal, 1);
560                 if (rv3d->rflag & RV3D_CLIPPING) {
561                         DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->fnormals_shgrp, rv3d);
562                 }
563
564                 stl->g_data->vnormals_shgrp = DRW_shgroup_create(sh_data->normals, psl->normals);
565                 DRW_shgroup_uniform_float(stl->g_data->vnormals_shgrp, "normalSize", &size_normal, 1);
566                 DRW_shgroup_uniform_vec4(stl->g_data->vnormals_shgrp, "color", ts.colorVNormal, 1);
567                 if (rv3d->rflag & RV3D_CLIPPING) {
568                         DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->vnormals_shgrp, rv3d);
569                 }
570
571                 stl->g_data->lnormals_shgrp = DRW_shgroup_create(sh_data->normals_loop, psl->normals);
572                 DRW_shgroup_uniform_float(stl->g_data->lnormals_shgrp, "normalSize", &size_normal, 1);
573                 DRW_shgroup_uniform_vec4(stl->g_data->lnormals_shgrp, "color", ts.colorLNormal, 1);
574                 if (rv3d->rflag & RV3D_CLIPPING) {
575                         DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->lnormals_shgrp, rv3d);
576                 }
577         }
578
579         if (!stl->g_data->do_zbufclip) {
580                 psl->edit_face_overlay = edit_mesh_create_overlay_pass(
581                         &face_mod, &stl->g_data->edge_width_scale, stl->g_data->data_mask, stl->g_data->do_edges, false,
582                         DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND,
583                         &stl->g_data->face_shgrp,
584                         &stl->g_data->face_cage_shgrp,
585                         &stl->g_data->verts_shgrp,
586                         &stl->g_data->ledges_shgrp,
587                         &stl->g_data->lverts_shgrp,
588                         &stl->g_data->facedot_shgrp);
589         }
590         else {
591                 /* We render all wires with depth and opaque to a new fbo and blend the result based on depth values */
592                 psl->edit_face_occluded = edit_mesh_create_overlay_pass(
593                         &zero, &stl->g_data->edge_width_scale, stl->g_data->data_mask, stl->g_data->do_edges, true,
594                         DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_WRITE_DEPTH,
595                         &stl->g_data->face_shgrp,
596                         &stl->g_data->face_cage_shgrp,
597                         &stl->g_data->verts_shgrp,
598                         &stl->g_data->ledges_shgrp,
599                         &stl->g_data->lverts_shgrp,
600                         &stl->g_data->facedot_shgrp);
601
602                 /* however we loose the front faces value (because we need the depth of occluded wires and
603                  * faces are alpha blended ) so we recover them in a new pass. */
604                 psl->facefill_occlude = DRW_pass_create(
605                         "Front Face Color",
606                         DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND);
607                 stl->g_data->facefill_occluded_shgrp = DRW_shgroup_create(sh_data->overlay_facefill, psl->facefill_occlude);
608                 DRW_shgroup_uniform_block(stl->g_data->facefill_occluded_shgrp, "globalsBlock", globals_ubo);
609                 DRW_shgroup_uniform_ivec4(stl->g_data->facefill_occluded_shgrp, "dataMask", stl->g_data->data_mask, 1);
610                 if (rv3d->rflag & RV3D_CLIPPING) {
611                         DRW_shgroup_world_clip_planes_from_rv3d(stl->g_data->facefill_occluded_shgrp, rv3d);
612                 }
613
614                 /* we need a full screen pass to combine the result */
615                 struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
616
617                 psl->mix_occlude = DRW_pass_create(
618                         "Mix Occluded Wires",
619                         DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND);
620                 DRWShadingGroup *mix_shgrp = DRW_shgroup_create(sh_data->overlay_mix, psl->mix_occlude);
621                 DRW_shgroup_call_add(mix_shgrp, quad, NULL);
622                 DRW_shgroup_uniform_float(mix_shgrp, "alpha", &backwire_opacity, 1);
623                 DRW_shgroup_uniform_texture_ref(mix_shgrp, "wireColor", &e_data.occlude_wire_color_tx);
624                 DRW_shgroup_uniform_texture_ref(mix_shgrp, "wireDepth", &e_data.occlude_wire_depth_tx);
625                 DRW_shgroup_uniform_texture_ref(mix_shgrp, "sceneDepth", &dtxl->depth);
626         }
627 }
628
629 static void edit_mesh_add_ob_to_pass(
630         Scene *scene, Object *ob,
631         EDIT_MESH_PrivateData *g_data,
632         DRWShadingGroup *facedot_shgrp,
633         DRWShadingGroup *facefill_shgrp)
634 {
635         struct GPUBatch *geom_tris, *geom_verts, *geom_ledges, *geom_ledges_nor, *geom_lverts, *geom_fcenter;
636         ToolSettings *tsettings = scene->toolsettings;
637
638         bool has_edit_mesh_cage = false;
639         /* TODO: Should be its own function. */
640         Mesh *me = (Mesh *)ob->data;
641         BMEditMesh *embm = me->edit_btmesh;
642         if (embm) {
643                 has_edit_mesh_cage = embm->mesh_eval_cage && (embm->mesh_eval_cage != embm->mesh_eval_final);
644         }
645
646         DRWShadingGroup *face_shgrp = (has_edit_mesh_cage) ? g_data->face_cage_shgrp : g_data->face_shgrp;
647         DRWShadingGroup *verts_shgrp = g_data->verts_shgrp;
648         DRWShadingGroup *ledges_shgrp = g_data->ledges_shgrp;
649         DRWShadingGroup *lverts_shgrp = g_data->lverts_shgrp;
650
651         geom_tris = DRW_mesh_batch_cache_get_edit_triangles(ob->data);
652         geom_ledges = DRW_mesh_batch_cache_get_edit_loose_edges(ob->data);
653         DRW_shgroup_call_add(face_shgrp, geom_tris, ob->obmat);
654         DRW_shgroup_call_add(ledges_shgrp, geom_ledges, ob->obmat);
655
656         if (facefill_shgrp) {
657                 DRW_shgroup_call_add(facefill_shgrp, geom_tris, ob->obmat);
658         }
659
660         if ((tsettings->selectmode & SCE_SELECT_VERTEX) != 0) {
661                 /* Thoses are point batches. */
662                 geom_verts = DRW_mesh_batch_cache_get_edit_vertices(ob->data);
663                 geom_ledges_nor = DRW_mesh_batch_cache_get_edit_loose_edges_nor(ob->data);
664                 geom_lverts = DRW_mesh_batch_cache_get_edit_loose_verts(ob->data);
665                 DRW_shgroup_call_add(verts_shgrp, geom_verts, ob->obmat);
666                 DRW_shgroup_call_add(lverts_shgrp, geom_ledges_nor, ob->obmat);
667                 DRW_shgroup_call_add(lverts_shgrp, geom_lverts, ob->obmat);
668         }
669
670         if (facedot_shgrp && (tsettings->selectmode & SCE_SELECT_FACE) != 0 ) {
671                 geom_fcenter = DRW_mesh_batch_cache_get_edit_facedots(ob->data);
672                 DRW_shgroup_call_add(facedot_shgrp, geom_fcenter, ob->obmat);
673         }
674 }
675
676 static void EDIT_MESH_cache_populate(void *vedata, Object *ob)
677 {
678         EDIT_MESH_StorageList *stl = ((EDIT_MESH_Data *)vedata)->stl;
679         const DRWContextState *draw_ctx = DRW_context_state_get();
680         View3D *v3d = draw_ctx->v3d;
681         Scene *scene = draw_ctx->scene;
682         ToolSettings *tsettings = scene->toolsettings;
683         struct GPUBatch *geom;
684
685         if (ob->type == OB_MESH) {
686                 if ((ob == draw_ctx->object_edit) || BKE_object_is_in_editmode(ob)) {
687                         bool do_occlude_wire = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_OCCLUDE_WIRE) != 0;
688                         bool do_show_weight = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_WEIGHT) != 0;
689                         bool fnormals_do = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_NORMALS) != 0;
690                         bool vnormals_do = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_VERT_NORMALS) != 0;
691                         bool lnormals_do = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_LOOP_NORMALS) != 0;
692
693                         bool show_face_dots = (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) != 0;
694
695                         if (stl->g_data->do_faces == false &&
696                             stl->g_data->do_edges == false &&
697                             (tsettings->selectmode & SCE_SELECT_FACE))
698                         {
699                                 /* Force display of face centers in this case because that's
700                                  * the only way to see if a face is selected. */
701                                 show_face_dots = true;
702                         }
703
704                         /* Updating uniform */
705                         backwire_opacity = v3d->overlay.backwire_opacity;
706                         size_normal = v3d->overlay.normals_length;
707
708                         face_mod = (do_occlude_wire) ? 0.0f : 1.0f;
709
710                         if (!stl->g_data->do_faces) {
711                                 face_mod = 0.0f;
712                         }
713
714                         if (do_show_weight) {
715                                 geom = DRW_cache_mesh_surface_weights_get(ob);
716                                 DRW_shgroup_call_add(stl->g_data->fweights_shgrp, geom, ob->obmat);
717                         }
718
719                         if (do_occlude_wire) {
720                                 geom = DRW_cache_mesh_surface_get(ob);
721                                 DRW_shgroup_call_add(stl->g_data->depth_shgrp_hidden_wire, geom, ob->obmat);
722                         }
723
724                         if (vnormals_do) {
725                                 geom = DRW_mesh_batch_cache_get_edit_triangles_nor(ob->data);
726                                 DRW_shgroup_call_add(stl->g_data->vnormals_shgrp, geom, ob->obmat);
727                                 geom = DRW_mesh_batch_cache_get_edit_loose_verts(ob->data);
728                                 DRW_shgroup_call_add(stl->g_data->vnormals_shgrp, geom, ob->obmat);
729                                 geom = DRW_mesh_batch_cache_get_edit_loose_edges_nor(ob->data);
730                                 DRW_shgroup_call_add(stl->g_data->vnormals_shgrp, geom, ob->obmat);
731                         }
732                         if (lnormals_do) {
733                                 geom = DRW_mesh_batch_cache_get_edit_triangles_lnor(ob->data);
734                                 DRW_shgroup_call_add(stl->g_data->lnormals_shgrp, geom, ob->obmat);
735                         }
736                         if (fnormals_do) {
737                                 geom = DRW_mesh_batch_cache_get_edit_facedots(ob->data);
738                                 DRW_shgroup_call_add(stl->g_data->fnormals_shgrp, geom, ob->obmat);
739                         }
740
741                         if (stl->g_data->do_zbufclip) {
742                                 edit_mesh_add_ob_to_pass(
743                                         scene, ob, stl->g_data,
744                                         stl->g_data->facedot_shgrp,
745                                         (stl->g_data->do_faces) ? stl->g_data->facefill_occluded_shgrp : NULL);
746                         }
747                         else {
748                                 edit_mesh_add_ob_to_pass(
749                                         scene, ob, stl->g_data,
750                                         (show_face_dots) ? stl->g_data->facedot_shgrp : NULL,
751                                         NULL);
752                         }
753
754                         stl->g_data->ghost_ob += (ob->dtx & OB_DRAWXRAY) ? 1 : 0;
755                         stl->g_data->edit_ob += 1;
756
757                         /* 3D text overlay */
758                         if (v3d->overlay.edit_flag & (V3D_OVERLAY_EDIT_EDGE_LEN |
759                                                       V3D_OVERLAY_EDIT_FACE_AREA |
760                                                       V3D_OVERLAY_EDIT_FACE_ANG |
761                                                       V3D_OVERLAY_EDIT_EDGE_ANG |
762                                                       V3D_OVERLAY_EDIT_INDICES))
763                         {
764                                 if (DRW_state_show_text()) {
765                                         DRW_edit_mesh_mode_text_measure_stats(
766                                                draw_ctx->ar, v3d, ob, &scene->unit);
767                                 }
768                         }
769                 }
770         }
771 }
772
773 static void EDIT_MESH_draw_scene(void *vedata)
774 {
775         EDIT_MESH_PassList *psl = ((EDIT_MESH_Data *)vedata)->psl;
776         EDIT_MESH_StorageList *stl = ((EDIT_MESH_Data *)vedata)->stl;
777         EDIT_MESH_FramebufferList *fbl = ((EDIT_MESH_Data *)vedata)->fbl;
778         DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
779         DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
780
781         DRW_draw_pass(psl->weight_faces);
782
783         DRW_draw_pass(psl->depth_hidden_wire);
784
785         if (stl->g_data->do_zbufclip) {
786                 float clearcol[4] = {0.0f, 0.0f, 0.0f, 0.0f};
787                 /* render facefill */
788                 DRW_draw_pass(psl->facefill_occlude);
789
790                 /* Render wires on a separate framebuffer */
791                 GPU_framebuffer_bind(fbl->occlude_wire_fb);
792                 GPU_framebuffer_clear_color_depth(fbl->occlude_wire_fb, clearcol, 1.0f);
793                 DRW_draw_pass(psl->normals);
794                 DRW_draw_pass(psl->edit_face_occluded);
795
796                 /* Combine with scene buffer */
797                 GPU_framebuffer_bind(dfbl->color_only_fb);
798                 DRW_draw_pass(psl->mix_occlude);
799         }
800         else {
801                 DRW_draw_pass(psl->normals);
802
803                 const DRWContextState *draw_ctx = DRW_context_state_get();
804                 View3D *v3d = draw_ctx->v3d;
805
806                 if (v3d->shading.type == OB_SOLID && (v3d->shading.flag & XRAY_FLAG(v3d)) == 0) {
807                         if (stl->g_data->ghost_ob == 1 && stl->g_data->edit_ob == 1) {
808                                 /* In the case of single ghost object edit (common case for retopology):
809                                  * we duplicate the depht+stencil buffer and clear all depth to 1.0f where
810                                  * the stencil buffer is no 0x00. */
811                                 const float *viewport_size = DRW_viewport_size_get();
812                                 const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
813                                 struct GPUTexture *ghost_depth_tx = DRW_texture_pool_query_2D(size[0], size[1], GPU_DEPTH24_STENCIL8, &draw_engine_edit_mesh_type);
814                                 GPU_framebuffer_ensure_config(&fbl->ghost_wire_fb, {
815                                         GPU_ATTACHMENT_TEXTURE(ghost_depth_tx),
816                                         GPU_ATTACHMENT_TEXTURE(dtxl->color),
817                                 });
818
819                                 GPU_framebuffer_blit(dfbl->depth_only_fb, 0, fbl->ghost_wire_fb, 0, GPU_DEPTH_BIT | GPU_STENCIL_BIT);
820                                 GPU_framebuffer_bind(fbl->ghost_wire_fb);
821
822                                 DRW_draw_pass(psl->ghost_clear_depth);
823                         }
824                 }
825
826                 DRW_draw_pass(psl->edit_face_overlay);
827         }
828
829         DRW_state_clip_planes_reset();
830 }
831
832 static void EDIT_MESH_engine_free(void)
833 {
834         for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) {
835                 EDIT_MESH_Shaders *sh_data = &e_data.sh_data[sh_data_index];
836                 /* Don't free builtins. */
837                 sh_data->depth = NULL;
838                 GPUShader **sh_data_as_array = (GPUShader **)sh_data;
839                 for (int i = 0; i < (sizeof(EDIT_MESH_Shaders) / sizeof(GPUShader *)); i++) {
840                         DRW_SHADER_FREE_SAFE(sh_data_as_array[i]);
841                 }
842         }
843 }
844
845 static const DrawEngineDataSize EDIT_MESH_data_size = DRW_VIEWPORT_DATA_SIZE(EDIT_MESH_Data);
846
847 DrawEngineType draw_engine_edit_mesh_type = {
848         NULL, NULL,
849         N_("EditMeshMode"),
850         &EDIT_MESH_data_size,
851         &EDIT_MESH_engine_init,
852         &EDIT_MESH_engine_free,
853         &EDIT_MESH_cache_init,
854         &EDIT_MESH_cache_populate,
855         NULL,
856         NULL,
857         &EDIT_MESH_draw_scene,
858         NULL,
859         NULL,
860 };