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