diff options
Diffstat (limited to 'source/blender/draw/engines')
22 files changed, 581 insertions, 276 deletions
diff --git a/source/blender/draw/engines/basic/basic_engine.c b/source/blender/draw/engines/basic/basic_engine.c index 2e3fdf37bdb..9dc8c8f2f34 100644 --- a/source/blender/draw/engines/basic/basic_engine.c +++ b/source/blender/draw/engines/basic/basic_engine.c @@ -112,7 +112,9 @@ static void basic_cache_populate(void *vedata, Object *ob) { BASIC_StorageList *stl = ((BASIC_Data *)vedata)->stl; - if (!DRW_object_is_renderable(ob)) { + /* TODO(fclem) fix selection of smoke domains. */ + + if (!DRW_object_is_renderable(ob) || (ob->dt < OB_SOLID)) { return; } @@ -125,7 +127,7 @@ static void basic_cache_populate(void *vedata, Object *ob) if (!psys_check_enabled(ob, psys, false)) { continue; } - if (!DRW_check_psys_visible_within_active_context(ob, psys)) { + if (!DRW_object_is_visible_psys_in_active_context(ob, psys)) { continue; } ParticleSettings *part = psys->part; diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index 32de4266c82..bea7d000181 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -137,7 +137,7 @@ void EEVEE_cache_populate(void *vedata, Object *ob) } if (DRW_object_is_renderable(ob) && - DRW_check_object_visible_within_active_context(ob)) + DRW_object_is_visible_in_active_context(ob)) { if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) { EEVEE_materials_cache_populate(vedata, sldata, ob, &cast_shadow); diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c index a458be040fc..7319572d7eb 100644 --- a/source/blender/draw/engines/eevee/eevee_lights.c +++ b/source/blender/draw/engines/eevee/eevee_lights.c @@ -628,12 +628,12 @@ static void eevee_light_setup(Object *ob, EEVEE_Light *evli) evli->radius = max_ff(0.001f, la->area_size); } else if (la->type == LA_AREA) { - evli->sizex = max_ff(0.0001f, la->area_size * scale[0] * 0.5f); + evli->sizex = max_ff(0.003f, la->area_size * scale[0] * 0.5f); if (ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_ELLIPSE)) { - evli->sizey = max_ff(0.0001f, la->area_sizey * scale[1] * 0.5f); + evli->sizey = max_ff(0.003f, la->area_sizey * scale[1] * 0.5f); } else { - evli->sizey = max_ff(0.0001f, la->area_size * scale[1] * 0.5f); + evli->sizey = max_ff(0.003f, la->area_size * scale[1] * 0.5f); } } else { diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index 2d27bb8e705..38c2fb50f81 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -1080,23 +1080,23 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) } } -#define ADD_SHGROUP_CALL(shgrp, ob, geom, oedata) do { \ +#define ADD_SHGROUP_CALL(shgrp, ob, ma, geom, oedata) do { \ if (is_sculpt_mode_draw) { \ DRW_shgroup_call_sculpt_add(shgrp, ob, ob->obmat); \ } \ else { \ if (oedata) { \ - DRW_shgroup_call_object_add_with_callback(shgrp, geom, ob, EEVEE_lightprobes_obj_visibility_cb, oedata); \ + DRW_shgroup_call_object_add_with_callback(shgrp, geom, ob, ma, EEVEE_lightprobes_obj_visibility_cb, oedata); \ } \ else { \ - DRW_shgroup_call_object_add(shgrp, geom, ob); \ + DRW_shgroup_call_object_add_ex(shgrp, geom, ob, ma, false); \ } \ } \ } while (0) -#define ADD_SHGROUP_CALL_SAFE(shgrp, ob, geom, oedata) do { \ +#define ADD_SHGROUP_CALL_SAFE(shgrp, ob, ma, geom, oedata) do { \ if (shgrp) { \ - ADD_SHGROUP_CALL(shgrp, ob, geom, oedata); \ + ADD_SHGROUP_CALL(shgrp, ob, ma, geom, oedata); \ } \ } while (0) @@ -1498,95 +1498,97 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sld */ bool use_volume_material = (gpumat_array[0] && GPU_material_use_domain_volume(gpumat_array[0])); - /* Get per-material split surface */ - char *auto_layer_names; - int *auto_layer_is_srgb; - int auto_layer_count; - struct GPUBatch **mat_geom = DRW_cache_object_surface_material_get( - ob, gpumat_array, materials_len, - &auto_layer_names, - &auto_layer_is_srgb, - &auto_layer_count); - if (mat_geom) { - for (int i = 0; i < materials_len; ++i) { - if (mat_geom[i] == NULL) { - continue; - } - EEVEE_ObjectEngineData *oedata = NULL; - Material *ma = give_current_material(ob, i + 1); - - if (ma == NULL) - ma = &defmaterial; - - /* Do not render surface if we are rendering a volume object - * and do not have a surface closure. */ - if (use_volume_material && - (gpumat_array[i] && !GPU_material_use_domain_surface(gpumat_array[i]))) - { - continue; - } + if (ob->dt >= OB_SOLID) { + /* Get per-material split surface */ + char *auto_layer_names; + int *auto_layer_is_srgb; + int auto_layer_count; + struct GPUBatch **mat_geom = DRW_cache_object_surface_material_get( + ob, gpumat_array, materials_len, + &auto_layer_names, + &auto_layer_is_srgb, + &auto_layer_count); + if (mat_geom) { + for (int i = 0; i < materials_len; ++i) { + if (mat_geom[i] == NULL) { + continue; + } + EEVEE_ObjectEngineData *oedata = NULL; + Material *ma = give_current_material(ob, i + 1); + + if (ma == NULL) + ma = &defmaterial; + + /* Do not render surface if we are rendering a volume object + * and do not have a surface closure. */ + if (use_volume_material && + (gpumat_array[i] && !GPU_material_use_domain_surface(gpumat_array[i]))) + { + continue; + } - /* XXX TODO rewrite this to include the dupli objects. - * This means we cannot exclude dupli objects from reflections!!! */ - if ((ob->base_flag & BASE_FROMDUPLI) == 0) { - oedata = EEVEE_object_data_ensure(ob); - oedata->ob = ob; - oedata->test_data = &sldata->probes->vis_data; - } + /* XXX TODO rewrite this to include the dupli objects. + * This means we cannot exclude dupli objects from reflections!!! */ + if ((ob->base_flag & BASE_FROMDUPLI) == 0) { + oedata = EEVEE_object_data_ensure(ob); + oedata->ob = ob; + oedata->test_data = &sldata->probes->vis_data; + } - /* Shading pass */ - ADD_SHGROUP_CALL(shgrp_array[i], ob, mat_geom[i], oedata); + /* Shading pass */ + ADD_SHGROUP_CALL(shgrp_array[i], ob, ma, mat_geom[i], oedata); - /* Depth Prepass */ - ADD_SHGROUP_CALL_SAFE(shgrp_depth_array[i], ob, mat_geom[i], oedata); - ADD_SHGROUP_CALL_SAFE(shgrp_depth_clip_array[i], ob, mat_geom[i], oedata); + /* Depth Prepass */ + ADD_SHGROUP_CALL_SAFE(shgrp_depth_array[i], ob, ma, mat_geom[i], oedata); + ADD_SHGROUP_CALL_SAFE(shgrp_depth_clip_array[i], ob, ma, mat_geom[i], oedata); - char *name = auto_layer_names; - for (int j = 0; j < auto_layer_count; ++j) { - /* TODO don't add these uniform when not needed (default pass shaders). */ - if (shgrp_array[i]) { - DRW_shgroup_uniform_bool(shgrp_array[i], name, &auto_layer_is_srgb[j], 1); - } - if (shgrp_depth_array[i]) { - DRW_shgroup_uniform_bool(shgrp_depth_array[i], name, &auto_layer_is_srgb[j], 1); - } - if (shgrp_depth_clip_array[i]) { - DRW_shgroup_uniform_bool(shgrp_depth_clip_array[i], name, &auto_layer_is_srgb[j], 1); + char *name = auto_layer_names; + for (int j = 0; j < auto_layer_count; ++j) { + /* TODO don't add these uniform when not needed (default pass shaders). */ + if (shgrp_array[i]) { + DRW_shgroup_uniform_bool(shgrp_array[i], name, &auto_layer_is_srgb[j], 1); + } + if (shgrp_depth_array[i]) { + DRW_shgroup_uniform_bool(shgrp_depth_array[i], name, &auto_layer_is_srgb[j], 1); + } + if (shgrp_depth_clip_array[i]) { + DRW_shgroup_uniform_bool(shgrp_depth_clip_array[i], name, &auto_layer_is_srgb[j], 1); + } + /* Go to next layer name. */ + while (*name != '\0') { name++; } + name += 1; } - /* Go to next layer name. */ - while (*name != '\0') { name++; } - name += 1; - } - /* Shadow Pass */ - if (ma->use_nodes && ma->nodetree && (ma->blend_method != MA_BM_SOLID)) { - struct GPUMaterial *gpumat; - switch (ma->blend_shadow) { - case MA_BS_SOLID: - EEVEE_lights_cache_shcaster_add( - sldata, stl, mat_geom[i], ob); - *cast_shadow = true; - break; - case MA_BS_CLIP: - gpumat = EEVEE_material_mesh_depth_get(scene, ma, false, true); - EEVEE_lights_cache_shcaster_material_add( - sldata, psl, gpumat, mat_geom[i], ob, &ma->alpha_threshold); - *cast_shadow = true; - break; - case MA_BS_HASHED: - gpumat = EEVEE_material_mesh_depth_get(scene, ma, true, true); - EEVEE_lights_cache_shcaster_material_add( - sldata, psl, gpumat, mat_geom[i], ob, NULL); - *cast_shadow = true; - break; - case MA_BS_NONE: - default: - break; + /* Shadow Pass */ + if (ma->use_nodes && ma->nodetree && (ma->blend_method != MA_BM_SOLID)) { + struct GPUMaterial *gpumat; + switch (ma->blend_shadow) { + case MA_BS_SOLID: + EEVEE_lights_cache_shcaster_add( + sldata, stl, mat_geom[i], ob); + *cast_shadow = true; + break; + case MA_BS_CLIP: + gpumat = EEVEE_material_mesh_depth_get(scene, ma, false, true); + EEVEE_lights_cache_shcaster_material_add( + sldata, psl, gpumat, mat_geom[i], ob, &ma->alpha_threshold); + *cast_shadow = true; + break; + case MA_BS_HASHED: + gpumat = EEVEE_material_mesh_depth_get(scene, ma, true, true); + EEVEE_lights_cache_shcaster_material_add( + sldata, psl, gpumat, mat_geom[i], ob, NULL); + *cast_shadow = true; + break; + case MA_BS_NONE: + default: + break; + } + } + else { + EEVEE_lights_cache_shcaster_add(sldata, stl, mat_geom[i], ob); + *cast_shadow = true; } - } - else { - EEVEE_lights_cache_shcaster_add(sldata, stl, mat_geom[i], ob); - *cast_shadow = true; } } } @@ -1617,7 +1619,7 @@ void EEVEE_hair_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata, if (!psys_check_enabled(ob, psys, false)) { continue; } - if (!DRW_check_psys_visible_within_active_context(ob, psys)) { + if (!DRW_object_is_visible_psys_in_active_context(ob, psys)) { continue; } ParticleSettings *part = psys->part; diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c index 80d8c066a44..e24142e3f71 100644 --- a/source/blender/draw/engines/eevee/eevee_render.c +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -163,7 +163,7 @@ void EEVEE_render_cache( EEVEE_hair_cache_populate(vedata, sldata, ob, &cast_shadow); } - if (DRW_check_object_visible_within_active_context(ob)) { + if (DRW_object_is_visible_in_active_context(ob)) { if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) { EEVEE_materials_cache_populate(vedata, sldata, ob, &cast_shadow); } @@ -191,6 +191,12 @@ static void eevee_render_result_combined( rect->xmin, rect->ymin, BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), 4, 0, rp->rect); + + /* Premult alpha */ + int pixels_len = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect); + for (int i = 0; i < pixels_len * 4; i += 4) { + mul_v3_fl(rp->rect + i, rp->rect[i + 3]); + } } static void eevee_render_result_subsurface( @@ -543,6 +549,9 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl /* Post Process */ EEVEE_draw_effects(sldata, vedata); + /* XXX Seems to fix TDR issue with NVidia drivers on linux. */ + glFinish(); + RE_engine_update_progress(engine, (float)(render_samples++) / (float)tot_sample); } diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c index 256838609a6..4fffa3f285c 100644 --- a/source/blender/draw/engines/eevee/eevee_volumes.c +++ b/source/blender/draw/engines/eevee/eevee_volumes.c @@ -46,6 +46,7 @@ #include "eevee_private.h" #include "GPU_draw.h" #include "GPU_texture.h" +#include "GPU_material.h" static struct { char *volumetric_common_lib; @@ -471,13 +472,13 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved struct GPUMaterial *mat = EEVEE_material_mesh_volume_get(scene, ma); - DRWShadingGroup *grp = DRW_shgroup_material_empty_tri_batch_create(mat, vedata->psl->volumetric_objects_ps, sldata->common_data.vol_tex_size[2]); - /* If shader failed to compile or is currently compiling. */ - if (grp == NULL) { + if (GPU_material_status(mat) != GPU_MAT_SUCCESS) { return; } + DRWShadingGroup *grp = DRW_shgroup_material_empty_tri_batch_create(mat, vedata->psl->volumetric_objects_ps, sldata->common_data.vol_tex_size[2]); + /* Making sure it's updated. */ invert_m4_m4(ob->imat, ob->obmat); diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl index 5f641c5d490..36c4562e137 100644 --- a/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl @@ -75,10 +75,11 @@ vec3 light_volume(LightData ld, vec4 l_vector) } else if (ld.l_type == SUN) { power = (4.0f * ld.l_radius * ld.l_radius * M_2PI) * (1.0 / 12.5); /* Removing area light power*/ - power *= M_2PI * 0.78; /* Matching cycles with point light. */ + power *= M_PI * 0.5; /* Matching cycles. */ } else { power = (4.0 * ld.l_radius * ld.l_radius) * (1.0 /10.0); + power *= M_2PI; /* Matching cycles with point light. */ } /* OPTI: find a better way than calculating this on the fly */ diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c index 40245810f42..8e7d16e60ba 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c @@ -414,7 +414,7 @@ GPUBatch *DRW_gpencil_get_fill_geom(Object *ob, bGPDstroke *gps, const float col /* Calculate triangles cache for filling area (must be done only after changes) */ if ((gps->flag & GP_STROKE_RECALC_CACHES) || (gps->tot_triangles == 0) || (gps->triangles == NULL)) { - DRW_gpencil_triangulate_stroke_fill(gps); + DRW_gpencil_triangulate_stroke_fill(ob, gps); ED_gpencil_calc_stroke_uv(ob, gps); } @@ -703,6 +703,7 @@ GPUBatch *DRW_gpencil_get_grid(Object *ob) const float grid_h = gpd->grid.scale[1] * ED_scene_grid_scale(scene, &grid_unit); const float space_w = (grid_w / gridlines); const float space_h = (grid_h / gridlines); + const float offset[2] = { gpd->grid.offset[0], gpd->grid.offset[1] }; const uint vertex_len = 2 * (gridlines * 4 + 2); @@ -722,34 +723,34 @@ GPUBatch *DRW_gpencil_get_grid(Object *ob) const float line_w = a * space_w; const float line_h = a * space_h; - set_grid_point(vbo, idx, col_grid, pos_id, color_id, -grid_w, -line_h, axis); + set_grid_point(vbo, idx, col_grid, pos_id, color_id, -grid_w + offset[0], -line_h + offset[1], axis); idx++; - set_grid_point(vbo, idx, col_grid, pos_id, color_id, +grid_w, -line_h, axis); + set_grid_point(vbo, idx, col_grid, pos_id, color_id, +grid_w + offset[0], -line_h + offset[1], axis); idx++; - set_grid_point(vbo, idx, col_grid, pos_id, color_id, -grid_w, +line_h, axis); + set_grid_point(vbo, idx, col_grid, pos_id, color_id, -grid_w + offset[0], +line_h + offset[1], axis); idx++; - set_grid_point(vbo, idx, col_grid, pos_id, color_id, +grid_w, +line_h, axis); + set_grid_point(vbo, idx, col_grid, pos_id, color_id, +grid_w + offset[0], +line_h + offset[1], axis); idx++; - set_grid_point(vbo, idx, col_grid, pos_id, color_id, -line_w, -grid_h, axis); + set_grid_point(vbo, idx, col_grid, pos_id, color_id, -line_w + offset[0], -grid_h + offset[1], axis); idx++; - set_grid_point(vbo, idx, col_grid, pos_id, color_id, -line_w, +grid_h, axis); + set_grid_point(vbo, idx, col_grid, pos_id, color_id, -line_w + offset[0], +grid_h + offset[1], axis); idx++; - set_grid_point(vbo, idx, col_grid, pos_id, color_id, +line_w, -grid_h, axis); + set_grid_point(vbo, idx, col_grid, pos_id, color_id, +line_w + offset[0], -grid_h + offset[1], axis); idx++; - set_grid_point(vbo, idx, col_grid, pos_id, color_id, +line_w, +grid_h, axis); + set_grid_point(vbo, idx, col_grid, pos_id, color_id, +line_w + offset[0], +grid_h + offset[1], axis); idx++; } /* center lines */ if (do_center) { - set_grid_point(vbo, idx, col_grid, pos_id, color_id, -grid_w, 0.0f, axis); + set_grid_point(vbo, idx, col_grid, pos_id, color_id, -grid_w + offset[0], 0.0f + offset[1], axis); idx++; - set_grid_point(vbo, idx, col_grid, pos_id, color_id, +grid_w, 0.0f, axis); + set_grid_point(vbo, idx, col_grid, pos_id, color_id, +grid_w + offset[0], 0.0f + offset[1], axis); idx++; - set_grid_point(vbo, idx, col_grid, pos_id, color_id, 0.0f, -grid_h, axis); + set_grid_point(vbo, idx, col_grid, pos_id, color_id, 0.0f + offset[0], -grid_h + offset[1], axis); idx++; - set_grid_point(vbo, idx, col_grid, pos_id, color_id, 0.0f, +grid_h, axis); + set_grid_point(vbo, idx, col_grid, pos_id, color_id, 0.0f + offset[0], +grid_h + offset[1], axis); idx++; } return GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO); diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c index f7823a2fced..03a6f7342ab 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c @@ -92,7 +92,7 @@ static bool gpencil_can_draw_stroke( /* calc bounding box in 2d using flat projection data */ static void gpencil_calc_2d_bounding_box( - const float(*points2d)[2], int totpoints, float minv[2], float maxv[2], bool expand) + const float(*points2d)[2], int totpoints, float minv[2], float maxv[2]) { minv[0] = points2d[0][0]; minv[1] = points2d[0][1]; @@ -115,14 +115,12 @@ static void gpencil_calc_2d_bounding_box( maxv[1] = points2d[i][1]; } } - /* If not expanded, use a perfect square */ - if (expand == false) { - if (maxv[0] > maxv[1]) { - maxv[1] = maxv[0]; - } - else { - maxv[0] = maxv[1]; - } + /* use a perfect square */ + if (maxv[0] > maxv[1]) { + maxv[1] = maxv[0]; + } + else { + maxv[0] = maxv[1]; } } @@ -184,10 +182,12 @@ static void gpencil_stroke_2d_flat(const bGPDspoint *points, int totpoints, floa } /* Triangulate stroke for high quality fill (this is done only if cache is null or stroke was modified) */ -void DRW_gpencil_triangulate_stroke_fill(bGPDstroke *gps) +void DRW_gpencil_triangulate_stroke_fill(Object *ob, bGPDstroke *gps) { BLI_assert(gps->totpoints >= 3); + bGPdata *gpd = (bGPdata *)ob->data; + /* allocate memory for temporary areas */ gps->tot_triangles = gps->totpoints - 2; uint(*tmp_triangles)[3] = MEM_mallocN(sizeof(*tmp_triangles) * gps->tot_triangles, "GP Stroke temp triangulation"); @@ -204,7 +204,14 @@ void DRW_gpencil_triangulate_stroke_fill(bGPDstroke *gps) float minv[2]; float maxv[2]; /* first needs bounding box data */ - gpencil_calc_2d_bounding_box(points2d, gps->totpoints, minv, maxv, false); + if (gpd->flag & GP_DATA_UV_ADAPTATIVE) { + gpencil_calc_2d_bounding_box(points2d, gps->totpoints, minv, maxv); + } + else { + ARRAY_SET_ITEMS(minv, -1.0f, -1.0f); + ARRAY_SET_ITEMS(maxv, 1.0f, 1.0f); + } + /* calc uv data */ gpencil_calc_stroke_fill_uv(points2d, gps->totpoints, minv, maxv, uv); @@ -256,7 +263,7 @@ static void DRW_gpencil_recalc_geometry_caches(Object *ob, MaterialGPencilStyle if ((gps->totpoints > 2) && ((gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) || (gp_style->fill_style > 0))) { - DRW_gpencil_triangulate_stroke_fill(gps); + DRW_gpencil_triangulate_stroke_fill(ob, gps); } } diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index 0b318bd974e..d854336cfd0 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -549,7 +549,7 @@ static void gpencil_add_draw_data(void *vedata, Object *ob) void GPENCIL_cache_populate(void *vedata, Object *ob) { /* object must be visible */ - if (!DRW_check_object_visible_within_active_context(ob)) { + if (!DRW_object_is_visible_in_active_context(ob)) { return; } diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h index df051f4697b..b8844d3c3e9 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.h +++ b/source/blender/draw/engines/gpencil/gpencil_engine.h @@ -73,6 +73,7 @@ typedef struct tGPencilObjectCache { DRWShadingGroup *fx_pixel_sh; DRWShadingGroup *fx_rim_sh; DRWShadingGroup *fx_shadow_sh; + DRWShadingGroup *fx_glow_sh; DRWShadingGroup *fx_swirl_sh; DRWShadingGroup *fx_flip_sh; DRWShadingGroup *fx_light_sh; @@ -231,6 +232,8 @@ typedef struct GPENCIL_e_data { struct GPUShader *gpencil_fx_blur_sh; struct GPUShader *gpencil_fx_colorize_sh; struct GPUShader *gpencil_fx_flip_sh; + struct GPUShader *gpencil_fx_glow_prepare_sh; + struct GPUShader *gpencil_fx_glow_resolve_sh; struct GPUShader *gpencil_fx_light_sh; struct GPUShader *gpencil_fx_pixel_sh; struct GPUShader *gpencil_fx_rim_prepare_sh; @@ -303,7 +306,7 @@ void DRW_gpencil_populate_buffer_strokes( void DRW_gpencil_populate_multiedit( struct GPENCIL_e_data *e_data, void *vedata, struct Scene *scene, struct Object *ob, struct tGPencilObjectCache *cache_ob); -void DRW_gpencil_triangulate_stroke_fill(struct bGPDstroke *gps); +void DRW_gpencil_triangulate_stroke_fill(struct Object *ob, struct bGPDstroke *gps); void DRW_gpencil_multisample_ensure(struct GPENCIL_Data *vedata, int rect_w, int rect_h); diff --git a/source/blender/draw/engines/gpencil/gpencil_render.c b/source/blender/draw/engines/gpencil/gpencil_render.c index 41f0c601a13..8dc15472a20 100644 --- a/source/blender/draw/engines/gpencil/gpencil_render.c +++ b/source/blender/draw/engines/gpencil/gpencil_render.c @@ -130,7 +130,7 @@ static void GPENCIL_render_cache( void *vedata, struct Object *ob, struct RenderEngine *UNUSED(engine), struct Depsgraph *UNUSED(depsgraph)) { - if ((ob == NULL) || (DRW_check_object_visible_within_active_context(ob) == false)) { + if ((ob == NULL) || (DRW_object_is_visible_in_active_context(ob) == false)) { return; } diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c index 9e04365fe1d..2165fb251dc 100644 --- a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c +++ b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c @@ -50,6 +50,8 @@ extern char datatoc_gpencil_fx_rim_prepare_frag_glsl[]; extern char datatoc_gpencil_fx_rim_resolve_frag_glsl[]; extern char datatoc_gpencil_fx_shadow_prepare_frag_glsl[]; extern char datatoc_gpencil_fx_shadow_resolve_frag_glsl[]; +extern char datatoc_gpencil_fx_glow_prepare_frag_glsl[]; +extern char datatoc_gpencil_fx_glow_resolve_frag_glsl[]; extern char datatoc_gpencil_fx_swirl_frag_glsl[]; extern char datatoc_gpencil_fx_wave_frag_glsl[]; @@ -208,7 +210,7 @@ static void DRW_gpencil_fx_blur( } } - struct GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); + GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); fx_shgrp = DRW_shgroup_create( e_data->gpencil_fx_blur_sh, @@ -236,7 +238,7 @@ static void DRW_gpencil_fx_colorize( GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; DRWShadingGroup *fx_shgrp; - struct GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); + GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_colorize_sh, psl->fx_shader_pass); DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); @@ -269,7 +271,7 @@ static void DRW_gpencil_fx_flip( fxd->flipmode += 1; } - struct GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); + GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_flip_sh, psl->fx_shader_pass); DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); @@ -298,7 +300,7 @@ static void DRW_gpencil_fx_light( GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; DRWShadingGroup *fx_shgrp; - struct GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); + GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_light_sh, psl->fx_shader_pass); DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); @@ -351,7 +353,7 @@ static void DRW_gpencil_fx_pixel( fxd->size[2] = (int)fxd->flag & FX_PIXEL_USE_LINES; - struct GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); + GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_pixel_sh, psl->fx_shader_pass); DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); @@ -380,7 +382,7 @@ static void DRW_gpencil_fx_rim( GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; DRWShadingGroup *fx_shgrp; - struct GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); + GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); /* prepare pass */ fx_shgrp = DRW_shgroup_create( e_data->gpencil_fx_rim_prepare_sh, @@ -431,8 +433,8 @@ static void DRW_gpencil_fx_rim( /* Shadow FX */ static void DRW_gpencil_fx_shadow( - ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata, - tGPencilObjectCache *cache) + ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata, + tGPencilObjectCache *cache) { if (fx == NULL) { return; @@ -446,7 +448,7 @@ static void DRW_gpencil_fx_shadow( GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; DRWShadingGroup *fx_shgrp; - struct GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); + GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); /* prepare pass */ fx_shgrp = DRW_shgroup_create( e_data->gpencil_fx_shadow_prepare_sh, @@ -512,10 +514,71 @@ static void DRW_gpencil_fx_shadow( fxd->runtime.fx_sh_c = fx_shgrp; } +/* Glow FX */ +static void DRW_gpencil_fx_glow( + ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata, + tGPencilObjectCache *cache) +{ + if (fx == NULL) { + return; + } + GlowShaderFxData *fxd = (GlowShaderFxData *)fx; + + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; + DRWShadingGroup *fx_shgrp; + + GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); + /* prepare pass */ + fx_shgrp = DRW_shgroup_create( + e_data->gpencil_fx_glow_prepare_sh, + psl->fx_shader_pass_blend); + DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); + + DRW_shgroup_uniform_vec3(fx_shgrp, "glow_color", &fxd->glow_color[0], 1); + DRW_shgroup_uniform_vec3(fx_shgrp, "select_color", &fxd->select_color[0], 1); + DRW_shgroup_uniform_int(fx_shgrp, "mode", &fxd->mode, 1); + DRW_shgroup_uniform_float(fx_shgrp, "threshold", &fxd->threshold, 1); + + fxd->runtime.fx_sh = fx_shgrp; + + /* blur pass */ + fx_shgrp = DRW_shgroup_create( + e_data->gpencil_fx_blur_sh, + psl->fx_shader_pass_blend); + DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_fx); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_fx); + DRW_shgroup_uniform_int(fx_shgrp, "blur", &fxd->blur[0], 2); + + DRW_shgroup_uniform_vec3(fx_shgrp, "loc", &cache->loc[0], 1); + DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1); + DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &cache->pixfactor, 1); + + fxd->runtime.fx_sh_b = fx_shgrp; + + /* resolve pass */ + fx_shgrp = DRW_shgroup_create( + e_data->gpencil_fx_glow_resolve_sh, + psl->fx_shader_pass_blend); + DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "glowColor", &e_data->temp_color_tx_fx); + DRW_shgroup_uniform_texture_ref(fx_shgrp, "glowDepth", &e_data->temp_depth_tx_fx); + + /* reuse field */ + DRW_shgroup_uniform_int(fx_shgrp, "alpha_mode", &fxd->blur[1], 1); + + fxd->runtime.fx_sh_c = fx_shgrp; +} + /* Swirl FX */ static void DRW_gpencil_fx_swirl( ShaderFxData *fx, GPENCIL_e_data *e_data, GPENCIL_Data *vedata, - tGPencilObjectCache *cache) + tGPencilObjectCache *cache) { if (fx == NULL) { return; @@ -531,7 +594,7 @@ static void DRW_gpencil_fx_swirl( fxd->transparent = (int)fxd->flag & FX_SWIRL_MAKE_TRANSPARENT; - struct GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); + GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_swirl_sh, psl->fx_shader_pass); DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeColor", &e_data->temp_color_tx_a); @@ -562,7 +625,7 @@ static void DRW_gpencil_fx_wave( WaveShaderFxData *fxd = (WaveShaderFxData *)fx; GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; - struct GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); + GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); DRWShadingGroup *fx_shgrp = DRW_shgroup_create(e_data->gpencil_fx_wave_sh, psl->fx_shader_pass); DRW_shgroup_call_add(fx_shgrp, fxquad, NULL); @@ -617,6 +680,13 @@ void GPENCIL_create_fx_shaders(GPENCIL_e_data *e_data) e_data->gpencil_fx_shadow_resolve_sh = DRW_shader_create_fullscreen( datatoc_gpencil_fx_shadow_resolve_frag_glsl, NULL); } + if (!e_data->gpencil_fx_glow_prepare_sh) { + e_data->gpencil_fx_glow_prepare_sh = DRW_shader_create_fullscreen( + datatoc_gpencil_fx_glow_prepare_frag_glsl, NULL); + + e_data->gpencil_fx_glow_resolve_sh = DRW_shader_create_fullscreen( + datatoc_gpencil_fx_glow_resolve_frag_glsl, NULL); + } if (!e_data->gpencil_fx_swirl_sh) { e_data->gpencil_fx_swirl_sh = DRW_shader_create_fullscreen( datatoc_gpencil_fx_swirl_frag_glsl, NULL); @@ -639,6 +709,8 @@ void GPENCIL_delete_fx_shaders(GPENCIL_e_data *e_data) DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_rim_resolve_sh); DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_shadow_prepare_sh); DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_shadow_resolve_sh); + DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_glow_prepare_sh); + DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_glow_resolve_sh); DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_swirl_sh); DRW_SHADER_FREE_SAFE(e_data->gpencil_fx_wave_sh); } @@ -659,8 +731,8 @@ void GPENCIL_create_fx_passes(GPENCIL_PassList *psl) /* prepare fx shading groups */ void DRW_gpencil_fx_prepare( - struct GPENCIL_e_data *e_data, struct GPENCIL_Data *vedata, - struct tGPencilObjectCache *cache) + GPENCIL_e_data *e_data, GPENCIL_Data *vedata, + tGPencilObjectCache *cache) { GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; int ob_idx = cache->idx; @@ -693,6 +765,9 @@ void DRW_gpencil_fx_prepare( case eShaderFxType_Shadow: DRW_gpencil_fx_shadow(fx, e_data, vedata, cache); break; + case eShaderFxType_Glow: + DRW_gpencil_fx_glow(fx, e_data, vedata, cache); + break; case eShaderFxType_Swirl: DRW_gpencil_fx_swirl(fx, e_data, vedata, cache); break; @@ -718,8 +793,7 @@ static void gpencil_draw_fx_pass( return; } - static float clearcol[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; - + const float clearcol[4] = {0.0f}; GPU_framebuffer_bind(fbl->temp_fb_b); GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f); @@ -743,9 +817,9 @@ static void gpencil_draw_fx_pass( /* helper to manage gaussian blur passes */ static void draw_gpencil_blur_passes( - struct GPENCIL_e_data *e_data, - struct GPENCIL_Data *vedata, - struct BlurShaderFxData *fxd) + GPENCIL_e_data *e_data, + GPENCIL_Data *vedata, + BlurShaderFxData *fxd) { if (fxd->runtime.fx_sh == NULL) { return; @@ -782,19 +856,19 @@ static void draw_gpencil_blur_passes( } } -static void draw_gpencil_rim_blur( - struct GPENCIL_e_data *UNUSED(e_data), - struct GPENCIL_Data *vedata, - struct RimShaderFxData *fxd) +/* blur intermediate pass */ +static void draw_gpencil_midpass_blur( + GPENCIL_Data *vedata, + ShaderFxData_Runtime *runtime) { GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl; - static float clearcol[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + const float clearcol[4] = {0.0f}; GPU_framebuffer_bind(fbl->temp_fb_b); GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f); DRW_draw_pass_subset(psl->fx_shader_pass_blend, - fxd->runtime.fx_sh_b, fxd->runtime.fx_sh_b); + runtime->fx_sh_b, runtime->fx_sh_b); /* copy pass from b for ping-pong frame buffers */ GPU_framebuffer_bind(fbl->temp_fb_fx); @@ -802,11 +876,40 @@ static void draw_gpencil_rim_blur( DRW_draw_pass(psl->mix_pass_noblend); } +/* do blur of mid passes */ +static void draw_gpencil_do_blur( + GPENCIL_e_data *e_data, + GPENCIL_Data *vedata, + ShaderFxData_Runtime *runtime, + int samples, int bx, int by, int blur[2]) +{ + e_data->input_depth_tx = e_data->temp_depth_tx_b; + e_data->input_color_tx = e_data->temp_color_tx_b; + + if ((samples > 0) && ((bx > 0) || (by > 0))) { + for (int x = 0; x < samples * 4; x++) { + + /* horizontal */ + blur[0] = bx; + blur[1] = 0; + draw_gpencil_midpass_blur(vedata, runtime); + + /* Vertical */ + blur[0] = 0; + blur[1] = by; + draw_gpencil_midpass_blur(vedata, runtime); + + blur[0] = bx; + blur[1] = by; + } + } +} + /* helper to draw RIM passes */ static void draw_gpencil_rim_passes( - struct GPENCIL_e_data *e_data, - struct GPENCIL_Data *vedata, - struct RimShaderFxData *fxd) + GPENCIL_e_data *e_data, + GPENCIL_Data *vedata, + RimShaderFxData *fxd) { if (fxd->runtime.fx_sh_b == NULL) { return; @@ -815,9 +918,7 @@ static void draw_gpencil_rim_passes( GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl; - static float clearcol[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; - int bx = fxd->blur[0]; - int by = fxd->blur[1]; + const float clearcol[4] = {0.0f}; /* prepare mask */ GPU_framebuffer_bind(fbl->temp_fb_fx); @@ -827,26 +928,11 @@ static void draw_gpencil_rim_passes( fxd->runtime.fx_sh, fxd->runtime.fx_sh); /* blur rim */ - e_data->input_depth_tx = e_data->temp_depth_tx_b; - e_data->input_color_tx = e_data->temp_color_tx_b; - - if ((fxd->samples > 0) && ((bx > 0) || (by > 0))) { - for (int x = 0; x < fxd->samples; x++) { - - /* horizontal */ - fxd->blur[0] = bx; - fxd->blur[1] = 0; - draw_gpencil_rim_blur(e_data, vedata, fxd); - - /* Vertical */ - fxd->blur[0] = 0; - fxd->blur[1] = by; - draw_gpencil_rim_blur(e_data, vedata, fxd); - - fxd->blur[0] = bx; - fxd->blur[1] = by; - } - } + draw_gpencil_do_blur( + e_data, vedata, &fxd->runtime, + fxd->samples, + fxd->blur[0], fxd->blur[1], + &fxd->blur[0]); /* resolve */ GPU_framebuffer_bind(fbl->temp_fb_b); @@ -864,32 +950,55 @@ static void draw_gpencil_rim_passes( DRW_draw_pass(psl->mix_pass_noblend); } -/* blur shadow */ -static void draw_gpencil_shadow_blur( - struct GPENCIL_e_data *UNUSED(e_data), - struct GPENCIL_Data *vedata, - struct ShadowShaderFxData *fxd) +/* helper to draw SHADOW passes */ +static void draw_gpencil_shadow_passes( + GPENCIL_e_data *e_data, + GPENCIL_Data *vedata, + ShadowShaderFxData *fxd) { + if (fxd->runtime.fx_sh_b == NULL) { + return; + } + GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl; - static float clearcol[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + const float clearcol[4] = {0.0f}; + + /* prepare shadow */ + GPU_framebuffer_bind(fbl->temp_fb_fx); + GPU_framebuffer_clear_color_depth(fbl->temp_fb_fx, clearcol, 1.0f); + DRW_draw_pass_subset( + psl->fx_shader_pass_blend, + fxd->runtime.fx_sh, fxd->runtime.fx_sh); + + /* blur shadow */ + draw_gpencil_do_blur( + e_data, vedata, &fxd->runtime, + fxd->samples, + fxd->blur[0], fxd->blur[1], + &fxd->blur[0]); + /* resolve */ GPU_framebuffer_bind(fbl->temp_fb_b); GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f); - DRW_draw_pass_subset(psl->fx_shader_pass_blend, - fxd->runtime.fx_sh_b, fxd->runtime.fx_sh_b); + DRW_draw_pass_subset( + psl->fx_shader_pass_blend, + fxd->runtime.fx_sh_c, fxd->runtime.fx_sh_c); - /* copy pass from b for ping-pong frame buffers */ - GPU_framebuffer_bind(fbl->temp_fb_fx); - GPU_framebuffer_clear_color_depth(fbl->temp_fb_fx, clearcol, 1.0f); + /* copy pass from b to a for ping-pong frame buffers */ + e_data->input_depth_tx = e_data->temp_depth_tx_b; + e_data->input_color_tx = e_data->temp_color_tx_b; + + GPU_framebuffer_bind(fbl->temp_fb_a); + GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f); DRW_draw_pass(psl->mix_pass_noblend); } -/* helper to draw SHADOW passes */ -static void draw_gpencil_shadow_passes( - struct GPENCIL_e_data *e_data, - struct GPENCIL_Data *vedata, - struct ShadowShaderFxData *fxd) +/* helper to draw GLOW passes */ +static void draw_gpencil_glow_passes( + GPENCIL_e_data *e_data, + GPENCIL_Data *vedata, + GlowShaderFxData *fxd) { if (fxd->runtime.fx_sh_b == NULL) { return; @@ -898,42 +1007,29 @@ static void draw_gpencil_shadow_passes( GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl; - static float clearcol[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; - int bx = fxd->blur[0]; - int by = fxd->blur[1]; + const float clearcol[4] = {0.0f}; - /* prepare shadow */ + /* prepare glow */ GPU_framebuffer_bind(fbl->temp_fb_fx); GPU_framebuffer_clear_color_depth(fbl->temp_fb_fx, clearcol, 1.0f); DRW_draw_pass_subset( psl->fx_shader_pass_blend, fxd->runtime.fx_sh, fxd->runtime.fx_sh); - /* blur shadow */ - e_data->input_depth_tx = e_data->temp_depth_tx_b; - e_data->input_color_tx = e_data->temp_color_tx_b; - - if ((fxd->samples > 0) && ((bx > 0) || (by > 0))) { - for (int x = 0; x < fxd->samples; x++) { - - /* horizontal */ - fxd->blur[0] = bx; - fxd->blur[1] = 0; - draw_gpencil_shadow_blur(e_data, vedata, fxd); - - /* Vertical */ - fxd->blur[0] = 0; - fxd->blur[1] = by; - draw_gpencil_shadow_blur(e_data, vedata, fxd); - - fxd->blur[0] = bx; - fxd->blur[1] = by; - } - } + /* blur glow */ + draw_gpencil_do_blur( + e_data, vedata, &fxd->runtime, + fxd->samples, + fxd->blur[0], fxd->blur[0], + &fxd->blur[0]); /* resolve */ GPU_framebuffer_bind(fbl->temp_fb_b); GPU_framebuffer_clear_color_depth(fbl->temp_fb_b, clearcol, 1.0f); + + /* reuses blur field to keep alpha mode */ + fxd->blur[1] = (fxd->flag & FX_GLOW_USE_ALPHA) ? 1 : 0; + DRW_draw_pass_subset( psl->fx_shader_pass_blend, fxd->runtime.fx_sh_c, fxd->runtime.fx_sh_c); @@ -949,8 +1045,8 @@ static void draw_gpencil_shadow_passes( /* apply all object fx effects */ void DRW_gpencil_fx_draw( - struct GPENCIL_e_data *e_data, - struct GPENCIL_Data *vedata, struct tGPencilObjectCache *cache) + GPENCIL_e_data *e_data, + GPENCIL_Data *vedata, tGPencilObjectCache *cache) { GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; @@ -1003,6 +1099,12 @@ void DRW_gpencil_fx_draw( draw_gpencil_shadow_passes(e_data, vedata, fxd); break; } + case eShaderFxType_Glow: + { + GlowShaderFxData *fxd = (GlowShaderFxData *)fx; + draw_gpencil_glow_passes(e_data, vedata, fxd); + break; + } case eShaderFxType_Swirl: { SwirlShaderFxData *fxd = (SwirlShaderFxData *)fx; diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_blur_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_blur_frag.glsl index c2bf1dbc1a7..c8bc5e1fe91 100644 --- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_blur_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_blur_frag.glsl @@ -56,4 +56,7 @@ void main() outcolor += texelFetch(strokeColor, ivec2(uv.x + 1.0 * dx, uv.y - 1.0 * dy), 0) * 0.0947416; FragColor = clamp(outcolor, 0, 1.0); + + if (outcolor.a < 0.02f) + discard; } diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_glow_prepare_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_glow_prepare_frag.glsl new file mode 100644 index 00000000000..237cdf15627 --- /dev/null +++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_glow_prepare_frag.glsl @@ -0,0 +1,68 @@ +uniform mat4 ProjectionMatrix; +uniform mat4 ViewMatrix; + +/* ******************************************************************* */ +/* create glow mask */ +/* ******************************************************************* */ +uniform sampler2D strokeColor; +uniform sampler2D strokeDepth; + +uniform vec3 glow_color; +uniform vec3 select_color; +uniform float threshold; +uniform int mode; + +out vec4 FragColor; + +#define MODE_LUMINANCE 0 +#define MODE_COLOR 1 + +/* calc luminance */ +float luma( vec3 color ) { + /* the color is linear, so do not apply tonemapping */ + return (color.r + color.g + color.b) / 3.0; +} + +bool check_color(vec3 color_a, vec3 color_b) +{ + /* need round the number to avoid precision errors */ + if ((floor(color_a.r * 100) == floor(color_b.r * 100)) && + (floor(color_a.g * 100) == floor(color_b.g * 100)) && + (floor(color_a.b * 100) == floor(color_b.b * 100))) + { + return true; + } + + return false; +} + +void main() +{ + vec2 uv = vec2(gl_FragCoord.xy); + + float stroke_depth = texelFetch(strokeDepth, ivec2(uv.xy), 0).r; + vec4 src_pixel= texelFetch(strokeColor, ivec2(uv.xy), 0); + vec4 outcolor; + + /* is transparent */ + if (src_pixel.a == 0.0f) { + discard; + } + + if (mode == MODE_LUMINANCE) { + if (luma(src_pixel.rgb) < threshold) { + discard; + } + } + else if (mode == MODE_COLOR) { + if (!check_color(src_pixel.rgb, select_color.rgb)) { + discard; + } + } + else { + discard; + } + + gl_FragDepth = stroke_depth; + FragColor = vec4(glow_color.rgb, 1.0); +} diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_glow_resolve_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_glow_resolve_frag.glsl new file mode 100644 index 00000000000..010c4ef4a88 --- /dev/null +++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_glow_resolve_frag.glsl @@ -0,0 +1,46 @@ +/* ******************************************************************* */ +/* Resolve GLOW pass */ +/* ******************************************************************* */ +uniform sampler2D strokeColor; +uniform sampler2D strokeDepth; +uniform sampler2D glowColor; +uniform sampler2D glowDepth; +uniform int alpha_mode; + +out vec4 FragColor; + +void main() +{ + vec4 outcolor; + ivec2 uv = ivec2(gl_FragCoord.xy); + + float stroke_depth = texelFetch(strokeDepth, uv.xy, 0).r; + vec4 src_pixel= texelFetch(strokeColor, uv.xy, 0); + vec4 glow_pixel= texelFetch(glowColor, uv.xy, 0); + float glow_depth = texelFetch(glowDepth, uv.xy, 0).r; + + if (alpha_mode == 0) { + outcolor = src_pixel + glow_pixel; + } + else { + if ((src_pixel.a < 0.1) || (glow_pixel.a < 0.1)) { + outcolor = src_pixel + glow_pixel; + } + else { + outcolor = src_pixel; + } + } + + if (src_pixel.a < glow_pixel.a) { + gl_FragDepth = glow_depth; + } + else { + gl_FragDepth = stroke_depth; + } + + if (outcolor.a < 0.001) { + discard; + } + + FragColor = outcolor; +} diff --git a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_wave_frag.glsl b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_wave_frag.glsl index 882b2cf59f1..df5248c7791 100644 --- a/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_wave_frag.glsl +++ b/source/blender/draw/engines/gpencil/shaders/fx/gpencil_fx_wave_frag.glsl @@ -37,4 +37,7 @@ void main() FragColor = outcolor; gl_FragDepth = stroke_depth; + + if (outcolor.a < 0.02f) + discard; } diff --git a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl index 1f14e506dcf..5b949a6d952 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_frag.glsl @@ -3,9 +3,15 @@ uniform mat4 ProjectionMatrix; uniform mat4 ModelMatrixInverse; uniform mat4 ModelViewMatrixInverse; uniform mat4 ModelMatrix; +uniform vec3 OrcoTexCoFactors[2]; uniform sampler2D depthBuffer; + uniform sampler3D densityTexture; +uniform sampler3D shadowTexture; +uniform sampler3D flameTexture; +uniform sampler1D flameColorTexture; +uniform sampler1D transferTexture; uniform int samplesLen = 256; uniform float stepLength; /* Step length in local space. */ @@ -62,15 +68,35 @@ float line_unit_box_intersect_dist(vec3 lineorigin, vec3 linedirection) void volume_properties(vec3 ls_pos, out vec3 scattering, out float extinction) { - scattering = vec3(0.0); - extinction = 1e-8; + vec3 co = ls_pos * 0.5 + 0.5; +#ifdef USE_COBA + float val = texture(densityTexture, co).r; + vec4 tval = texture(transferTexture, val) * densityScale; + tval.rgb = pow(tval.rgb, vec3(2.2)); + scattering = tval.rgb * 1500.0; + extinction = max(1e-4, tval.a * 50.0); +#else + float flame = texture(flameTexture, co).r; + vec4 emission = texture(flameColorTexture, flame); + float shadows = texture(shadowTexture, co).r; + vec4 density = texture(densityTexture, co); /* rgb: color, a: density */ + + scattering = density.rgb * density.a * densityScale; + extinction = max(1e-4, dot(scattering, vec3(0.33333))); - vec4 density = texture(densityTexture, ls_pos * 0.5 + 0.5); - density.rgb /= density.a; - density *= densityScale; + scattering *= shadows * M_PI; + /* 800 is arbitrary and here to mimic old viewport. TODO make it a parameter */ + scattering += pow(emission.rgb, vec3(2.2)) * emission.a * 800.0; +#endif +} - scattering = density.rgb; - extinction = max(1e-8, density.a); +void eval_volume_step(inout vec3 Lscat, float extinction, float step_len, out float Tr) +{ + Lscat *= phase_function_isotropic(); + /* Evaluate Scattering */ + Tr = exp(-extinction * step_len); + /* integrate along the current step segment */ + Lscat = (Lscat - Lscat * Tr) / extinction; } #define P(x) ((x + 0.5) * (1.0 / 16.0)) @@ -96,18 +122,15 @@ vec4 volume_integration( vec3 ls_pos = ray_ori + ray_dir * ray_len; vec3 Lscat; - float s_extinction; + float s_extinction, Tr; volume_properties(ls_pos, Lscat, s_extinction); - /* Evaluate Scattering */ - float Tr = exp(-s_extinction * step_len); - /* integrate along the current step segment */ - Lscat = (Lscat - Lscat * Tr) / s_extinction; + eval_volume_step(Lscat, s_extinction, step_len, Tr); /* accumulate and also take into account the transmittance from previous steps */ final_scattering += final_transmittance * Lscat; final_transmittance *= Tr; } - return vec4(final_scattering, 1.0 - final_transmittance); + return vec4(final_scattering, final_transmittance); } void main() @@ -134,15 +157,11 @@ void main() step_len = 1.0 / step_len; vec3 Lscat; - float s_extinction; + float s_extinction, Tr; volume_properties(localPos, Lscat, s_extinction); - /* Evaluate Scattering */ - float Tr = exp(-s_extinction * step_len); - /* integrate along the current step segment */ - Lscat = (Lscat - Lscat * Tr) / s_extinction; - - fragColor = vec4(Lscat, 1.0 - Tr); + eval_volume_step(Lscat, s_extinction, step_len, Tr); + fragColor = vec4(Lscat, Tr); #else vec2 screen_uv = gl_FragCoord.xy / vec2(textureSize(depthBuffer, 0).xy); bool is_persp = ProjectionMatrix[3][3] == 0.0; @@ -156,10 +175,13 @@ void main() vec3 vs_ray_dir = (is_persp) ? (vs_ray_end - vs_ray_ori) : vec3(0.0, 0.0, -1.0); vs_ray_dir /= abs(vs_ray_dir.z); - vec3 ls_ray_dir = mat3(ModelViewMatrixInverse) * vs_ray_dir; + vec3 ls_ray_dir = mat3(ModelViewMatrixInverse) * vs_ray_dir * OrcoTexCoFactors[1] * 2.0; vec3 ls_ray_ori = (ModelViewMatrixInverse * vec4(vs_ray_ori, 1.0)).xyz; vec3 ls_ray_end = (ModelViewMatrixInverse * vec4(vs_ray_end, 1.0)).xyz; + ls_ray_ori = (OrcoTexCoFactors[0] + ls_ray_ori * OrcoTexCoFactors[1]) * 2.0 - 1.0; + ls_ray_end = (OrcoTexCoFactors[0] + ls_ray_end * OrcoTexCoFactors[1]) * 2.0 - 1.0; + /* TODO: Align rays to volume center so that it mimics old behaviour of slicing the volume. */ float dist = line_unit_box_intersect_dist(ls_ray_ori, ls_ray_dir); diff --git a/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl index 90a22d9d02f..7ce21c3d5ca 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_volume_vert.glsl @@ -1,5 +1,6 @@ uniform mat4 ModelViewProjectionMatrix; +uniform vec3 OrcoTexCoFactors[2]; uniform float slicePosition; uniform int sliceAxis; /* -1 is no slice, 0 is X, 1 is Y, 2 is Z. */ @@ -23,9 +24,10 @@ void main() else { localPos = vec3(pos.xy, slicePosition * 2.0 - 1.0); } - - gl_Position = ModelViewProjectionMatrix * vec4(localPos, 1.0); + vec3 final_pos = localPos; #else - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + vec3 final_pos = pos; #endif + final_pos = ((final_pos * 0.5 + 0.5) - OrcoTexCoFactors[0]) / OrcoTexCoFactors[1]; + gl_Position = ModelViewProjectionMatrix * vec4(final_pos, 1.0); } diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c index 7fbe928d29e..a1345afcf11 100644 --- a/source/blender/draw/engines/workbench/workbench_deferred.c +++ b/source/blender/draw/engines/workbench/workbench_deferred.c @@ -649,7 +649,7 @@ static void workbench_cache_populate_particles(WORKBENCH_Data *vedata, Object *o if (!psys_check_enabled(ob, psys, false)) { continue; } - if (!DRW_check_psys_visible_within_active_context(ob, psys)) { + if (!DRW_object_is_visible_psys_in_active_context(ob, psys)) { continue; } ParticleSettings *part = psys->part; @@ -701,7 +701,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob) return; /* Do not draw solid in this case. */ } - if (!DRW_check_object_visible_within_active_context(ob)) { + if (!DRW_object_is_visible_in_active_context(ob) || (ob->dt < OB_SOLID)) { return; } diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c index 0d4329c9699..cb11864df54 100644 --- a/source/blender/draw/engines/workbench/workbench_forward.c +++ b/source/blender/draw/engines/workbench/workbench_forward.c @@ -420,7 +420,7 @@ static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, O if (!psys_check_enabled(ob, psys, false)) { continue; } - if (!DRW_check_psys_visible_within_active_context(ob, psys)) { + if (!DRW_object_is_visible_psys_in_active_context(ob, psys)) { continue; } ParticleSettings *part = psys->part; @@ -487,7 +487,7 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob) return; /* Do not draw solid in this case. */ } - if (!DRW_check_object_visible_within_active_context(ob)) { + if (!DRW_object_is_visible_in_active_context(ob) || (ob->dt < OB_SOLID)) { return; } diff --git a/source/blender/draw/engines/workbench/workbench_volume.c b/source/blender/draw/engines/workbench/workbench_volume.c index ea4152486af..b0c08a2dc28 100644 --- a/source/blender/draw/engines/workbench/workbench_volume.c +++ b/source/blender/draw/engines/workbench/workbench_volume.c @@ -35,7 +35,11 @@ static struct { struct GPUShader *volume_sh; + struct GPUShader *volume_coba_sh; struct GPUShader *volume_slice_sh; + struct GPUShader *volume_slice_coba_sh; + struct GPUTexture *dummy_tex; + struct GPUTexture *dummy_coba_tex; } e_data = {NULL}; extern char datatoc_workbench_volume_vert_glsl[]; @@ -47,21 +51,39 @@ void workbench_volume_engine_init(void) e_data.volume_sh = DRW_shader_create( datatoc_workbench_volume_vert_glsl, NULL, datatoc_workbench_volume_frag_glsl, NULL); + e_data.volume_coba_sh = DRW_shader_create( + datatoc_workbench_volume_vert_glsl, NULL, + datatoc_workbench_volume_frag_glsl, + "#define USE_COBA\n"); e_data.volume_slice_sh = DRW_shader_create( datatoc_workbench_volume_vert_glsl, NULL, - datatoc_workbench_volume_frag_glsl, "#define VOLUME_SLICE"); + datatoc_workbench_volume_frag_glsl, + "#define VOLUME_SLICE\n"); + e_data.volume_slice_coba_sh = DRW_shader_create( + datatoc_workbench_volume_vert_glsl, NULL, + datatoc_workbench_volume_frag_glsl, + "#define VOLUME_SLICE\n" + "#define USE_COBA\n"); + + float pixel[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + e_data.dummy_tex = GPU_texture_create_3D(1, 1, 1, GPU_RGBA8, pixel, NULL); + e_data.dummy_coba_tex = GPU_texture_create_1D(1, GPU_RGBA8, pixel, NULL); } } void workbench_volume_engine_free(void) { DRW_SHADER_FREE_SAFE(e_data.volume_sh); + DRW_SHADER_FREE_SAFE(e_data.volume_coba_sh); DRW_SHADER_FREE_SAFE(e_data.volume_slice_sh); + DRW_SHADER_FREE_SAFE(e_data.volume_slice_coba_sh); + DRW_TEXTURE_FREE_SAFE(e_data.dummy_tex); + DRW_TEXTURE_FREE_SAFE(e_data.dummy_coba_tex); } void workbench_volume_cache_init(WORKBENCH_Data *vedata) { - vedata->psl->volume_pass = DRW_pass_create("Volumes", DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_PREMUL | DRW_STATE_CULL_FRONT); + vedata->psl->volume_pass = DRW_pass_create("Volumes", DRW_STATE_WRITE_COLOR | DRW_STATE_TRANSMISSION | DRW_STATE_CULL_FRONT); } void workbench_volume_cache_populate(WORKBENCH_Data *vedata, Scene *scene, Object *ob, ModifierData *md) @@ -70,6 +92,7 @@ void workbench_volume_cache_populate(WORKBENCH_Data *vedata, Scene *scene, Objec SmokeDomainSettings *sds = smd->domain; WORKBENCH_PrivateData *wpd = vedata->stl->g_data; DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + DRWShadingGroup *grp = NULL; /* Don't show smoke before simulation starts, this could be made an option in the future. */ if (!sds->fluid || CFRA < sds->point_cache[0]->startframe) { @@ -77,21 +100,26 @@ void workbench_volume_cache_populate(WORKBENCH_Data *vedata, Scene *scene, Objec } wpd->volumes_do = true; - - if (!sds->wt || !(sds->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) { + if (sds->use_coba) { + GPU_create_smoke_coba_field(smd); + } + else if (!sds->wt || !(sds->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) { GPU_create_smoke(smd, 0); } else if (sds->wt && (sds->viewsettings & MOD_SMOKE_VIEW_SHOWBIG)) { GPU_create_smoke(smd, 1); } - if (sds->tex == NULL) { + if ((!sds->use_coba && sds->tex == NULL) || + (sds->use_coba && sds->tex_field == NULL)) + { return; } - if (sds->slice_method == MOD_SMOKE_SLICE_AXIS_ALIGNED && - sds->axis_slice_method == AXIS_SLICE_SINGLE) - { + const bool use_slice = (sds->slice_method == MOD_SMOKE_SLICE_AXIS_ALIGNED && + sds->axis_slice_method == AXIS_SLICE_SINGLE); + + if (use_slice) { float invviewmat[4][4]; DRW_viewport_matrix_get(invviewmat, DRW_MAT_VIEWINV); @@ -99,41 +127,46 @@ void workbench_volume_cache_populate(WORKBENCH_Data *vedata, Scene *scene, Objec ? axis_dominant_v3_single(invviewmat[2]) : sds->slice_axis - 1; - DRWShadingGroup *grp = DRW_shgroup_create(e_data.volume_slice_sh, vedata->psl->volume_pass); - DRW_shgroup_uniform_texture(grp, "densityTexture", sds->tex); - DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); - DRW_shgroup_uniform_float_copy(grp, "densityScale", 10.0f * sds->display_thickness); + GPUShader *sh = (sds->use_coba) ? e_data.volume_slice_coba_sh : e_data.volume_slice_sh; + grp = DRW_shgroup_create(sh, vedata->psl->volume_pass); DRW_shgroup_uniform_float_copy(grp, "slicePosition", sds->slice_depth); DRW_shgroup_uniform_int_copy(grp, "sliceAxis", axis); - DRW_shgroup_state_disable(grp, DRW_STATE_CULL_FRONT); - BLI_addtail(&wpd->smoke_domains, BLI_genericNodeN(smd)); - - /* TODO Flame rendering */ - /* TODO COBA Rendering */ - - DRW_shgroup_call_object_add(grp, DRW_cache_quad_get(), ob); } else { int max_slices = max_iii(sds->res[0], sds->res[1], sds->res[2]) * sds->slice_per_voxel; - DRWShadingGroup *grp = DRW_shgroup_create(e_data.volume_sh, vedata->psl->volume_pass); + GPUShader *sh = (sds->use_coba) ? e_data.volume_coba_sh : e_data.volume_sh; + grp = DRW_shgroup_create(sh, vedata->psl->volume_pass); DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)wpd->viewvecs, 3); - DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); - DRW_shgroup_uniform_texture(grp, "densityTexture", sds->tex); - DRW_shgroup_uniform_float_copy(grp, "densityScale", 10.0f * sds->display_thickness); DRW_shgroup_uniform_int_copy(grp, "samplesLen", max_slices); /* TODO FIXME : This step size is in object space but the ray itself * is NOT unit length in object space so the required number of subdivisions * is tricky to get. */ DRW_shgroup_uniform_float_copy(grp, "stepLength", 8.0f / max_slices); - DRW_shgroup_state_enable(grp, DRW_STATE_CULL_FRONT); - BLI_addtail(&wpd->smoke_domains, BLI_genericNodeN(smd)); + } - /* TODO Flame rendering */ - /* TODO COBA Rendering */ + if (sds->use_coba) { + DRW_shgroup_uniform_texture(grp, "densityTexture", sds->tex_field); + DRW_shgroup_uniform_texture(grp, "transferTexture", sds->tex_coba); + } + else { + DRW_shgroup_uniform_texture(grp, "densityTexture", sds->tex); + DRW_shgroup_uniform_texture(grp, "shadowTexture", sds->tex_shadow); + DRW_shgroup_uniform_texture(grp, "flameTexture", (sds->tex_flame) ? sds->tex_flame : e_data.dummy_tex); + DRW_shgroup_uniform_texture(grp, "flameColorTexture", (sds->tex_flame) ? sds->tex_flame_coba : e_data.dummy_coba_tex); + } + DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth); + DRW_shgroup_uniform_float_copy(grp, "densityScale", 10.0f * sds->display_thickness); + DRW_shgroup_state_disable(grp, DRW_STATE_CULL_FRONT); + if (use_slice) { + DRW_shgroup_call_object_add(grp, DRW_cache_quad_get(), ob); + } + else { DRW_shgroup_call_object_add(grp, DRW_cache_cube_get(), ob); } + + BLI_addtail(&wpd->smoke_domains, BLI_genericNodeN(smd)); } void workbench_volume_smoke_textures_free(WORKBENCH_PrivateData *wpd) |