Workbench: Shadows: Fix cap being clipped by far plane.
This was the last remaining problem with shadow volumes (that I know of). Only extrude until we hit the far plane.
This commit is contained in:
parent
349d416949
commit
101c277e3d
Notes:
blender-bot
2023-02-14 06:00:50 +01:00
Referenced by commit 17e9870221
, DRW: Fix crashes with instanced data
Referenced by issue #54931, Workbench: Performance Shadows
|
@ -3,6 +3,7 @@
|
|||
uniform mat4 ModelViewProjectionMatrix;
|
||||
|
||||
uniform vec3 lightDirection = vec3(0.57, 0.57, -0.57);
|
||||
uniform float lightDistance = 1e4;
|
||||
|
||||
in vec3 pos;
|
||||
|
||||
|
@ -16,5 +17,5 @@ void main()
|
|||
{
|
||||
vData.pos = pos;
|
||||
vData.frontPosition = ModelViewProjectionMatrix * vec4(pos, 1.0);
|
||||
vData.backPosition = ModelViewProjectionMatrix * vec4(pos + lightDirection * INFINITE, 1.0);
|
||||
vData.backPosition = ModelViewProjectionMatrix * vec4(pos + lightDirection * lightDistance, 1.0);
|
||||
}
|
||||
|
|
|
@ -634,12 +634,15 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
|
|||
grp = DRW_shgroup_create(e_data.shadow_pass_sh, psl->shadow_depth_pass_pass);
|
||||
}
|
||||
DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1);
|
||||
DRW_shgroup_uniform_float_copy(grp, "lightDistance", 1e5f);
|
||||
DRW_shgroup_call_add(grp, geom_shadow, ob->obmat);
|
||||
#ifdef 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) {
|
||||
|
@ -650,6 +653,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
|
|||
grp = DRW_shgroup_create(e_data.shadow_caps_sh, psl->shadow_depth_fail_caps_pass);
|
||||
}
|
||||
DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1);
|
||||
DRW_shgroup_uniform_float_copy(grp, "lightDistance", extrude_distance);
|
||||
DRW_shgroup_call_add(grp, DRW_cache_object_surface_get(ob), ob->obmat);
|
||||
}
|
||||
|
||||
|
@ -660,6 +664,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
|
|||
grp = DRW_shgroup_create(e_data.shadow_fail_sh, psl->shadow_depth_fail_pass);
|
||||
}
|
||||
DRW_shgroup_uniform_vec3(grp, "lightDirection", engine_object_data->shadow_dir, 1);
|
||||
DRW_shgroup_uniform_float_copy(grp, "lightDistance", extrude_distance);
|
||||
DRW_shgroup_call_add(grp, geom_shadow, ob->obmat);
|
||||
#ifdef DEBUG_SHADOW_VOLUME
|
||||
DRW_debug_bbox(&engine_object_data->shadow_bbox, (float[4]){0.0f, 1.0f, 0.0f, 1.0f});
|
||||
|
|
|
@ -156,6 +156,7 @@ typedef struct WORKBENCH_PrivateData {
|
|||
float cached_shadow_direction[3];
|
||||
float shadow_mat[4][4];
|
||||
float shadow_inv[4][4];
|
||||
float shadow_far_plane[4]; /* Far plane of the view frustum. */
|
||||
float shadow_near_corners[4][3]; /* Near plane corners in shadow space. */
|
||||
float shadow_near_min[3]; /* min and max of shadow_near_corners. allow fast test */
|
||||
float shadow_near_max[3];
|
||||
|
@ -186,7 +187,7 @@ typedef struct WORKBENCH_ObjectData {
|
|||
/* Accumulated recalc flags, which corresponds to ID->recalc flags. */
|
||||
int recalc;
|
||||
/* Shadow direction in local object space. */
|
||||
float shadow_dir[3];
|
||||
float shadow_dir[3], shadow_depth;
|
||||
float shadow_min[3], shadow_max[3]; /* Min, max in shadow space */
|
||||
BoundBox shadow_bbox;
|
||||
bool shadow_bbox_dirty;
|
||||
|
@ -232,6 +233,7 @@ void workbench_material_set_normal_world_matrix(
|
|||
void studiolight_update_world(StudioLight *sl, WORKBENCH_UBO_World *wd);
|
||||
void studiolight_update_light(WORKBENCH_PrivateData *wpd, const float light_direction[3]);
|
||||
bool studiolight_object_cast_visible_shadow(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed);
|
||||
float studiolight_object_shadow_distance(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed);
|
||||
bool studiolight_camera_in_object_shadow(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed);
|
||||
|
||||
/* workbench_data.c */
|
||||
|
|
|
@ -76,9 +76,13 @@ void studiolight_update_light(WORKBENCH_PrivateData *wpd, const float light_dire
|
|||
invert_m4_m4(wpd->shadow_inv, wpd->shadow_mat);
|
||||
|
||||
copy_v3_v3(wpd->cached_shadow_direction, light_direction);
|
||||
|
||||
}
|
||||
|
||||
float planes[6][4];
|
||||
DRW_culling_frustum_planes_get(planes);
|
||||
/* we only need the far plane. */
|
||||
copy_v4_v4(wpd->shadow_far_plane, planes[2]);
|
||||
|
||||
BoundBox frustum_corners;
|
||||
DRW_culling_frustum_corners_get(&frustum_corners);
|
||||
|
||||
|
@ -112,8 +116,9 @@ static BoundBox *studiolight_object_shadow_bbox_get(WORKBENCH_PrivateData *wpd,
|
|||
mul_v3_m4v3(corner, tmp_mat, bbox->vec[i]);
|
||||
minmax_v3v3_v3(oed->shadow_min, oed->shadow_max, corner);
|
||||
}
|
||||
oed->shadow_depth = oed->shadow_max[2] - oed->shadow_min[2];
|
||||
/* Extend towards infinity. */
|
||||
oed->shadow_max[2] += 1e4;
|
||||
oed->shadow_max[2] += 1e4f;
|
||||
|
||||
/* Get extended AABB in world space. */
|
||||
BKE_boundbox_init_from_minmax(&oed->shadow_bbox, oed->shadow_min, oed->shadow_max);
|
||||
|
@ -131,6 +136,30 @@ bool studiolight_object_cast_visible_shadow(WORKBENCH_PrivateData *wpd, Object *
|
|||
return DRW_culling_box_test(shadow_bbox);
|
||||
}
|
||||
|
||||
float studiolight_object_shadow_distance(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed)
|
||||
{
|
||||
BoundBox *shadow_bbox = studiolight_object_shadow_bbox_get(wpd, ob, oed);
|
||||
|
||||
int corners[4] = {0, 3, 4, 7};
|
||||
float dist = 1e4f, dist_isect;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (isect_ray_plane_v3(shadow_bbox->vec[corners[i]],
|
||||
wpd->cached_shadow_direction,
|
||||
wpd->shadow_far_plane,
|
||||
&dist_isect, true))
|
||||
{
|
||||
if (dist_isect < dist) {
|
||||
dist = dist_isect;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* All rays are parallels. If one fails, the other will too. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
return max_ii(dist - oed->shadow_depth, 0);
|
||||
}
|
||||
|
||||
bool studiolight_camera_in_object_shadow(WORKBENCH_PrivateData *wpd, Object *ob, WORKBENCH_ObjectData *oed)
|
||||
{
|
||||
/* Just to be sure the min, max are updated. */
|
||||
|
|
|
@ -506,6 +506,7 @@ bool DRW_culling_box_test(BoundBox *bbox);
|
|||
bool DRW_culling_plane_test(float plane[4]);
|
||||
|
||||
void DRW_culling_frustum_corners_get(BoundBox *corners);
|
||||
void DRW_culling_frustum_planes_get(float planes[6][4]);
|
||||
|
||||
/* Selection */
|
||||
void DRW_select_load_id(uint id);
|
||||
|
|
|
@ -516,12 +516,12 @@ static void draw_clipping_setup_from_view(void)
|
|||
for (int p = 0; p < 6; p++) {
|
||||
int q, r;
|
||||
switch (p) {
|
||||
case 0: q = 1; r = 2; break;
|
||||
case 1: q = 0; r = 5; break;
|
||||
case 2: q = 1; r = 5; break;
|
||||
case 3: q = 2; r = 6; break;
|
||||
case 4: q = 0; r = 3; break;
|
||||
default: q = 4; r = 7; break;
|
||||
case 0: q = 1; r = 2; break; /* -X */
|
||||
case 1: q = 0; r = 5; break; /* -Y */
|
||||
case 2: q = 1; r = 5; break; /* +Z (far) */
|
||||
case 3: q = 2; r = 6; break; /* +Y */
|
||||
case 4: q = 0; r = 3; break; /* -Z (near) */
|
||||
default: q = 4; r = 7; break; /* +X */
|
||||
}
|
||||
if (DST.frontface == GL_CW) {
|
||||
SWAP(int, q, r);
|
||||
|
@ -713,6 +713,13 @@ void DRW_culling_frustum_corners_get(BoundBox *corners)
|
|||
memcpy(corners, &DST.clipping.frustum_corners, sizeof(BoundBox));
|
||||
}
|
||||
|
||||
/* See draw_clipping_setup_from_view() for the plane order. */
|
||||
void DRW_culling_frustum_planes_get(float planes[6][4])
|
||||
{
|
||||
draw_clipping_setup_from_view();
|
||||
memcpy(planes, &DST.clipping.frustum_planes, sizeof(DST.clipping.frustum_planes));
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
Loading…
Reference in New Issue