3D View: add opacity for sculpt mask display
[blender.git] / source / blender / draw / modes / sculpt_mode.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * Copyright 2016, Blender Foundation.
17  */
18
19 /** \file
20  * \ingroup draw
21  */
22
23 #include "DRW_engine.h"
24 #include "DRW_render.h"
25
26 #include "DNA_object_types.h"
27 #include "DNA_mesh_types.h"
28 #include "DNA_meshdata_types.h"
29
30 #include "BKE_pbvh.h"
31 #include "BKE_paint.h"
32 #include "BKE_subdiv_ccg.h"
33
34 /* If builtin shaders are needed */
35 #include "GPU_shader.h"
36
37 #include "draw_common.h"
38 #include "draw_mode_engines.h"
39
40 extern char datatoc_sculpt_mask_vert_glsl[];
41 extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[];
42
43 /* *********** LISTS *********** */
44 /* All lists are per viewport specific datas.
45  * They are all free when viewport changes engines
46  * or is free itself. Use SCULPT_engine_init() to
47  * initialize most of them and SCULPT_cache_init()
48  * for SCULPT_PassList */
49
50 typedef struct SCULPT_PassList {
51   /* Declare all passes here and init them in
52    * SCULPT_cache_init().
53    * Only contains (DRWPass *) */
54   struct DRWPass *pass;
55 } SCULPT_PassList;
56
57 typedef struct SCULPT_FramebufferList {
58   /* Contains all framebuffer objects needed by this engine.
59    * Only contains (GPUFrameBuffer *) */
60   struct GPUFrameBuffer *fb;
61 } SCULPT_FramebufferList;
62
63 typedef struct SCULPT_TextureList {
64   /* Contains all framebuffer textures / utility textures
65    * needed by this engine. Only viewport specific textures
66    * (not per object). Only contains (GPUTexture *) */
67   struct GPUTexture *texture;
68 } SCULPT_TextureList;
69
70 typedef struct SCULPT_StorageList {
71   /* Contains any other memory block that the engine needs.
72    * Only directly MEM_(m/c)allocN'ed blocks because they are
73    * free with MEM_freeN() when viewport is freed.
74    * (not per object) */
75   struct CustomStruct *block;
76   struct SCULPT_PrivateData *g_data;
77 } SCULPT_StorageList;
78
79 typedef struct SCULPT_Data {
80   /* Struct returned by DRW_viewport_engine_data_ensure.
81    * If you don't use one of these, just make it a (void *) */
82   // void *fbl;
83   void *engine_type; /* Required */
84   SCULPT_FramebufferList *fbl;
85   SCULPT_TextureList *txl;
86   SCULPT_PassList *psl;
87   SCULPT_StorageList *stl;
88 } SCULPT_Data;
89
90 /* *********** STATIC *********** */
91
92 static struct {
93   /* Custom shaders :
94    * Add sources to source/blender/draw/modes/shaders
95    * init in SCULPT_engine_init();
96    * free in SCULPT_engine_free(); */
97   struct GPUShader *shader_smooth;
98 } e_data = {NULL}; /* Engine data */
99
100 typedef struct SCULPT_PrivateData {
101   /* This keeps the references of the shading groups for
102    * easy access in SCULPT_cache_populate() */
103   DRWShadingGroup *group_flat;
104   DRWShadingGroup *group_smooth;
105 } SCULPT_PrivateData; /* Transient data */
106
107 /* *********** FUNCTIONS *********** */
108
109 /* Init Textures, Framebuffers, Storage and Shaders.
110  * It is called for every frames.
111  * (Optional) */
112 static void SCULPT_engine_init(void *vedata)
113 {
114   SCULPT_TextureList *txl = ((SCULPT_Data *)vedata)->txl;
115   SCULPT_FramebufferList *fbl = ((SCULPT_Data *)vedata)->fbl;
116   SCULPT_StorageList *stl = ((SCULPT_Data *)vedata)->stl;
117
118   UNUSED_VARS(txl, fbl, stl);
119
120   if (!e_data.shader_smooth) {
121     e_data.shader_smooth = DRW_shader_create(
122         datatoc_sculpt_mask_vert_glsl, NULL, datatoc_gpu_shader_3D_smooth_color_frag_glsl, NULL);
123   }
124 }
125
126 /* Here init all passes and shading groups
127  * Assume that all Passes are NULL */
128 static void SCULPT_cache_init(void *vedata)
129 {
130   SCULPT_PassList *psl = ((SCULPT_Data *)vedata)->psl;
131   SCULPT_StorageList *stl = ((SCULPT_Data *)vedata)->stl;
132
133   if (!stl->g_data) {
134     stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
135   }
136
137   {
138     const DRWContextState *draw_ctx = DRW_context_state_get();
139     View3D *v3d = draw_ctx->v3d;
140
141     DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_MULTIPLY;
142     psl->pass = DRW_pass_create("Sculpt Pass", state);
143
144     DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.shader_smooth, psl->pass);
145     DRW_shgroup_uniform_float(shgrp, "maskOpacity", &v3d->overlay.sculpt_mode_mask_opacity, 1);
146     stl->g_data->group_smooth = shgrp;
147   }
148 }
149
150 static void sculpt_draw_mask_cb(DRWShadingGroup *shgroup,
151                                 void (*draw_fn)(DRWShadingGroup *shgroup, struct GPUBatch *geom),
152                                 void *user_data)
153 {
154   Object *ob = user_data;
155   PBVH *pbvh = ob->sculpt->pbvh;
156
157   if (pbvh) {
158     BKE_pbvh_draw_cb(pbvh,
159                      NULL,
160                      NULL,
161                      false,
162                      false,
163                      true,
164                      (void (*)(void *, struct GPUBatch *))draw_fn,
165                      shgroup);
166   }
167 }
168
169 static void sculpt_update_pbvh_normals(Object *object)
170 {
171   Mesh *mesh = object->data;
172   PBVH *pbvh = object->sculpt->pbvh;
173   SubdivCCG *subdiv_ccg = mesh->runtime.subdiv_ccg;
174   if (pbvh == NULL || subdiv_ccg == NULL) {
175     return;
176   }
177   BKE_sculpt_bvh_update_from_ccg(pbvh, subdiv_ccg);
178   struct CCGFace **faces;
179   int num_faces;
180   BKE_pbvh_get_grid_updates(pbvh, 1, (void ***)&faces, &num_faces);
181   if (num_faces > 0) {
182     BKE_subdiv_ccg_update_normals(subdiv_ccg, faces, num_faces);
183     MEM_freeN(faces);
184   }
185 }
186
187 /* Add geometry to shadingGroups. Execute for each objects */
188 static void SCULPT_cache_populate(void *vedata, Object *ob)
189 {
190   SCULPT_PassList *psl = ((SCULPT_Data *)vedata)->psl;
191   SCULPT_StorageList *stl = ((SCULPT_Data *)vedata)->stl;
192
193   UNUSED_VARS(psl, stl);
194
195   if (ob->type == OB_MESH) {
196     const DRWContextState *draw_ctx = DRW_context_state_get();
197
198     if (ob->sculpt && (ob == draw_ctx->obact)) {
199       sculpt_update_pbvh_normals(ob);
200
201       /* XXX, needed for dyntopo-undo (which clears).
202        * probably depsgraph should handlle? in 2.7x getting derived-mesh does this (mesh_build_data) */
203       if (ob->sculpt->pbvh == NULL) {
204         /* create PBVH immediately (would be created on the fly too,
205          * but this avoids waiting on first stroke) */
206         Scene *scene = draw_ctx->scene;
207
208         BKE_sculpt_update_mesh_elements(
209             draw_ctx->depsgraph, scene, scene->toolsettings->sculpt, ob, false, false);
210       }
211
212       PBVH *pbvh = ob->sculpt->pbvh;
213       if (pbvh && pbvh_has_mask(pbvh)) {
214         DRW_shgroup_call_generate_add(
215             stl->g_data->group_smooth, sculpt_draw_mask_cb, ob, ob->obmat);
216       }
217     }
218   }
219 }
220
221 /* Optional: Post-cache_populate callback */
222 static void SCULPT_cache_finish(void *vedata)
223 {
224   SCULPT_PassList *psl = ((SCULPT_Data *)vedata)->psl;
225   SCULPT_StorageList *stl = ((SCULPT_Data *)vedata)->stl;
226
227   /* Do something here! dependent on the objects gathered */
228   UNUSED_VARS(psl, stl);
229 }
230
231 /* Draw time ! Control rendering pipeline from here */
232 static void SCULPT_draw_scene(void *vedata)
233 {
234   SCULPT_PassList *psl = ((SCULPT_Data *)vedata)->psl;
235   SCULPT_FramebufferList *fbl = ((SCULPT_Data *)vedata)->fbl;
236
237   /* Default framebuffer and texture */
238   DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
239   DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
240
241   UNUSED_VARS(fbl, dfbl, dtxl);
242
243   /* Show / hide entire passes, swap framebuffers ... whatever you fancy */
244   /*
245    * DRW_framebuffer_texture_detach(dtxl->depth);
246    * DRW_framebuffer_bind(fbl->custom_fb);
247    * DRW_draw_pass(psl->pass);
248    * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0);
249    * DRW_framebuffer_bind(dfbl->default_fb);
250    */
251
252   /* ... or just render passes on default framebuffer. */
253   DRW_draw_pass(psl->pass);
254
255   /* If you changed framebuffer, double check you rebind
256    * the default one with its textures attached before finishing */
257 }
258
259 /* Cleanup when destroying the engine.
260  * This is not per viewport ! only when quitting blender.
261  * Mostly used for freeing shaders */
262 static void SCULPT_engine_free(void)
263 {
264   DRW_SHADER_FREE_SAFE(e_data.shader_smooth);
265 }
266
267 static const DrawEngineDataSize SCULPT_data_size = DRW_VIEWPORT_DATA_SIZE(SCULPT_Data);
268
269 DrawEngineType draw_engine_sculpt_type = {
270     NULL,
271     NULL,
272     N_("SculptMode"),
273     &SCULPT_data_size,
274     &SCULPT_engine_init,
275     &SCULPT_engine_free,
276     &SCULPT_cache_init,
277     &SCULPT_cache_populate,
278     &SCULPT_cache_finish,
279     NULL, /* draw_background but not needed by mode engines */
280     &SCULPT_draw_scene,
281     NULL,
282     NULL,
283 };