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