Workbench: Rename orientation to type and Camera studio light to Studio
[blender.git] / source / blender / draw / engines / workbench / workbench_forward.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 workbench_forward.c
23  *  \ingroup draw_engine
24  */
25
26 #include "workbench_private.h"
27
28 #include "BIF_gl.h"
29
30 #include "BLI_alloca.h"
31 #include "BLI_dynstr.h"
32 #include "BLI_utildefines.h"
33
34 #include "BKE_node.h"
35 #include "BKE_particle.h"
36 #include "BKE_modifier.h"
37
38 #include "DNA_image_types.h"
39 #include "DNA_mesh_types.h"
40 #include "DNA_modifier_types.h"
41 #include "DNA_node_types.h"
42
43 #include "ED_uvedit.h"
44
45 #include "GPU_shader.h"
46 #include "GPU_texture.h"
47
48 #include "UI_resources.h"
49
50 /* *********** STATIC *********** */
51 static struct {
52         struct GPUShader *composite_sh_cache[MAX_SHADERS];
53         struct GPUShader *transparent_accum_sh_cache[MAX_SHADERS];
54         struct GPUShader *object_outline_sh;
55         struct GPUShader *object_outline_texture_sh;
56         struct GPUShader *object_outline_hair_sh;
57         struct GPUShader *checker_depth_sh;
58
59         struct GPUTexture *object_id_tx; /* ref only, not alloced */
60         struct GPUTexture *transparent_accum_tx; /* ref only, not alloced */
61         struct GPUTexture *transparent_revealage_tx; /* ref only, not alloced */
62         struct GPUTexture *composite_buffer_tx; /* ref only, not alloced */
63
64         int next_object_id;
65 } e_data = {{NULL}};
66
67 /* Shaders */
68 extern char datatoc_common_hair_lib_glsl[];
69
70 extern char datatoc_workbench_forward_composite_frag_glsl[];
71 extern char datatoc_workbench_forward_depth_frag_glsl[];
72 extern char datatoc_workbench_forward_transparent_accum_frag_glsl[];
73 extern char datatoc_workbench_data_lib_glsl[];
74 extern char datatoc_workbench_background_lib_glsl[];
75 extern char datatoc_workbench_checkerboard_depth_frag_glsl[];
76 extern char datatoc_workbench_object_outline_lib_glsl[];
77 extern char datatoc_workbench_curvature_lib_glsl[];
78 extern char datatoc_workbench_prepass_vert_glsl[];
79 extern char datatoc_workbench_common_lib_glsl[];
80 extern char datatoc_workbench_world_light_lib_glsl[];
81
82 /* static functions */
83 static char *workbench_build_forward_vert(bool is_hair)
84 {
85         char *str = NULL;
86         if (!is_hair) {
87                 return BLI_strdup(datatoc_workbench_prepass_vert_glsl);
88         }
89
90         DynStr *ds = BLI_dynstr_new();
91
92         BLI_dynstr_append(ds, datatoc_common_hair_lib_glsl);
93         BLI_dynstr_append(ds, datatoc_workbench_prepass_vert_glsl);
94
95         str = BLI_dynstr_get_cstring(ds);
96         BLI_dynstr_free(ds);
97         return str;
98 }
99
100 static char *workbench_build_forward_transparent_accum_frag(void)
101 {
102         char *str = NULL;
103
104         DynStr *ds = BLI_dynstr_new();
105
106         BLI_dynstr_append(ds, datatoc_workbench_data_lib_glsl);
107         BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl);
108         BLI_dynstr_append(ds, datatoc_workbench_world_light_lib_glsl);
109         BLI_dynstr_append(ds, datatoc_workbench_forward_transparent_accum_frag_glsl);
110
111         str = BLI_dynstr_get_cstring(ds);
112         BLI_dynstr_free(ds);
113         return str;
114 }
115
116 static char *workbench_build_forward_composite_frag(void)
117 {
118         char *str = NULL;
119
120         DynStr *ds = BLI_dynstr_new();
121
122         BLI_dynstr_append(ds, datatoc_workbench_data_lib_glsl);
123         BLI_dynstr_append(ds, datatoc_workbench_common_lib_glsl);
124         BLI_dynstr_append(ds, datatoc_workbench_background_lib_glsl);
125         BLI_dynstr_append(ds, datatoc_workbench_object_outline_lib_glsl);
126         BLI_dynstr_append(ds, datatoc_workbench_curvature_lib_glsl);
127         BLI_dynstr_append(ds, datatoc_workbench_forward_composite_frag_glsl);
128
129         str = BLI_dynstr_get_cstring(ds);
130         BLI_dynstr_free(ds);
131         return str;
132 }
133
134 static void workbench_init_object_data(DrawData *dd)
135 {
136         WORKBENCH_ObjectData *data = (WORKBENCH_ObjectData *)dd;
137         data->object_id = ((e_data.next_object_id++) & 0xff) + 1;
138 }
139
140 static WORKBENCH_MaterialData *get_or_create_material_data(
141         WORKBENCH_Data *vedata, Object *ob, Material *mat, Image *ima, int color_type)
142 {
143         WORKBENCH_StorageList *stl = vedata->stl;
144         WORKBENCH_PassList *psl = vedata->psl;
145         WORKBENCH_PrivateData *wpd = stl->g_data;
146         WORKBENCH_MaterialData *material;
147         WORKBENCH_ObjectData *engine_object_data = (WORKBENCH_ObjectData *)DRW_drawdata_ensure(
148                 &ob->id, &draw_engine_workbench_solid, sizeof(WORKBENCH_ObjectData), &workbench_init_object_data, NULL);
149         WORKBENCH_MaterialData material_template;
150         DRWShadingGroup *grp;
151
152         /* Solid */
153         workbench_material_update_data(wpd, ob, mat, &material_template);
154         material_template.object_id = OBJECT_ID_PASS_ENABLED(wpd) ? engine_object_data->object_id : 1;
155         material_template.color_type = color_type;
156         material_template.ima = ima;
157         uint hash = workbench_material_get_hash(&material_template, false);
158
159         material = BLI_ghash_lookup(wpd->material_hash, POINTER_FROM_UINT(hash));
160         if (material == NULL) {
161                 material = MEM_mallocN(sizeof(WORKBENCH_MaterialData), __func__);
162
163                 /* transparent accum */
164                 grp = DRW_shgroup_create(
165                         color_type == V3D_SHADING_TEXTURE_COLOR ? wpd->transparent_accum_texture_sh: wpd->transparent_accum_sh,
166                         psl->transparent_accum_pass);
167                 DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
168                 DRW_shgroup_uniform_float(grp, "alpha", &wpd->shading.xray_alpha, 1);
169                 DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)wpd->viewvecs, 3);
170                 workbench_material_copy(material, &material_template);
171                 if (STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) {
172                         BKE_studiolight_ensure_flag(wpd->studio_light, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE);
173                         DRW_shgroup_uniform_texture(grp, "matcapImage", wpd->studio_light->equirect_radiance_gputexture );
174                 }
175                 if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || MATCAP_ENABLED(wpd)) {
176                         DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1);
177                 }
178
179                 workbench_material_shgroup_uniform(wpd, grp, material, ob);
180                 material->shgrp = grp;
181
182                 /* Depth */
183                 if (workbench_material_determine_color_type(wpd, material->ima, ob) == V3D_SHADING_TEXTURE_COLOR) {
184                         material->shgrp_object_outline = DRW_shgroup_create(
185                                 e_data.object_outline_texture_sh, psl->object_outline_pass);
186                         GPUTexture *tex = GPU_texture_from_blender(material->ima, NULL, GL_TEXTURE_2D, false, 0.0f);
187                         DRW_shgroup_uniform_texture(material->shgrp_object_outline, "image", tex);
188                 }
189                 else {
190                         material->shgrp_object_outline = DRW_shgroup_create(
191                                 e_data.object_outline_sh, psl->object_outline_pass);
192                 }
193                 material->object_id = engine_object_data->object_id;
194                 DRW_shgroup_uniform_int(material->shgrp_object_outline, "object_id", &material->object_id, 1);
195                 BLI_ghash_insert(wpd->material_hash, POINTER_FROM_UINT(hash), material);
196         }
197         return material;
198 }
199
200 static void ensure_forward_shaders(WORKBENCH_PrivateData *wpd, int index, bool use_textures, bool is_hair)
201 {
202         if (e_data.composite_sh_cache[index] == NULL && !use_textures && !is_hair) {
203                 char *defines = workbench_material_build_defines(wpd, use_textures, is_hair);
204                 char *composite_frag = workbench_build_forward_composite_frag();
205                 e_data.composite_sh_cache[index] = DRW_shader_create_fullscreen(composite_frag, defines);
206                 MEM_freeN(composite_frag);
207                 MEM_freeN(defines);
208         }
209
210         if (e_data.transparent_accum_sh_cache[index] == NULL) {
211                 char *defines = workbench_material_build_defines(wpd, use_textures, is_hair);
212                 char *transparent_accum_vert = workbench_build_forward_vert(is_hair);
213                 char *transparent_accum_frag = workbench_build_forward_transparent_accum_frag();
214                 e_data.transparent_accum_sh_cache[index] = DRW_shader_create(
215                         transparent_accum_vert, NULL,
216                         transparent_accum_frag, defines);
217                 MEM_freeN(transparent_accum_vert);
218                 MEM_freeN(transparent_accum_frag);
219                 MEM_freeN(defines);
220         }
221 }
222
223 static void select_forward_shaders(WORKBENCH_PrivateData *wpd)
224 {
225         int index_solid = workbench_material_get_shader_index(wpd, false, false);
226         int index_solid_hair = workbench_material_get_shader_index(wpd, false, true);
227         int index_texture = workbench_material_get_shader_index(wpd, true, false);
228         int index_texture_hair = workbench_material_get_shader_index(wpd, true, true);
229
230         ensure_forward_shaders(wpd, index_solid, false, false);
231         ensure_forward_shaders(wpd, index_solid_hair, false, true);
232         ensure_forward_shaders(wpd, index_texture, true, false);
233         ensure_forward_shaders(wpd, index_texture_hair, true, true);
234
235         wpd->composite_sh = e_data.composite_sh_cache[index_solid];
236         wpd->transparent_accum_sh = e_data.transparent_accum_sh_cache[index_solid];
237         wpd->transparent_accum_hair_sh = e_data.transparent_accum_sh_cache[index_solid_hair];
238         wpd->transparent_accum_texture_sh = e_data.transparent_accum_sh_cache[index_texture];
239         wpd->transparent_accum_texture_hair_sh = e_data.transparent_accum_sh_cache[index_texture_hair];
240 }
241
242 /* public functions */
243 void workbench_forward_engine_init(WORKBENCH_Data *vedata)
244 {
245         WORKBENCH_FramebufferList *fbl = vedata->fbl;
246         WORKBENCH_PassList *psl = vedata->psl;
247         WORKBENCH_StorageList *stl = vedata->stl;
248         DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
249         const DRWContextState *draw_ctx = DRW_context_state_get();
250         DRWShadingGroup *grp;
251
252         if (!stl->g_data) {
253                 /* Alloc transient pointers */
254                 stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__);
255         }
256         if (!stl->effects) {
257                 stl->effects = MEM_callocN(sizeof(*stl->effects), __func__);
258                 workbench_effect_info_init(stl->effects);
259         }
260         WORKBENCH_PrivateData *wpd = stl->g_data;
261         workbench_private_data_init(wpd);
262         float light_direction[3];
263         workbench_private_data_get_light_direction(wpd, light_direction);
264
265         if (!e_data.next_object_id) {
266                 e_data.next_object_id = 1;
267                 memset(e_data.composite_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS);
268                 memset(e_data.transparent_accum_sh_cache, 0x00, sizeof(struct GPUShader *) * MAX_SHADERS);
269
270                 char *defines = workbench_material_build_defines(wpd, false, false);
271                 char *defines_texture = workbench_material_build_defines(wpd, true, false);
272                 char *defines_hair = workbench_material_build_defines(wpd, false, true);
273                 char *forward_vert = workbench_build_forward_vert(false);
274                 char *forward_hair_vert = workbench_build_forward_vert(true);
275                 e_data.object_outline_sh = DRW_shader_create(
276                         forward_vert, NULL,
277                         datatoc_workbench_forward_depth_frag_glsl, defines);
278                 e_data.object_outline_texture_sh = DRW_shader_create(
279                         forward_vert, NULL,
280                         datatoc_workbench_forward_depth_frag_glsl, defines_texture);
281                 e_data.object_outline_hair_sh = DRW_shader_create(
282                         forward_hair_vert, NULL,
283                         datatoc_workbench_forward_depth_frag_glsl, defines_hair);
284
285
286                 e_data.checker_depth_sh = DRW_shader_create_fullscreen(
287                         datatoc_workbench_checkerboard_depth_frag_glsl, NULL);
288                 MEM_freeN(forward_hair_vert);
289                 MEM_freeN(forward_vert);
290                 MEM_freeN(defines);
291                 MEM_freeN(defines_texture);
292                 MEM_freeN(defines_hair);
293         }
294         workbench_volume_engine_init();
295         workbench_fxaa_engine_init();
296         workbench_taa_engine_init(vedata);
297
298         select_forward_shaders(wpd);
299
300         const float *viewport_size = DRW_viewport_size_get();
301         const int size[2] = {(int)viewport_size[0], (int)viewport_size[1]};
302
303         e_data.object_id_tx = DRW_texture_pool_query_2D(
304                 size[0], size[1], GPU_R32UI, &draw_engine_workbench_transparent);
305         e_data.transparent_accum_tx = DRW_texture_pool_query_2D(
306                 size[0], size[1], GPU_RGBA16F, &draw_engine_workbench_transparent);
307         e_data.transparent_revealage_tx = DRW_texture_pool_query_2D(
308                 size[0], size[1], GPU_R16F, &draw_engine_workbench_transparent);
309         e_data.composite_buffer_tx = DRW_texture_pool_query_2D(
310                 size[0], size[1], GPU_R11F_G11F_B10F, &draw_engine_workbench_transparent);
311
312         GPU_framebuffer_ensure_config(&fbl->object_outline_fb, {
313                 GPU_ATTACHMENT_TEXTURE(dtxl->depth),
314                 GPU_ATTACHMENT_TEXTURE(e_data.object_id_tx),
315         });
316         GPU_framebuffer_ensure_config(&fbl->transparent_accum_fb, {
317                 GPU_ATTACHMENT_NONE,
318                 GPU_ATTACHMENT_TEXTURE(e_data.transparent_accum_tx),
319                 GPU_ATTACHMENT_TEXTURE(e_data.transparent_revealage_tx),
320         });
321         GPU_framebuffer_ensure_config(&fbl->composite_fb, {
322                 GPU_ATTACHMENT_NONE,
323                 GPU_ATTACHMENT_TEXTURE(e_data.composite_buffer_tx),
324         });
325         GPU_framebuffer_ensure_config(&fbl->effect_fb, {
326                 GPU_ATTACHMENT_NONE,
327                 GPU_ATTACHMENT_TEXTURE(e_data.transparent_accum_tx),
328         });
329
330         workbench_volume_cache_init(vedata);
331         const bool do_cull = (draw_ctx->v3d && (draw_ctx->v3d->flag2 & V3D_BACKFACE_CULLING));
332         const int cull_state = (do_cull) ? DRW_STATE_CULL_BACK : 0;
333
334         /* Transparency Accum */
335         {
336                 int state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_OIT | cull_state;
337                 psl->transparent_accum_pass = DRW_pass_create("Transparent Accum", state);
338         }
339         /* Depth */
340         {
341                 int state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | cull_state;
342                 psl->object_outline_pass = DRW_pass_create("Object Outline Pass", state);
343         }
344         /* Composite */
345         {
346                 int state = DRW_STATE_WRITE_COLOR;
347                 psl->composite_pass = DRW_pass_create("Composite", state);
348
349                 grp = DRW_shgroup_create(wpd->composite_sh, psl->composite_pass);
350                 if (OBJECT_ID_PASS_ENABLED(wpd)) {
351                         DRW_shgroup_uniform_texture_ref(grp, "objectId", &e_data.object_id_tx);
352                 }
353                 DRW_shgroup_uniform_texture_ref(grp, "transparentAccum", &e_data.transparent_accum_tx);
354                 DRW_shgroup_uniform_texture_ref(grp, "transparentRevealage", &e_data.transparent_revealage_tx);
355                 DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
356                 DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1);
357                 DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
358         }
359
360         {
361                 workbench_aa_create_pass(vedata, &e_data.transparent_accum_tx);
362         }
363
364         /* Checker Depth */
365         {
366                 static float noise_offset = 0.0f;
367                 float blend_threshold = 0.0f;
368
369                 if (DRW_state_is_image_render()) {
370                         /* TODO: Should be based on the number of samples used for render. */
371                         noise_offset = fmodf(noise_offset + 1.0f / 8.0f, 1.0f);
372                 }
373
374                 if (wpd->shading.flag & XRAY_FLAG(wpd)) {
375                         blend_threshold = 1.0f - XRAY_ALPHA(wpd) * 0.9f;
376                 }
377
378                 if (wpd->shading.type == OB_WIRE) {
379                         wpd->shading.xray_alpha = 0.0f;
380                         wpd->shading.xray_alpha_wire = 0.0f;
381                 }
382
383                 int state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS;
384                 psl->checker_depth_pass = DRW_pass_create("Checker Depth", state);
385                 grp = DRW_shgroup_create(e_data.checker_depth_sh, psl->checker_depth_pass);
386                 DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
387                 DRW_shgroup_uniform_float_copy(grp, "threshold", blend_threshold);
388                 DRW_shgroup_uniform_float_copy(grp, "offset", noise_offset);
389         }
390 }
391
392 void workbench_forward_engine_free()
393 {
394         for (int index = 0; index < MAX_SHADERS; index++) {
395                 DRW_SHADER_FREE_SAFE(e_data.composite_sh_cache[index]);
396                 DRW_SHADER_FREE_SAFE(e_data.transparent_accum_sh_cache[index]);
397         }
398         DRW_SHADER_FREE_SAFE(e_data.object_outline_sh);
399         DRW_SHADER_FREE_SAFE(e_data.object_outline_texture_sh);
400         DRW_SHADER_FREE_SAFE(e_data.object_outline_hair_sh);
401         DRW_SHADER_FREE_SAFE(e_data.checker_depth_sh);
402
403         workbench_volume_engine_free();
404         workbench_fxaa_engine_free();
405         workbench_taa_engine_free();
406 }
407
408 void workbench_forward_cache_init(WORKBENCH_Data *UNUSED(vedata))
409 {
410 }
411
412 static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, Object *ob)
413 {
414         WORKBENCH_StorageList *stl = vedata->stl;
415         WORKBENCH_PassList *psl = vedata->psl;
416         WORKBENCH_PrivateData *wpd = stl->g_data;
417
418         for (ModifierData *md = ob->modifiers.first; md; md = md->next) {
419                 if (md->type != eModifierType_ParticleSystem) {
420                         continue;
421                 }
422                 ParticleSystem *psys = ((ParticleSystemModifierData *)md)->psys;
423                 if (!psys_check_enabled(ob, psys, false)) {
424                         continue;
425                 }
426                 if (!DRW_object_is_visible_psys_in_active_context(ob, psys)) {
427                         continue;
428                 }
429                 ParticleSettings *part = psys->part;
430                 const int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as;
431
432                 if (draw_as == PART_DRAW_PATH) {
433                         Image *image = NULL;
434                         Material *mat = give_current_material(ob, part->omat);
435                         ED_object_get_active_image(ob, part->omat, &image, NULL, NULL, NULL);
436                         int color_type = workbench_material_determine_color_type(wpd, image, ob);
437                         WORKBENCH_MaterialData *material = get_or_create_material_data(vedata, ob, mat, image, color_type);
438
439                         struct GPUShader *shader = (color_type != V3D_SHADING_TEXTURE_COLOR)
440                                                    ? wpd->transparent_accum_hair_sh
441                                                    : wpd->transparent_accum_texture_hair_sh;
442                         DRWShadingGroup *shgrp = DRW_shgroup_hair_create(
443                                                         ob, psys, md,
444                                                         psl->transparent_accum_pass,
445                                                         shader);
446                         DRW_shgroup_uniform_block(shgrp, "world_block", wpd->world_ubo);
447                         workbench_material_shgroup_uniform(wpd, shgrp, material, ob);
448                         DRW_shgroup_uniform_vec4(shgrp, "viewvecs[0]", (float *)wpd->viewvecs, 3);
449                         /* Hairs have lots of layer and can rapidly become the most prominent surface.
450                          * So lower their alpha artificially. */
451                         float hair_alpha = XRAY_ALPHA(wpd) * 0.33f;
452                         DRW_shgroup_uniform_float_copy(shgrp, "alpha", hair_alpha);
453                         if (STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) {
454                                 BKE_studiolight_ensure_flag(wpd->studio_light, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE);
455                                 DRW_shgroup_uniform_texture(shgrp, "matcapImage", wpd->studio_light->equirect_radiance_gputexture );
456                         }
457                         if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || MATCAP_ENABLED(wpd)) {
458                                 DRW_shgroup_uniform_vec2(shgrp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1);
459                         }
460                         shgrp = DRW_shgroup_hair_create(ob, psys, md,
461                                                 vedata->psl->object_outline_pass,
462                                                 e_data.object_outline_hair_sh);
463                         DRW_shgroup_uniform_int(shgrp, "object_id", &material->object_id, 1);
464                 }
465         }
466 }
467
468 void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
469 {
470         WORKBENCH_StorageList *stl = vedata->stl;
471         WORKBENCH_PrivateData *wpd = stl->g_data;
472         const DRWContextState *draw_ctx = DRW_context_state_get();
473         Scene *scene = draw_ctx->scene;
474         const bool is_wire = (ob->dt == OB_WIRE);
475
476         if (!DRW_object_is_renderable(ob))
477                 return;
478
479         if (ob->type == OB_MESH) {
480                 workbench_forward_cache_populate_particles(vedata, ob);
481         }
482
483         ModifierData *md;
484         if (((ob->base_flag & BASE_FROMDUPLI) == 0) &&
485             (md = modifiers_findByType(ob, eModifierType_Smoke)) &&
486             (modifier_isEnabled(scene, md, eModifierMode_Realtime)) &&
487             (((SmokeModifierData *)md)->domain != NULL))
488         {
489                 workbench_volume_cache_populate(vedata, scene, ob, md);
490                 return; /* Do not draw solid in this case. */
491         }
492
493         if (!DRW_object_is_visible_in_active_context(ob) || (ob->dt < OB_WIRE)) {
494                 return;
495         }
496
497         WORKBENCH_MaterialData *material;
498         if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) {
499                 const bool is_active = (ob == draw_ctx->obact);
500                 const bool is_sculpt_mode = is_active && (draw_ctx->object_mode & OB_MODE_SCULPT) != 0;
501                 const bool use_hide = is_active && DRW_object_use_hide_faces(ob);
502                 bool is_drawn = false;
503
504                 if (!is_sculpt_mode && TEXTURE_DRAWING_ENABLED(wpd) && ELEM(ob->type, OB_MESH)) {
505                         const Mesh *me = ob->data;
506                         if (me->mloopuv) {
507                                 const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol));
508                                 struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len);
509                                 struct GPUBatch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob, use_hide) : NULL;
510                                 if (materials_len > 0 && geom_array) {
511                                         for (int i = 0; i < materials_len; i++) {
512                                                 if (geom_array[i] == NULL) {
513                                                         continue;
514                                                 }
515
516                                                 Material *mat = give_current_material(ob, i + 1);
517                                                 Image *image;
518                                                 ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL);
519                                                 /* use OB_SOLID when no texture could be determined */
520
521                                                 int color_type = wpd->shading.color_type;
522                                                 if (color_type == V3D_SHADING_TEXTURE_COLOR) {
523                                                         /* use OB_SOLID when no texture could be determined */
524                                                         if (image == NULL) {
525                                                                 color_type = V3D_SHADING_MATERIAL_COLOR;
526                                                         }
527                                                 }
528
529                                                 material = get_or_create_material_data(vedata, ob, mat, image, color_type);
530                                                 DRW_shgroup_call_object_add(material->shgrp_object_outline, geom_array[i], ob);
531                                                 DRW_shgroup_call_object_add(material->shgrp, geom_array[i], ob);
532                                         }
533                                         is_drawn = true;
534                                 }
535                         }
536                 }
537
538                 /* Fallback from not drawn OB_TEXTURE mode or just OB_SOLID mode */
539                 if (!is_drawn) {
540                         if (ELEM(wpd->shading.color_type, V3D_SHADING_SINGLE_COLOR, V3D_SHADING_RANDOM_COLOR)) {
541                                 /* No material split needed */
542                                 struct GPUBatch *geom = DRW_cache_object_surface_get_ex(ob, use_hide);
543                                 if (geom) {
544                                         material = get_or_create_material_data(vedata, ob, NULL, NULL, wpd->shading.color_type);
545                                         if (is_sculpt_mode) {
546                                                 DRW_shgroup_call_sculpt_add(material->shgrp_object_outline, ob, ob->obmat);
547                                                 if (!is_wire) {
548                                                         DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat);
549                                                 }
550                                         }
551                                         else {
552                                                 DRW_shgroup_call_object_add(material->shgrp_object_outline, geom, ob);
553                                                 if (!is_wire) {
554                                                         DRW_shgroup_call_object_add(material->shgrp, geom, ob);
555                                                 }
556                                         }
557                                 }
558                         }
559                         else {
560                                 const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol));
561                                 struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len);
562                                 for (int i = 0; i < materials_len; i++) {
563                                         gpumat_array[i] = NULL;
564                                 }
565
566                                 struct GPUBatch **mat_geom = DRW_cache_object_surface_material_get(
567                                         ob, gpumat_array, materials_len, use_hide, NULL, NULL, NULL);
568                                 if (mat_geom) {
569                                         for (int i = 0; i < materials_len; ++i) {
570                                                 if (mat_geom[i] == NULL) {
571                                                         continue;
572                                                 }
573
574                                                 Material *mat = give_current_material(ob, i + 1);
575                                                 material = get_or_create_material_data(vedata, ob, mat, NULL, V3D_SHADING_MATERIAL_COLOR);
576                                                 if (is_sculpt_mode) {
577                                                         DRW_shgroup_call_sculpt_add(material->shgrp_object_outline, ob, ob->obmat);
578                                                         if (!is_wire) {
579                                                                 DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat);
580                                                         }
581                                                 }
582                                                 else {
583                                                         DRW_shgroup_call_object_add(material->shgrp_object_outline, mat_geom[i], ob);
584                                                         if (!is_wire) {
585                                                                 DRW_shgroup_call_object_add(material->shgrp, mat_geom[i], ob);
586                                                         }
587                                                 }
588                                         }
589                                 }
590                         }
591                 }
592         }
593 }
594
595 void workbench_forward_cache_finish(WORKBENCH_Data *UNUSED(vedata))
596 {
597 }
598
599 void workbench_forward_draw_background(WORKBENCH_Data *UNUSED(vedata))
600 {
601         const float clear_depth = 1.0f;
602         DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
603         DRW_stats_group_start("Clear depth");
604         GPU_framebuffer_bind(dfbl->default_fb);
605         GPU_framebuffer_clear_depth(dfbl->default_fb, clear_depth);
606         DRW_stats_group_end();
607 }
608
609 void workbench_forward_draw_scene(WORKBENCH_Data *vedata)
610 {
611         WORKBENCH_PassList *psl = vedata->psl;
612         WORKBENCH_StorageList *stl = vedata->stl;
613         WORKBENCH_FramebufferList *fbl = vedata->fbl;
614         WORKBENCH_PrivateData *wpd = stl->g_data;
615         DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
616
617         if (TAA_ENABLED(wpd)) {
618                 workbench_taa_draw_scene_start(vedata);
619         }
620
621         /* Write Depth + Object ID */
622         const float clear_outline[4] = {0.0f};
623         GPU_framebuffer_bind(fbl->object_outline_fb);
624         GPU_framebuffer_clear_color(fbl->object_outline_fb, clear_outline);
625         DRW_draw_pass(psl->object_outline_pass);
626
627         if (XRAY_ALPHA(wpd) > 0.0) {
628                 const float clear_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
629                 GPU_framebuffer_bind(fbl->transparent_accum_fb);
630                 GPU_framebuffer_clear_color(fbl->transparent_accum_fb, clear_color);
631                 DRW_draw_pass(psl->transparent_accum_pass);
632         }
633         else {
634                 /* TODO(fclem): this is unnecessary and takes up perf.
635                  * Better change the composite frag shader to not use the tx. */
636                 const float clear_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
637                 GPU_framebuffer_bind(fbl->transparent_accum_fb);
638                 GPU_framebuffer_clear_color(fbl->transparent_accum_fb, clear_color);
639         }
640
641         /* Composite */
642         GPU_framebuffer_bind(fbl->composite_fb);
643         DRW_draw_pass(psl->composite_pass);
644         DRW_draw_pass(psl->volume_pass);
645
646         /* Color correct and Anti aliasing */
647         workbench_aa_draw_pass(vedata, e_data.composite_buffer_tx);
648
649         /* Apply checker pattern */
650         GPU_framebuffer_bind(dfbl->depth_only_fb);
651         DRW_draw_pass(psl->checker_depth_pass);
652 }
653
654 void workbench_forward_draw_finish(WORKBENCH_Data *vedata)
655 {
656         WORKBENCH_StorageList *stl = vedata->stl;
657         WORKBENCH_PrivateData *wpd = stl->g_data;
658
659         workbench_private_data_free(wpd);
660         workbench_volume_smoke_textures_free(wpd);
661 }