Mesh Batch Cache: Port Texture paint batches to new batch request
[blender.git] / source / blender / draw / modes / paint_texture_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/paint_texture_mode.c
23  *  \ingroup draw
24  */
25
26 #include "DRW_engine.h"
27 #include "DRW_render.h"
28
29 #include "BIF_gl.h"
30
31 /* If builtin shaders are needed */
32 #include "GPU_shader.h"
33 #include "GPU_texture.h"
34
35 #include "draw_common.h"
36
37 #include "draw_mode_engines.h"
38
39 #include "DNA_mesh_types.h"
40
41 #include "DEG_depsgraph_query.h"
42
43 extern char datatoc_common_globals_lib_glsl[];
44 extern char datatoc_paint_texture_vert_glsl[];
45 extern char datatoc_paint_texture_frag_glsl[];
46 extern char datatoc_paint_wire_vert_glsl[];
47 extern char datatoc_paint_wire_frag_glsl[];
48
49 /* If needed, contains all global/Theme colors
50  * Add needed theme colors / values to DRW_globals_update() and update UBO
51  * Not needed for constant color. */
52 extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
53 extern struct GlobalsUboStorage ts; /* draw_common.c */
54
55 /* *********** LISTS *********** */
56 /* All lists are per viewport specific datas.
57  * They are all free when viewport changes engines
58  * or is free itself. Use PAINT_TEXTURE_engine_init() to
59  * initialize most of them and PAINT_TEXTURE_cache_init()
60  * for PAINT_TEXTURE_PassList */
61
62 typedef struct PAINT_TEXTURE_PassList {
63         /* Declare all passes here and init them in
64          * PAINT_TEXTURE_cache_init().
65          * Only contains (DRWPass *) */
66         struct DRWPass *image_faces;
67
68         struct DRWPass *wire_overlay;
69         struct DRWPass *face_overlay;
70 } PAINT_TEXTURE_PassList;
71
72 typedef struct PAINT_TEXTURE_FramebufferList {
73         /* Contains all framebuffer objects needed by this engine.
74          * Only contains (GPUFrameBuffer *) */
75         struct GPUFrameBuffer *fb;
76 } PAINT_TEXTURE_FramebufferList;
77
78 typedef struct PAINT_TEXTURE_TextureList {
79         /* Contains all framebuffer textures / utility textures
80          * needed by this engine. Only viewport specific textures
81          * (not per object). Only contains (GPUTexture *) */
82         struct GPUTexture *texture;
83 } PAINT_TEXTURE_TextureList;
84
85 typedef struct PAINT_TEXTURE_StorageList {
86         /* Contains any other memory block that the engine needs.
87          * Only directly MEM_(m/c)allocN'ed blocks because they are
88          * free with MEM_freeN() when viewport is freed.
89          * (not per object) */
90         struct CustomStruct *block;
91         struct PAINT_TEXTURE_PrivateData *g_data;
92 } PAINT_TEXTURE_StorageList;
93
94 typedef struct PAINT_TEXTURE_Data {
95         /* Struct returned by DRW_viewport_engine_data_ensure.
96          * If you don't use one of these, just make it a (void *) */
97         // void *fbl;
98         void *engine_type; /* Required */
99         PAINT_TEXTURE_FramebufferList *fbl;
100         PAINT_TEXTURE_TextureList *txl;
101         PAINT_TEXTURE_PassList *psl;
102         PAINT_TEXTURE_StorageList *stl;
103 } PAINT_TEXTURE_Data;
104
105 /* *********** STATIC *********** */
106
107 static struct {
108         /* Custom shaders :
109          * Add sources to source/blender/draw/modes/shaders
110          * init in PAINT_TEXTURE_engine_init();
111          * free in PAINT_TEXTURE_engine_free(); */
112         struct GPUShader *fallback_sh;
113         struct GPUShader *image_sh;
114
115         struct GPUShader *wire_overlay_shader;
116         struct GPUShader *face_overlay_shader;
117 } e_data = {NULL}; /* Engine data */
118
119 typedef struct PAINT_TEXTURE_PrivateData {
120         /* This keeps the references of the shading groups for
121          * easy access in PAINT_TEXTURE_cache_populate() */
122         DRWShadingGroup *shgroup_fallback;
123         DRWShadingGroup **shgroup_image_array;
124
125         /* face-mask  */
126         DRWShadingGroup *lwire_shgrp;
127         DRWShadingGroup *face_shgrp;
128 } PAINT_TEXTURE_PrivateData; /* Transient data */
129
130 /* *********** FUNCTIONS *********** */
131
132 /* Init Textures, Framebuffers, Storage and Shaders.
133  * It is called for every frames.
134  * (Optional) */
135 static void PAINT_TEXTURE_engine_init(void *vedata)
136 {
137         PAINT_TEXTURE_TextureList *txl = ((PAINT_TEXTURE_Data *)vedata)->txl;
138         PAINT_TEXTURE_FramebufferList *fbl = ((PAINT_TEXTURE_Data *)vedata)->fbl;
139         PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl;
140
141         UNUSED_VARS(txl, fbl, stl);
142
143         /* Init Framebuffers like this: order is attachment order (for color texs) */
144         /*
145          * DRWFboTexture tex[2] = {{&txl->depth, GPU_DEPTH_COMPONENT24, 0},
146          *                         {&txl->color, GPU_RGBA8, DRW_TEX_FILTER}};
147          */
148
149         /* DRW_framebuffer_init takes care of checking if
150          * the framebuffer is valid and has the right size*/
151         /*
152          * float *viewport_size = DRW_viewport_size_get();
153          * DRW_framebuffer_init(&fbl->occlude_wire_fb,
154          *                     (int)viewport_size[0], (int)viewport_size[1],
155          *                     tex, 2);
156          */
157
158         if (!e_data.fallback_sh) {
159                 e_data.fallback_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
160         }
161         if (!e_data.image_sh) {
162                 e_data.image_sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
163
164                 e_data.image_sh = DRW_shader_create_with_lib(
165                         datatoc_paint_texture_vert_glsl, NULL,
166                         datatoc_paint_texture_frag_glsl,
167                         datatoc_common_globals_lib_glsl, NULL);
168
169         }
170
171         if (!e_data.wire_overlay_shader) {
172                 e_data.wire_overlay_shader = DRW_shader_create_with_lib(
173                         datatoc_paint_wire_vert_glsl, NULL,
174                         datatoc_paint_wire_frag_glsl,
175                         datatoc_common_globals_lib_glsl,
176                         "#define VERTEX_MODE\n");
177         }
178
179         if (!e_data.face_overlay_shader) {
180                 e_data.face_overlay_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
181         }
182 }
183
184 /* Here init all passes and shading groups
185  * Assume that all Passes are NULL */
186 static void PAINT_TEXTURE_cache_init(void *vedata)
187 {
188         PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl;
189         PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl;
190
191         if (!stl->g_data) {
192                 /* Alloc transient pointers */
193                 stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
194                 stl->g_data->shgroup_image_array = NULL;
195         }
196
197         {
198                 /* Create a pass */
199                 DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND;
200                 psl->image_faces = DRW_pass_create("Image Color Pass", state);
201
202                 stl->g_data->shgroup_fallback = DRW_shgroup_create(e_data.fallback_sh, psl->image_faces);
203
204                 /* Uniforms need a pointer to it's value so be sure it's accessible at
205                  * any given time (i.e. use static vars) */
206                 static float color[4] = {1.0f, 0.0f, 1.0f, 1.0};
207                 DRW_shgroup_uniform_vec4(stl->g_data->shgroup_fallback, "color", color, 1);
208
209                 MEM_SAFE_FREE(stl->g_data->shgroup_image_array);
210
211                 const DRWContextState *draw_ctx = DRW_context_state_get();
212                 Object *ob = draw_ctx->obact;
213                 if (ob && ob->type == OB_MESH) {
214                         Scene *scene = draw_ctx->scene;
215                         const bool use_material_slots = (scene->toolsettings->imapaint.mode == IMAGEPAINT_MODE_MATERIAL);
216                         const Mesh *me = ob->data;
217
218                         stl->g_data->shgroup_image_array = MEM_mallocN(
219                                 sizeof(*stl->g_data->shgroup_image_array) * (use_material_slots ? me->totcol : 1), __func__);
220
221                         if (use_material_slots) {
222                                 for (int i = 0; i < me->totcol; i++) {
223                                         Material *ma = give_current_material(ob, i + 1);
224                                         Image *ima = (ma && ma->texpaintslot) ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
225                                         GPUTexture *tex = ima ?
226                                                 GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false, 0.0f) : NULL;
227
228                                         if (tex) {
229                                                 DRWShadingGroup *grp = DRW_shgroup_create(e_data.image_sh, psl->image_faces);
230                                                 DRW_shgroup_uniform_texture(grp, "image", tex);
231                                                 DRW_shgroup_uniform_float(grp, "alpha", &draw_ctx->v3d->overlay.texture_paint_mode_opacity, 1);
232                                                 DRW_shgroup_uniform_block(grp, "globalsBlock", globals_ubo);
233                                                 stl->g_data->shgroup_image_array[i] = grp;
234                                         }
235                                         else {
236                                                 stl->g_data->shgroup_image_array[i] = NULL;
237                                         }
238                                 }
239                         }
240                         else {
241                                 Image *ima = scene->toolsettings->imapaint.canvas;
242                                 GPUTexture *tex = ima ?
243                                         GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false, 0.0f) : NULL;
244
245                                 if (tex) {
246                                         DRWShadingGroup *grp = DRW_shgroup_create(e_data.image_sh, psl->image_faces);
247                                         DRW_shgroup_uniform_texture(grp, "image", tex);
248                                         DRW_shgroup_uniform_float(grp, "alpha", &draw_ctx->v3d->overlay.texture_paint_mode_opacity, 1);
249                                         DRW_shgroup_uniform_block(grp, "globalsBlock", globals_ubo);
250                                         stl->g_data->shgroup_image_array[0] = grp;
251                                 }
252                                 else {
253                                         stl->g_data->shgroup_image_array[0] = NULL;
254                                 }
255                         }
256                 }
257         }
258
259         /* Face Mask */
260         {
261                 psl->wire_overlay = DRW_pass_create(
262                         "Wire Pass",
263                         DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL);
264
265                 stl->g_data->lwire_shgrp = DRW_shgroup_create(e_data.wire_overlay_shader, psl->wire_overlay);
266                 DRW_shgroup_uniform_block(stl->g_data->lwire_shgrp, "globalsBlock", globals_ubo);
267         }
268
269         {
270                 psl->face_overlay = DRW_pass_create(
271                         "Face Mask Pass",
272                         DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_BLEND);
273
274                 stl->g_data->face_shgrp = DRW_shgroup_create(e_data.face_overlay_shader, psl->face_overlay);
275
276                 static float col[4] = {1.0f, 1.0f, 1.0f, 0.2f};
277                 DRW_shgroup_uniform_vec4(stl->g_data->face_shgrp, "color", col, 1);
278         }
279 }
280
281 /* Add geometry to shadingGroups. Execute for each objects */
282 static void PAINT_TEXTURE_cache_populate(void *vedata, Object *ob)
283 {
284         PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl;
285         PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl;
286         const DRWContextState *draw_ctx = DRW_context_state_get();
287
288         UNUSED_VARS(psl, stl);
289
290         if ((ob->type == OB_MESH) && (draw_ctx->obact == ob)) {
291                 /* Get geometry cache */
292                 const Mesh *me = ob->data;
293                 const Mesh *me_orig = DEG_get_original_object(ob)->data;
294                 Scene *scene = draw_ctx->scene;
295                 const bool use_surface = draw_ctx->v3d->overlay.texture_paint_mode_opacity != 0.0; //DRW_object_is_mode_shade(ob) == true;
296                 const bool use_material_slots = (scene->toolsettings->imapaint.mode == IMAGEPAINT_MODE_MATERIAL);
297                 const bool use_face_sel = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
298
299                 if (use_surface) {
300                         if (me->mloopuv != NULL) {
301                                 if (use_material_slots) {
302                                         int mat_nr = max_ii(1, me->totcol);
303                                         struct GPUBatch **geom_array = DRW_cache_mesh_surface_texpaint_get(ob);
304
305                                         for (int i = 0; i < mat_nr; i++) {
306                                                 const int index = use_material_slots ? i : 0;
307                                                 if (stl->g_data->shgroup_image_array[index]) {
308                                                         DRW_shgroup_call_add(stl->g_data->shgroup_image_array[index], geom_array[i], ob->obmat);
309                                                 }
310                                                 else {
311                                                         DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom_array[i], ob->obmat);
312                                                 }
313                                         }
314                                 }
315                                 else {
316                                         if (stl->g_data->shgroup_image_array[0]) {
317                                                 struct GPUBatch *geom = DRW_cache_mesh_surface_texpaint_single_get(ob);
318                                                 DRW_shgroup_call_add(stl->g_data->shgroup_image_array[0], geom, ob->obmat);
319                                         }
320                                 }
321                         }
322                         else {
323                                 struct GPUBatch *geom = DRW_cache_mesh_surface_get(ob);
324                                 DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom, ob->obmat);
325                         }
326                 }
327
328                 /* Face Mask */
329                 if (use_face_sel) {
330                         struct GPUBatch *geom;
331                         /* Note: ideally selected faces wouldn't show interior wire. */
332                         const bool use_wire = true;
333                         geom = DRW_cache_mesh_edges_paint_overlay_get(ob, use_wire, use_face_sel);
334                         DRW_shgroup_call_add(stl->g_data->lwire_shgrp, geom, ob->obmat);
335
336                         geom = DRW_cache_mesh_faces_weight_overlay_get(ob);
337                         DRW_shgroup_call_add(stl->g_data->face_shgrp, geom, ob->obmat);
338                 }
339         }
340 }
341
342 /* Optional: Post-cache_populate callback */
343 static void PAINT_TEXTURE_cache_finish(void *vedata)
344 {
345         PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl;
346         PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl;
347
348         /* Do something here! dependent on the objects gathered */
349         UNUSED_VARS(psl);
350
351         MEM_SAFE_FREE(stl->g_data->shgroup_image_array);
352 }
353
354 /* Draw time ! Control rendering pipeline from here */
355 static void PAINT_TEXTURE_draw_scene(void *vedata)
356 {
357         PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl;
358         PAINT_TEXTURE_FramebufferList *fbl = ((PAINT_TEXTURE_Data *)vedata)->fbl;
359
360         /* Default framebuffer and texture */
361         DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
362         DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
363
364         UNUSED_VARS(fbl, dfbl, dtxl);
365
366         DRW_draw_pass(psl->image_faces);
367
368         DRW_draw_pass(psl->face_overlay);
369         DRW_draw_pass(psl->wire_overlay);
370 }
371
372 /* Cleanup when destroying the engine.
373  * This is not per viewport ! only when quitting blender.
374  * Mostly used for freeing shaders */
375 static void PAINT_TEXTURE_engine_free(void)
376 {
377         DRW_SHADER_FREE_SAFE(e_data.image_sh);
378         DRW_SHADER_FREE_SAFE(e_data.wire_overlay_shader);
379 }
380
381 static const DrawEngineDataSize PAINT_TEXTURE_data_size = DRW_VIEWPORT_DATA_SIZE(PAINT_TEXTURE_Data);
382
383 DrawEngineType draw_engine_paint_texture_type = {
384         NULL, NULL,
385         N_("PaintTextureMode"),
386         &PAINT_TEXTURE_data_size,
387         &PAINT_TEXTURE_engine_init,
388         &PAINT_TEXTURE_engine_free,
389         &PAINT_TEXTURE_cache_init,
390         &PAINT_TEXTURE_cache_populate,
391         &PAINT_TEXTURE_cache_finish,
392         NULL, /* draw_background but not needed by mode engines */
393         &PAINT_TEXTURE_draw_scene,
394         NULL,
395         NULL,
396 };