Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2020-03-02 01:50:05 +0300
committerClément Foucault <foucault.clem@gmail.com>2020-03-02 17:16:18 +0300
commit606f1d80b39a978f32aaae5a0cd22e18775dd36a (patch)
treeb95e99b2007980827cccc5ebcc92b53c81bfc858
parentf426e71e091cbd000066c46c699e2529cd97a1cd (diff)
Workbench: Refactor: Add Shadow support
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl2
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl5
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_shadow_debug_frag.glsl16
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_transparent_accum_frag.glsl2
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl10
-rw-r--r--source/blender/draw/engines/workbench/workbench_data.c55
-rw-r--r--source/blender/draw/engines/workbench/workbench_deferred.c14
-rw-r--r--source/blender/draw/engines/workbench/workbench_engine.c78
-rw-r--r--source/blender/draw/engines/workbench/workbench_materials.c27
-rw-r--r--source/blender/draw/engines/workbench/workbench_opaque.c25
-rw-r--r--source/blender/draw/engines/workbench/workbench_private.h49
-rw-r--r--source/blender/draw/engines/workbench/workbench_shader.c50
-rw-r--r--source/blender/draw/engines/workbench/workbench_shadow.c114
-rw-r--r--source/blender/draw/engines/workbench/workbench_studiolight.c9
-rw-r--r--source/blender/draw/engines/workbench/workbench_transparent.c1
-rw-r--r--source/blender/draw/intern/draw_hair.c2
16 files changed, 364 insertions, 95 deletions
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl
index 0616043aef0..cdb9823096c 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_composite_frag.glsl
@@ -38,5 +38,7 @@ void main()
fragColor.rgb = base_color;
#endif
+ fragColor.rgb *= get_shadow(N);
+
fragColor.a = 1.0;
}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl
index 83ee73b00d8..75fde40bc94 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl
@@ -9,6 +9,11 @@ struct WorldData {
vec4 viewport_size;
vec4 object_outline_color;
vec4 shadow_direction_vs;
+ float shadow_focus;
+ float shadow_shift;
+ float shadow_mul;
+ float shadow_add;
+ /* - 16 bytes alignment- */
LightData lights[4];
vec4 ambient_color;
int matcap_orientation;
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_shadow_debug_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_shadow_debug_frag.glsl
index 6b0741b6d1b..6fa76510e6e 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_shadow_debug_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_shadow_debug_frag.glsl
@@ -1,15 +1,19 @@
out vec4 fragColor;
+layout(location = 0) out vec4 materialData;
+layout(location = 1) out vec4 normalData;
+layout(location = 2) out uint objectId;
+
void main()
{
- const float intensity = 0.25;
+ const float a = 0.25;
#ifdef SHADOW_PASS
- fragColor = vec4(
- (gl_FrontFacing) ? vec3(intensity, -intensity, 0.0) : vec3(-intensity, intensity, 0.0), 1.0);
+ materialData.rgb = gl_FrontFacing ? vec3(a, -a, 0.0) : vec3(-a, a, 0.0);
#else
- fragColor = vec4((gl_FrontFacing) ? vec3(intensity, intensity, -intensity) :
- vec3(-intensity, -intensity, intensity),
- 1.0);
+ materialData.rgb = gl_FrontFacing ? vec3(a, a, -a) : vec3(-a, -a, a);
#endif
+ materialData.a = 0.0;
+ normalData = vec4(0.0);
+ objectId = 0u;
}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_transparent_accum_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_transparent_accum_frag.glsl
index e1b031e7294..7113b998fa7 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_transparent_accum_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_transparent_accum_frag.glsl
@@ -79,6 +79,8 @@ void main()
vec3 shaded_color = color;
#endif
+ shaded_color *= get_shadow(N);
+
/* Listing 4 */
float weight = calculate_transparent_weight() * alpha_interp;
transparentAccum = vec4(shaded_color * weight, alpha_interp);
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl b/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl
index e7c94c9b955..1c966a9e47c 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl
@@ -121,3 +121,13 @@ vec3 get_world_lighting(vec3 base_color, float roughness, float metallic, vec3 N
return diffuse_light + specular_light;
}
+
+uniform bool forceShadowing = false;
+
+float get_shadow(vec3 N)
+{
+ float light_factor = -dot(N, world_data.shadow_direction_vs.xyz);
+ float shadow_mix = smoothstep(world_data.shadow_shift, world_data.shadow_focus, light_factor);
+ shadow_mix *= forceShadowing ? 0.0 : world_data.shadow_mul;
+ return shadow_mix + world_data.shadow_add;
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c
index ad5eaff2392..937c6a33319 100644
--- a/source/blender/draw/engines/workbench/workbench_data.c
+++ b/source/blender/draw/engines/workbench/workbench_data.c
@@ -79,17 +79,44 @@ static WORKBENCH_ViewLayerData *workbench_view_layer_data_ensure_ex(struct ViewL
return *vldata;
}
-static void workbench_world_data_update_shadow_direction_vs(WORKBENCH_PrivateData *wpd)
+void workbench_private_data_get_light_direction(float r_light_direction[3])
{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+
+ copy_v3_v3(r_light_direction, scene->display.light_direction);
+ SWAP(float, r_light_direction[2], r_light_direction[1]);
+ r_light_direction[2] = -r_light_direction[2];
+ r_light_direction[0] = -r_light_direction[0];
+}
+
+static void workbench_shadow_world_data_update(WORKBENCH_PrivateData *wpd)
+{
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ const Scene *scene = draw_ctx->scene;
+
WORKBENCH_UBO_World *wd = &wpd->world_data;
- float light_direction[3];
float view_matrix[4][4];
DRW_view_viewmat_get(NULL, view_matrix, false);
- workbench_private_data_get_light_direction(light_direction);
+ workbench_private_data_get_light_direction(wpd->light_direction_ws);
/* Shadow direction. */
- mul_v3_mat3_m4v3(wd->shadow_direction_vs, view_matrix, light_direction);
+ mul_v3_mat3_m4v3(wd->shadow_direction_vs, view_matrix, wpd->light_direction_ws);
+
+ /* Clamp to avoid overshadowing and shading errors. */
+ float focus = clamp_f(scene->display.shadow_focus, 0.0001f, 0.99999f);
+ wd->shadow_shift = scene->display.shadow_shift;
+ wd->shadow_focus = 1.0f - focus * (1.0f - wd->shadow_shift);
+
+ if (SHADOW_ENABLED(wpd)) {
+ wd->shadow_mul = wpd->shading.shadow_intensity;
+ wd->shadow_add = 1.0f - wd->shadow_mul;
+ }
+ else {
+ wd->shadow_mul = 0.0f;
+ wd->shadow_add = 1.0f;
+ }
}
/* \} */
@@ -205,13 +232,6 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
wpd->studio_light = BKE_studiolight_find(wpd->shading.studio_light, STUDIOLIGHT_TYPE_STUDIO);
}
- float shadow_focus = scene->display.shadow_focus;
- /* Clamp to avoid overshadowing and shading errors. */
- CLAMP(shadow_focus, 0.0001f, 0.99999f);
- wpd->shadow_shift = scene->display.shadow_shift;
- wpd->shadow_focus = 1.0f - shadow_focus * (1.0f - wpd->shadow_shift);
- wpd->shadow_multiplier = 1.0 - wpd->shading.shadow_intensity;
-
WORKBENCH_UBO_World *wd = &wpd->world_data;
wd->matcap_orientation = (wpd->shading.flag & V3D_SHADING_MATCAP_FLIP_X) != 0;
@@ -227,7 +247,7 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
wd->curvature_ridge = 0.5f / max_ff(SQUARE(wpd->shading.curvature_ridge_factor), 1e-4f);
wd->curvature_valley = 0.7f / max_ff(SQUARE(wpd->shading.curvature_valley_factor), 1e-4f);
- workbench_world_data_update_shadow_direction_vs(wpd);
+ workbench_shadow_world_data_update(wpd);
workbench_viewvecs_update(wpd->world_data.viewvecs);
copy_v2_v2(wpd->world_data.viewport_size, DRW_viewport_size_get());
copy_v2_v2(wpd->world_data.viewport_size_inv, DRW_viewport_invert_size_get());
@@ -296,17 +316,6 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd)
BLI_listbase_clear(&wpd->smoke_domains);
}
-void workbench_private_data_get_light_direction(float r_light_direction[3])
-{
- const DRWContextState *draw_ctx = DRW_context_state_get();
- Scene *scene = draw_ctx->scene;
-
- copy_v3_v3(r_light_direction, scene->display.light_direction);
- SWAP(float, r_light_direction[2], r_light_direction[1]);
- r_light_direction[2] = -r_light_direction[2];
- r_light_direction[0] = -r_light_direction[0];
-}
-
void workbench_update_material_ubos(WORKBENCH_PrivateData *UNUSED(wpd))
{
const DRWContextState *draw_ctx = DRW_context_state_get();
diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c
index f1528c2213c..4bd0e663650 100644
--- a/source/blender/draw/engines/workbench/workbench_deferred.c
+++ b/source/blender/draw/engines/workbench/workbench_deferred.c
@@ -334,12 +334,6 @@ static struct GPUTexture *create_jitter_texture(int num_samples)
}
/* Functions */
-static void workbench_init_object_data(DrawData *dd)
-{
- WORKBENCH_ObjectData *data = (WORKBENCH_ObjectData *)dd;
- data->shadow_bbox_dirty = true;
-}
-
static void workbench_init_oit_framebuffer(WORKBENCH_FramebufferList *fbl,
DefaultTextureList *dtxl)
{
@@ -732,7 +726,7 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata)
/* Deferred Mix Pass */
{
workbench_private_data_get_light_direction(e_data.display.light_direction);
- studiolight_update_light(wpd, e_data.display.light_direction);
+ studiolight_update_light(wpd);
if (SHADOW_ENABLED(wpd)) {
psl->composite_pass = DRW_pass_create(
@@ -1161,11 +1155,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
}
else {
WORKBENCH_ObjectData *engine_object_data = (WORKBENCH_ObjectData *)DRW_drawdata_ensure(
- &ob->id,
- &draw_engine_workbench_solid,
- sizeof(WORKBENCH_ObjectData),
- &workbench_init_object_data,
- NULL);
+ &ob->id, &draw_engine_workbench_solid, sizeof(WORKBENCH_ObjectData), NULL, NULL);
if (studiolight_object_cast_visible_shadow(wpd, ob, engine_object_data)) {
diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c
index 06a8508c997..ac0a4e6221a 100644
--- a/source/blender/draw/engines/workbench/workbench_engine.c
+++ b/source/blender/draw/engines/workbench/workbench_engine.c
@@ -82,6 +82,7 @@ static void workbench_cache_init(void *ved)
workbench_opaque_cache_init(vedata);
workbench_transparent_cache_init(vedata);
+ workbench_shadow_cache_init(vedata);
// workbench_aa_create_pass(vedata);
// workbench_dof_create_pass(vedata);
@@ -105,14 +106,14 @@ static void workbench_cache_sculpt_populate(WORKBENCH_PrivateData *wpd, Object *
BLI_assert(wpd->shading.color_type != V3D_SHADING_TEXTURE_COLOR);
if (use_single_drawcall) {
- DRWShadingGroup *grp = workbench_material_setup(wpd, ob, 0, color_type, false);
+ DRWShadingGroup *grp = workbench_material_setup(wpd, ob, 0, color_type, NULL);
DRW_shgroup_call_sculpt(grp, ob, false, false, use_vcol);
}
else {
const int materials_len = DRW_cache_object_material_count_get(ob);
struct DRWShadingGroup **shgrps = BLI_array_alloca(shgrps, materials_len);
for (int i = 0; i < materials_len; i++) {
- shgrps[i] = workbench_material_setup(wpd, ob, i + 1, color_type, false);
+ shgrps[i] = workbench_material_setup(wpd, ob, i + 1, color_type, NULL);
}
DRW_shgroup_call_sculpt_with_materials(shgrps, ob, false);
}
@@ -132,7 +133,7 @@ static void workbench_cache_texpaint_populate(WORKBENCH_PrivateData *wpd, Object
int interp = (imapaint->interp == IMAGEPAINT_INTERP_LINEAR) ? SHD_INTERP_LINEAR :
SHD_INTERP_CLOSEST;
- DRWShadingGroup *grp = workbench_image_setup(wpd, ob, 0, ima, NULL, interp, false);
+ DRWShadingGroup *grp = workbench_image_setup(wpd, ob, 0, ima, NULL, interp);
DRW_shgroup_call(grp, geom, ob);
}
}
@@ -141,14 +142,17 @@ static void workbench_cache_texpaint_populate(WORKBENCH_PrivateData *wpd, Object
if (geoms) {
const int materials_len = DRW_cache_object_material_count_get(ob);
for (int i = 0; i < materials_len; i++) {
- DRWShadingGroup *grp = workbench_image_setup(wpd, ob, i + 1, NULL, NULL, 0, false);
+ DRWShadingGroup *grp = workbench_image_setup(wpd, ob, i + 1, NULL, NULL, 0);
DRW_shgroup_call(grp, geoms[i], ob);
}
}
}
}
-static void workbench_cache_common_populate(WORKBENCH_PrivateData *wpd, Object *ob, int color_type)
+static void workbench_cache_common_populate(WORKBENCH_PrivateData *wpd,
+ Object *ob,
+ int color_type,
+ bool *r_transp)
{
const bool use_tex = ELEM(color_type, V3D_SHADING_TEXTURE_COLOR);
const bool use_vcol = ELEM(color_type, V3D_SHADING_VERTEX_COLOR);
@@ -159,7 +163,7 @@ static void workbench_cache_common_populate(WORKBENCH_PrivateData *wpd, Object *
struct GPUBatch *geom = (use_vcol) ? DRW_cache_mesh_surface_vertpaint_get(ob) :
DRW_cache_object_surface_get(ob);
if (geom) {
- DRWShadingGroup *grp = workbench_material_setup(wpd, ob, 0, color_type, false);
+ DRWShadingGroup *grp = workbench_material_setup(wpd, ob, 0, color_type, r_transp);
DRW_shgroup_call(grp, geom, ob);
}
}
@@ -169,7 +173,7 @@ static void workbench_cache_common_populate(WORKBENCH_PrivateData *wpd, Object *
if (geoms) {
const int materials_len = DRW_cache_object_material_count_get(ob);
for (int i = 0; i < materials_len; i++) {
- DRWShadingGroup *grp = workbench_material_setup(wpd, ob, i + 1, color_type, false);
+ DRWShadingGroup *grp = workbench_material_setup(wpd, ob, i + 1, color_type, r_transp);
DRW_shgroup_call(grp, geoms[i], ob);
}
}
@@ -192,8 +196,8 @@ static void workbench_cache_hair_populate(WORKBENCH_PrivateData *wpd,
int interp = (imapaint && imapaint->interp == IMAGEPAINT_INTERP_LINEAR) ? SHD_INTERP_LINEAR :
SHD_INTERP_CLOSEST;
DRWShadingGroup *grp = (use_texpaint_mode) ?
- workbench_image_setup(wpd, ob, part->omat, ima, NULL, interp, true) :
- workbench_material_setup(wpd, ob, part->omat, color_type, true);
+ workbench_image_hair_setup(wpd, ob, part->omat, ima, NULL, interp) :
+ workbench_material_hair_setup(wpd, ob, part->omat, color_type);
DRW_shgroup_hair_create_sub(ob, psys, md, grp);
}
@@ -203,7 +207,8 @@ static void workbench_cache_hair_populate(WORKBENCH_PrivateData *wpd,
static int workbench_color_type_get(WORKBENCH_PrivateData *wpd,
Object *ob,
bool *r_sculpt_pbvh,
- bool *r_texpaint_mode)
+ bool *r_texpaint_mode,
+ bool *r_draw_shadow)
{
int color_type = wpd->shading.color_type;
const Mesh *me = (ob->type == OB_MESH) ? ob->data : NULL;
@@ -241,6 +246,20 @@ static int workbench_color_type_get(WORKBENCH_PrivateData *wpd,
}
}
+ if (r_draw_shadow) {
+ *r_draw_shadow = (ob->dtx & OB_DRAW_NO_SHADOW_CAST) == 0 && SHADOW_ENABLED(wpd);
+ /* Currently unsupported in sculpt mode. We could revert to the slow
+ * method in this case but I'm not sure if it's a good idea given that
+ * sculpted meshes are heavy to begin with. */
+ if (is_sculpt_pbvh) {
+ *r_draw_shadow = false;
+ }
+
+ if (is_active && DRW_object_use_hide_faces(ob)) {
+ *r_draw_shadow = false;
+ }
+ }
+
return color_type;
}
@@ -256,9 +275,9 @@ static void workbench_cache_populate(void *ved, Object *ob)
if (ob->type == OB_MESH && ob->modifiers.first != NULL) {
bool use_sculpt_pbvh, use_texpaint_mode;
- int color_type = workbench_color_type_get(wpd, ob, &use_sculpt_pbvh, &use_texpaint_mode);
+ int color_type = workbench_color_type_get(wpd, ob, &use_sculpt_pbvh, &use_texpaint_mode, NULL);
- for (ModifierData *md = ob->modifiers.first; md; md = md->next) {
+ LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
if (md->type != eModifierType_ParticleSystem) {
continue;
}
@@ -286,8 +305,9 @@ static void workbench_cache_populate(void *ved, Object *ob)
}
if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) {
- bool use_sculpt_pbvh, use_texpaint_mode;
- int color_type = workbench_color_type_get(wpd, ob, &use_sculpt_pbvh, &use_texpaint_mode);
+ bool use_sculpt_pbvh, use_texpaint_mode, draw_shadow, has_transp_mat = false;
+ int color_type = workbench_color_type_get(
+ wpd, ob, &use_sculpt_pbvh, &use_texpaint_mode, &draw_shadow);
if (use_sculpt_pbvh) {
workbench_cache_sculpt_populate(wpd, ob, color_type);
@@ -296,7 +316,11 @@ static void workbench_cache_populate(void *ved, Object *ob)
workbench_cache_texpaint_populate(wpd, ob);
}
else {
- workbench_cache_common_populate(wpd, ob, color_type);
+ workbench_cache_common_populate(wpd, ob, color_type, &has_transp_mat);
+ }
+
+ if (draw_shadow) {
+ workbench_shadow_cache_populate(vedata, ob, has_transp_mat);
}
}
}
@@ -372,10 +396,13 @@ static void workbench_draw_scene(void *ved)
{
GPU_framebuffer_bind(fbl->opaque_fb);
+ GPU_framebuffer_clear_stencil(fbl->opaque_fb, 0x00);
DRW_draw_pass(psl->opaque_pass);
- /* TODO(fclem) shadows */
- // DRW_draw_pass(psl->shadow_pass);
+ if (psl->shadow_pass[0]) {
+ DRW_draw_pass(psl->shadow_pass[0]);
+ DRW_draw_pass(psl->shadow_pass[1]);
+ }
{
GPU_framebuffer_bind(fbl->opaque_infront_fb);
@@ -388,9 +415,6 @@ static void workbench_draw_scene(void *ved)
GPU_framebuffer_bind(dfbl->default_fb);
DRW_draw_pass(psl->composite_pass);
- /* TODO(fclem) shadows : render shadowed areas */
- // DRW_draw_pass(psl->composite_shadow_pass);
-
/* TODO(fclem) ambient occlusion */
// GPU_framebuffer_bind(dfbl->color_only_fb);
// DRW_draw_pass(psl->ambient_occlusion_pass);
@@ -433,6 +457,18 @@ static void workbench_view_update(void *UNUSED(ved))
{
}
+static void workbench_id_update(void *UNUSED(vedata), struct ID *id)
+{
+ if (GS(id->name) == ID_OB) {
+ WORKBENCH_ObjectData *oed = (WORKBENCH_ObjectData *)DRW_drawdata_get(
+ id, &draw_engine_workbench_solid);
+ if (oed != NULL && oed->dd.recalc != 0) {
+ oed->shadow_bbox_dirty = (oed->dd.recalc & ID_RECALC_ALL) != 0;
+ oed->dd.recalc = 0;
+ }
+ }
+}
+
static const DrawEngineDataSize workbench_data_size = DRW_VIEWPORT_DATA_SIZE(WORKBENCH_Data);
DrawEngineType draw_engine_workbench = {
@@ -447,7 +483,7 @@ DrawEngineType draw_engine_workbench = {
&workbench_cache_finish,
&workbench_draw_scene,
&workbench_view_update,
- NULL,
+ &workbench_id_update,
NULL,
};
diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c
index 2aeaee646e9..60349cd567b 100644
--- a/source/blender/draw/engines/workbench/workbench_materials.c
+++ b/source/blender/draw/engines/workbench/workbench_materials.c
@@ -466,8 +466,8 @@ static bool workbench_material_chunk_select(WORKBENCH_PrivateData *wpd, uint32_t
return resource_changed;
}
-DRWShadingGroup *workbench_material_setup(
- WORKBENCH_PrivateData *wpd, Object *ob, int mat_nr, int color_type, bool hair)
+DRWShadingGroup *workbench_material_setup_ex(
+ WORKBENCH_PrivateData *wpd, Object *ob, int mat_nr, int color_type, bool hair, bool *r_transp)
{
Image *ima = NULL;
ImageUser *iuser = NULL;
@@ -484,7 +484,7 @@ DRWShadingGroup *workbench_material_setup(
switch (color_type) {
case V3D_SHADING_TEXTURE_COLOR: {
- return workbench_image_setup(wpd, ob, mat_nr, ima, iuser, interp, hair);
+ return workbench_image_setup_ex(wpd, ob, mat_nr, ima, iuser, interp, hair);
}
case V3D_SHADING_MATERIAL_COLOR: {
/* For now, we use the same ubo for material and object coloring but with different indices.
@@ -497,6 +497,10 @@ DRWShadingGroup *workbench_material_setup(
const bool transp = wpd->shading.xray_alpha < 1.0f || ma->a < 1.0f;
WORKBENCH_Prepass *prepass = &wpd->prepass[transp][infront][hair];
+ if (r_transp && transp) {
+ *r_transp = true;
+ }
+
DRWShadingGroup **grp_mat = NULL;
/* A hashmap stores material shgroups to pack all similar drawcalls together. */
if (BLI_ghash_ensure_p(prepass->material_hash, ma, (void ***)&grp_mat)) {
@@ -536,19 +540,22 @@ DRWShadingGroup *workbench_material_setup(
grp = DRW_shgroup_create_sub(grp);
DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr);
}
+ if (r_transp && transp) {
+ *r_transp = true;
+ }
return grp;
}
}
}
/* If ima is null, search appropriate image node but will fallback to purple texture otherwise. */
-DRWShadingGroup *workbench_image_setup(WORKBENCH_PrivateData *wpd,
- Object *ob,
- int mat_nr,
- Image *ima,
- ImageUser *iuser,
- int interp,
- bool hair)
+DRWShadingGroup *workbench_image_setup_ex(WORKBENCH_PrivateData *wpd,
+ Object *ob,
+ int mat_nr,
+ Image *ima,
+ ImageUser *iuser,
+ int interp,
+ bool hair)
{
GPUTexture *tex = NULL, *tex_tile_data = NULL;
diff --git a/source/blender/draw/engines/workbench/workbench_opaque.c b/source/blender/draw/engines/workbench/workbench_opaque.c
index d9c4c5a80a9..b968f257007 100644
--- a/source/blender/draw/engines/workbench/workbench_opaque.c
+++ b/source/blender/draw/engines/workbench/workbench_opaque.c
@@ -114,17 +114,18 @@ void workbench_opaque_cache_init(WORKBENCH_Data *data)
}
}
{
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_GREATER;
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_GREATER | DRW_STATE_STENCIL_EQUAL;
DRW_PASS_CREATE(psl->composite_pass, state);
sh = workbench_shader_composite_get(wpd);
grp = DRW_shgroup_create(sh, psl->composite_pass);
+ DRW_shgroup_uniform_block_persistent(grp, "world_block", wpd->world_ubo);
+ DRW_shgroup_uniform_texture_persistent(grp, "materialBuffer", wpd->material_buffer_tx);
+ DRW_shgroup_uniform_texture_persistent(grp, "normalBuffer", wpd->normal_buffer_tx);
+ DRW_shgroup_uniform_bool_copy(grp, "forceShadowing", false);
DRW_shgroup_stencil_mask(grp, 0x00);
- DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
- DRW_shgroup_uniform_texture(grp, "materialBuffer", wpd->material_buffer_tx);
- DRW_shgroup_uniform_texture(grp, "normalBuffer", wpd->normal_buffer_tx);
const bool use_spec = workbench_is_specular_highlight_enabled(wpd);
@@ -134,14 +135,24 @@ void workbench_opaque_cache_init(WORKBENCH_Data *data)
STUDIOLIGHT_MATCAP_SPECULAR_GPUTEXTURE);
struct GPUTexture *diff_tx = wpd->studio_light->matcap_diffuse.gputexture;
struct GPUTexture *spec_tx = wpd->studio_light->matcap_specular.gputexture;
- DRW_shgroup_uniform_texture(grp, "matcapDiffuseImage", diff_tx);
- DRW_shgroup_uniform_texture(grp, "matcapSpecularImage", use_spec ? spec_tx : diff_tx);
+ spec_tx = use_spec ? spec_tx : diff_tx;
+ DRW_shgroup_uniform_texture_persistent(grp, "matcapDiffuseImage", diff_tx);
+ DRW_shgroup_uniform_texture_persistent(grp, "matcapSpecularImage", spec_tx);
DRW_shgroup_uniform_bool_copy(grp, "useSpecularMatcap", use_spec);
}
else if (STUDIOLIGHT_TYPE_STUDIO_ENABLED(wpd)) {
DRW_shgroup_uniform_bool_copy(grp, "useSpecularLighting", use_spec);
}
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+
+ if (true) {
+ grp = DRW_shgroup_create_sub(grp);
+ DRW_shgroup_uniform_bool_copy(grp, "forceShadowing", true);
+ DRW_shgroup_state_disable(grp, DRW_STATE_STENCIL_EQUAL);
+ DRW_shgroup_state_enable(grp, DRW_STATE_STENCIL_NEQUAL);
+ DRW_shgroup_stencil_mask(grp, 0x00);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+ }
}
{
DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS | DRW_STATE_WRITE_STENCIL |
@@ -152,8 +163,8 @@ void workbench_opaque_cache_init(WORKBENCH_Data *data)
sh = workbench_shader_merge_infront_get(wpd);
grp = DRW_shgroup_create(sh, psl->merge_infront_pass);
- DRW_shgroup_stencil_mask(grp, 0x00);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth_in_front);
+ DRW_shgroup_stencil_mask(grp, 0x00);
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
}
}
diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h
index 90c1908100f..155deba8380 100644
--- a/source/blender/draw/engines/workbench/workbench_private.h
+++ b/source/blender/draw/engines/workbench/workbench_private.h
@@ -34,6 +34,8 @@
#include "workbench_engine.h"
+extern struct DrawEngineType draw_engine_workbench;
+
#define WORKBENCH_ENGINE "BLENDER_WORKBENCH"
/* TODO put them in workbench_shader.c */
#define MAX_COMPOSITE_SHADERS 3
@@ -42,6 +44,8 @@
#define MAX_CAVITY_SHADERS (1 << 3)
#define MAX_MATERIAL (1 << 12)
+#define DEBUG_SHADOW_VOLUME 0
+
#define TEXTURE_DRAWING_ENABLED(wpd) (wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR)
#define VERTEX_COLORS_ENABLED(wpd) (wpd->shading.color_type == V3D_SHADING_VERTEX_COLOR)
#define MATERIAL_COLORS_ENABLED(wpd) (wpd->shading.color_type == V3D_SHADING_MATERIAL_COLOR)
@@ -143,6 +147,7 @@ typedef struct WORKBENCH_PassList {
/* deferred rendering */
struct DRWPass *opaque_pass;
struct DRWPass *opaque_infront_pass;
+ struct DRWPass *shadow_pass[2];
struct DRWPass *merge_infront_pass;
struct DRWPass *prepass_pass;
struct DRWPass *prepass_hair_pass;
@@ -207,6 +212,7 @@ typedef struct WORKBENCH_UBO_World {
float viewport_size[2], viewport_size_inv[2];
float object_outline_color[4];
float shadow_direction_vs[4];
+ float shadow_focus, shadow_shift, shadow_mul, shadow_add;
WORKBENCH_UBO_Light lights[4];
float ambient_color[4];
int matcap_orientation;
@@ -299,6 +305,12 @@ typedef struct WORKBENCH_PrivateData {
int material_chunk_curr;
int material_index;
+ /* Shadow */
+ struct DRWShadingGroup *shadow_pass_grp[2];
+ struct DRWShadingGroup *shadow_fail_grp[2];
+ struct DRWShadingGroup *shadow_fail_caps_grp[2];
+ float light_direction_ws[3];
+
/* Volumes */
bool volumes_do;
ListBase smoke_domains;
@@ -493,6 +505,10 @@ void workbench_opaque_cache_init(WORKBENCH_Data *data);
void workbench_transparent_engine_init(WORKBENCH_Data *data);
void workbench_transparent_cache_init(WORKBENCH_Data *data);
+/* workbench_shadow.c */
+void workbench_shadow_cache_init(WORKBENCH_Data *data);
+void workbench_shadow_cache_populate(WORKBENCH_Data *data, Object *ob, const bool has_transp_mat);
+
/* workbench_shader.c */
GPUShader *workbench_shader_opaque_get(WORKBENCH_PrivateData *wpd, bool hair);
GPUShader *workbench_shader_opaque_image_get(WORKBENCH_PrivateData *wpd, bool hair, bool tiled);
@@ -505,6 +521,9 @@ GPUShader *workbench_shader_transparent_image_get(WORKBENCH_PrivateData *wpd,
bool tiled);
GPUShader *workbench_shader_transparent_resolve_get(WORKBENCH_PrivateData *wpd);
+GPUShader *workbench_shader_shadow_pass_get(bool manifold);
+GPUShader *workbench_shader_shadow_fail_get(bool manifold, bool cap);
+
void workbench_shader_library_ensure(void);
void workbench_shader_free(void);
@@ -609,21 +628,31 @@ void workbench_material_ubo_data(WORKBENCH_PrivateData *wpd,
WORKBENCH_UBO_Material *data,
int color_type);
-DRWShadingGroup *workbench_material_setup(
- WORKBENCH_PrivateData *wpd, Object *ob, int mat_nr, int color_type, bool hair);
-DRWShadingGroup *workbench_image_setup(WORKBENCH_PrivateData *wpd,
- Object *ob,
- int mat_nr,
- Image *ima,
- ImageUser *iuser,
- int interp,
- bool hair);
+DRWShadingGroup *workbench_material_setup_ex(
+ WORKBENCH_PrivateData *wpd, Object *ob, int mat_nr, int color_type, bool hair, bool *r_transp);
+DRWShadingGroup *workbench_image_setup_ex(WORKBENCH_PrivateData *wpd,
+ Object *ob,
+ int mat_nr,
+ Image *ima,
+ ImageUser *iuser,
+ int interp,
+ bool hair);
+
+#define workbench_material_setup(wpd, ob, mat_nr, color_type, r_transp) \
+ workbench_material_setup_ex(wpd, ob, mat_nr, color_type, false, r_transp)
+#define workbench_image_setup(wpd, ob, mat_nr, ima, iuser, interp) \
+ workbench_image_setup_ex(wpd, ob, mat_nr, ima, iuser, interp, false)
+
+#define workbench_material_hair_setup(wpd, ob, mat_nr, color_type) \
+ workbench_material_setup_ex(wpd, ob, mat_nr, color_type, true, 0)
+#define workbench_image_hair_setup(wpd, ob, mat_nr, ima, iuser, interp) \
+ workbench_image_setup_ex(wpd, ob, mat_nr, ima, iuser, interp, true)
/* workbench_studiolight.c */
void studiolight_update_world(WORKBENCH_PrivateData *wpd,
StudioLight *sl,
WORKBENCH_UBO_World *wd);
-void studiolight_update_light(WORKBENCH_PrivateData *wpd, const float light_direction[3]);
+void studiolight_update_light(WORKBENCH_PrivateData *wpd);
bool studiolight_object_cast_visible_shadow(WORKBENCH_PrivateData *wpd,
Object *ob,
WORKBENCH_ObjectData *oed);
diff --git a/source/blender/draw/engines/workbench/workbench_shader.c b/source/blender/draw/engines/workbench/workbench_shader.c
index bc769001f8c..3470d42608e 100644
--- a/source/blender/draw/engines/workbench/workbench_shader.c
+++ b/source/blender/draw/engines/workbench/workbench_shader.c
@@ -33,6 +33,7 @@ extern char datatoc_common_view_lib_glsl[];
extern char datatoc_workbench_prepass_vert_glsl[];
extern char datatoc_workbench_prepass_hair_vert_glsl[];
extern char datatoc_workbench_prepass_frag_glsl[];
+
// extern char datatoc_workbench_cavity_frag_glsl[];
// extern char datatoc_workbench_forward_composite_frag_glsl[];
// extern char datatoc_workbench_deferred_composite_frag_glsl[];
@@ -77,6 +78,9 @@ static struct {
struct GPUShader *oit_resolve_sh;
struct GPUShader *merge_infront_sh;
+ struct GPUShader *shadow_depth_pass_sh[2];
+ struct GPUShader *shadow_depth_fail_sh[2][2];
+
struct DRWShaderLibrary *lib;
} e_data = {{{{NULL}}}};
@@ -241,6 +245,44 @@ GPUShader *workbench_shader_transparent_resolve_get(WORKBENCH_PrivateData *wpd)
return e_data.oit_resolve_sh;
}
+static GPUShader *workbench_shader_shadow_pass_get_ex(bool depth_pass, bool manifold, bool cap)
+{
+ struct GPUShader **shader = (depth_pass) ? &e_data.shadow_depth_pass_sh[manifold] :
+ &e_data.shadow_depth_fail_sh[manifold][cap];
+
+ if (*shader == NULL) {
+#if DEBUG_SHADOW_VOLUME
+ const char *shadow_frag = datatoc_workbench_shadow_debug_frag_glsl;
+#else
+ const char *shadow_frag = datatoc_gpu_shader_depth_only_frag_glsl;
+#endif
+
+ *shader = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){datatoc_common_view_lib_glsl,
+ datatoc_workbench_shadow_vert_glsl,
+ NULL},
+ .geom = (const char *[]){(cap) ? datatoc_workbench_shadow_caps_geom_glsl :
+ datatoc_workbench_shadow_geom_glsl,
+ NULL},
+ .frag = (const char *[]){shadow_frag, NULL},
+ .defs = (const char *[]){(depth_pass) ? "#define SHADOW_PASS\n" : "#define SHADOW_FAIL\n",
+ (manifold) ? "" : "#define DOUBLE_MANIFOLD\n",
+ NULL},
+ });
+ }
+ return *shader;
+}
+
+GPUShader *workbench_shader_shadow_pass_get(bool manifold)
+{
+ return workbench_shader_shadow_pass_get_ex(true, manifold, false);
+}
+
+GPUShader *workbench_shader_shadow_fail_get(bool manifold, bool cap)
+{
+ return workbench_shader_shadow_pass_get_ex(false, manifold, cap);
+}
+
void workbench_shader_free(void)
{
for (int j = 0; j < sizeof(e_data.opaque_prepass_sh_cache) / sizeof(void *); j++) {
@@ -255,6 +297,14 @@ void workbench_shader_free(void)
struct GPUShader **sh_array = &e_data.opaque_composite_sh[0];
DRW_SHADER_FREE_SAFE(sh_array[j]);
}
+ for (int j = 0; j < sizeof(e_data.shadow_depth_pass_sh) / sizeof(void *); j++) {
+ struct GPUShader **sh_array = &e_data.shadow_depth_pass_sh[0];
+ DRW_SHADER_FREE_SAFE(sh_array[j]);
+ }
+ for (int j = 0; j < sizeof(e_data.shadow_depth_fail_sh) / sizeof(void *); j++) {
+ struct GPUShader **sh_array = &e_data.shadow_depth_fail_sh[0][0];
+ DRW_SHADER_FREE_SAFE(sh_array[j]);
+ }
DRW_SHADER_FREE_SAFE(e_data.oit_resolve_sh);
DRW_SHADER_FREE_SAFE(e_data.merge_infront_sh);
diff --git a/source/blender/draw/engines/workbench/workbench_shadow.c b/source/blender/draw/engines/workbench/workbench_shadow.c
index 5be863e387d..635206cd38f 100644
--- a/source/blender/draw/engines/workbench/workbench_shadow.c
+++ b/source/blender/draw/engines/workbench/workbench_shadow.c
@@ -22,4 +22,116 @@
#include "DRW_render.h"
-#include "workbench_engine.h" \ No newline at end of file
+#include "workbench_engine.h"
+#include "workbench_private.h"
+
+void workbench_shadow_cache_init(WORKBENCH_Data *data)
+{
+ WORKBENCH_PassList *psl = data->psl;
+ WORKBENCH_PrivateData *wpd = data->stl->wpd;
+ struct GPUShader *sh;
+ DRWShadingGroup *grp;
+
+ studiolight_update_light(wpd);
+
+ if (SHADOW_ENABLED(wpd)) {
+#if DEBUG_SHADOW_VOLUME
+ DRWState depth_pass_state = DRW_STATE_DEPTH_LESS;
+ DRWState depth_fail_state = DRW_STATE_DEPTH_GREATER_EQUAL;
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ADD_FULL;
+#else
+ DRWState depth_pass_state = DRW_STATE_WRITE_STENCIL_SHADOW_PASS;
+ DRWState depth_fail_state = DRW_STATE_WRITE_STENCIL_SHADOW_FAIL;
+ DRWState state = DRW_STATE_DEPTH_LESS | DRW_STATE_STENCIL_ALWAYS;
+#endif
+
+ /* TODO(fclem) Merge into one pass with subpasses. */
+ DRW_PASS_CREATE(psl->shadow_pass[0], state | depth_pass_state);
+ DRW_PASS_CREATE(psl->shadow_pass[1], state | depth_fail_state);
+
+ /* Stencil Shadow passes. */
+ for (int manifold = 0; manifold < 2; manifold++) {
+ sh = workbench_shader_shadow_pass_get(manifold);
+ wpd->shadow_pass_grp[manifold] = grp = DRW_shgroup_create(sh, psl->shadow_pass[0]);
+ DRW_shgroup_stencil_mask(grp, 0xFF); /* Needed once to set the stencil state for the pass. */
+
+ sh = workbench_shader_shadow_fail_get(manifold, false);
+ wpd->shadow_fail_grp[manifold] = grp = DRW_shgroup_create(sh, psl->shadow_pass[1]);
+ DRW_shgroup_stencil_mask(grp, 0xFF); /* Needed once to set the stencil state for the pass. */
+
+ sh = workbench_shader_shadow_fail_get(manifold, true);
+ wpd->shadow_fail_caps_grp[manifold] = grp = DRW_shgroup_create(sh, psl->shadow_pass[1]);
+ }
+ }
+ else {
+ psl->shadow_pass[0] = NULL;
+ psl->shadow_pass[1] = NULL;
+ }
+}
+
+static void workbench_init_object_data(DrawData *dd)
+{
+ WORKBENCH_ObjectData *data = (WORKBENCH_ObjectData *)dd;
+ data->shadow_bbox_dirty = true;
+}
+
+void workbench_shadow_cache_populate(WORKBENCH_Data *data, Object *ob, const bool has_transp_mat)
+{
+ WORKBENCH_PrivateData *wpd = data->stl->wpd;
+
+ bool is_manifold;
+ struct GPUBatch *geom_shadow = DRW_cache_object_edge_detection_get(ob, &is_manifold);
+ if (geom_shadow == NULL) {
+ return;
+ }
+
+ WORKBENCH_ObjectData *engine_object_data = (WORKBENCH_ObjectData *)DRW_drawdata_ensure(
+ &ob->id,
+ &draw_engine_workbench,
+ sizeof(WORKBENCH_ObjectData),
+ &workbench_init_object_data,
+ NULL);
+
+ if (studiolight_object_cast_visible_shadow(wpd, ob, engine_object_data)) {
+ mul_v3_mat3_m4v3(engine_object_data->shadow_dir, ob->imat, wpd->light_direction_ws);
+
+ DRWShadingGroup *grp;
+ bool use_shadow_pass_technique = !studiolight_camera_in_object_shadow(
+ wpd, ob, engine_object_data);
+
+ /* Shadow pass technique needs object to be have all its surface opaque. */
+ if (has_transp_mat) {
+ use_shadow_pass_technique = false;
+ }
+
+ if (use_shadow_pass_technique) {
+ grp = DRW_shgroup_create_sub(wpd->shadow_pass_grp[is_manifold]);
+ DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1);
+ DRW_shgroup_uniform_float_copy(grp, "lightDistance", 1e5f);
+ DRW_shgroup_call_no_cull(grp, geom_shadow, ob);
+#if DEBUG_SHADOW_VOLUME
+ DRW_debug_bbox(&engine_object_data->shadow_bbox, (float[4]){1.0f, 0.0f, 0.0f, 1.0f});
+#endif
+ }
+ else {
+ float extrude_distance = studiolight_object_shadow_distance(wpd, ob, engine_object_data);
+
+ /* TODO(fclem): only use caps if they are in the view frustum. */
+ const bool need_caps = true;
+ if (need_caps) {
+ grp = DRW_shgroup_create_sub(wpd->shadow_fail_caps_grp[is_manifold]);
+ DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1);
+ DRW_shgroup_uniform_float_copy(grp, "lightDistance", extrude_distance);
+ DRW_shgroup_call_no_cull(grp, DRW_cache_object_surface_get(ob), ob);
+ }
+
+ grp = DRW_shgroup_create_sub(wpd->shadow_fail_grp[is_manifold]);
+ DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1);
+ DRW_shgroup_uniform_float_copy(grp, "lightDistance", extrude_distance);
+ DRW_shgroup_call_no_cull(grp, geom_shadow, ob);
+#if DEBUG_SHADOW_VOLUME
+ DRW_debug_bbox(&engine_object_data->shadow_bbox, (float[4]){0.0f, 1.0f, 0.0f, 1.0f});
+#endif
+ }
+ }
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/workbench/workbench_studiolight.c b/source/blender/draw/engines/workbench/workbench_studiolight.c
index 4eee0ce3cce..e9dd6c63feb 100644
--- a/source/blender/draw/engines/workbench/workbench_studiolight.c
+++ b/source/blender/draw/engines/workbench/workbench_studiolight.c
@@ -94,23 +94,24 @@ static void compute_parallel_lines_nor_and_dist(const float v1[2],
}
}
-void studiolight_update_light(WORKBENCH_PrivateData *wpd, const float light_direction[3])
+void studiolight_update_light(WORKBENCH_PrivateData *wpd)
{
- wpd->shadow_changed = !compare_v3v3(wpd->cached_shadow_direction, light_direction, 1e-5f);
+ wpd->shadow_changed = !compare_v3v3(
+ wpd->cached_shadow_direction, wpd->light_direction_ws, 1e-5f);
if (wpd->shadow_changed) {
float up[3] = {0.0f, 0.0f, 1.0f};
unit_m4(wpd->shadow_mat);
/* TODO fix singularity. */
- copy_v3_v3(wpd->shadow_mat[2], light_direction);
+ copy_v3_v3(wpd->shadow_mat[2], wpd->light_direction_ws);
cross_v3_v3v3(wpd->shadow_mat[0], wpd->shadow_mat[2], up);
normalize_v3(wpd->shadow_mat[0]);
cross_v3_v3v3(wpd->shadow_mat[1], wpd->shadow_mat[2], wpd->shadow_mat[0]);
invert_m4_m4(wpd->shadow_inv, wpd->shadow_mat);
- copy_v3_v3(wpd->cached_shadow_direction, light_direction);
+ copy_v3_v3(wpd->cached_shadow_direction, wpd->light_direction_ws);
}
float planes[6][4];
diff --git a/source/blender/draw/engines/workbench/workbench_transparent.c b/source/blender/draw/engines/workbench/workbench_transparent.c
index 297d07c03c6..2efa08683c3 100644
--- a/source/blender/draw/engines/workbench/workbench_transparent.c
+++ b/source/blender/draw/engines/workbench/workbench_transparent.c
@@ -56,6 +56,7 @@ static void workbench_transparent_lighting_uniforms(WORKBENCH_PrivateData *wpd,
{
const bool use_spec = workbench_is_specular_highlight_enabled(wpd);
DRW_shgroup_uniform_block_persistent(grp, "world_block", wpd->world_ubo);
+ DRW_shgroup_uniform_bool_copy(grp, "forceShadowing", false);
if (STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) {
BKE_studiolight_ensure_flag(wpd->studio_light,
diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c
index fa03c28b470..7b0fa3ce1ec 100644
--- a/source/blender/draw/intern/draw_hair.c
+++ b/source/blender/draw/intern/draw_hair.c
@@ -128,7 +128,7 @@ static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object,
object, psys, md, &hair_cache, subdiv, thickness_res);
DRWShadingGroup *shgrp;
- if (shgrp) {
+ if (shgrp_parent) {
shgrp = DRW_shgroup_create_sub(shgrp_parent);
}
else if (gpu_mat) {