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>2018-10-28 23:41:40 +0300
committerClément Foucault <foucault.clem@gmail.com>2018-10-28 23:48:22 +0300
commitb8331b79e63cfd80b5a18460e3988fe17fb01fb8 (patch)
treeeb38a4ed54466f4fce5fa6148c35e410f77585e9
parent2c545c0409a9bd44e815dbbd4eb7038797e65b23 (diff)
Eevee: Implement jittered soft shadowmap
This new option is located in the shadows options in the render settings. This approach is simple and just randomize the shadow map position (not the lamp itself) and just let the temporal supersampling do the average of all the shadowing. The downside is that is needs quite a large number of samples to give smooth results and individual sample position can remain visible. Enabling this option will make the viewport refresh all shadow maps every redraw so it has a serious performance impact. This approach is not physicaly based at all and will not match cycles. ---- The sampling for point lamps (spheres) is not
-rw-r--r--release/scripts/startup/bl_ui/properties_render.py1
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c4
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightcache.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c4
-rw-r--r--source/blender/draw/engines/eevee/eevee_lights.c173
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h8
-rw-r--r--source/blender/draw/engines/eevee/eevee_render.c5
-rw-r--r--source/blender/makesdna/DNA_scene_types.h1
-rw-r--r--source/blender/makesrna/intern/rna_scene.c6
9 files changed, 174 insertions, 30 deletions
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index fbc19a4c83e..d64570b07ca 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -748,6 +748,7 @@ class RENDER_PT_eevee_shadows(RenderButtonsPanel, Panel):
col.prop(props, "shadow_cube_size", text="Cube Size")
col.prop(props, "shadow_cascade_size", text="Cascade Size")
col.prop(props, "use_shadow_high_bitdepth")
+ col.prop(props, "use_soft_shadows")
class RENDER_PT_eevee_sampling(RenderButtonsPanel, Panel):
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index fdd908dbc44..1d173e6d3fc 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -168,7 +168,7 @@ static void eevee_cache_finish(void *vedata)
EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
EEVEE_materials_cache_finish(vedata);
- EEVEE_lights_cache_finish(sldata);
+ EEVEE_lights_cache_finish(sldata, vedata);
EEVEE_lightprobes_cache_finish(sldata, vedata);
}
@@ -249,7 +249,7 @@ static void eevee_draw_background(void *vedata)
/* Refresh shadows */
DRW_stats_group_start("Shadows");
- EEVEE_draw_shadows(sldata, psl);
+ EEVEE_draw_shadows(sldata, vedata);
DRW_stats_group_end();
GPU_framebuffer_bind(fbl->main_fb);
diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c
index 425749b0b52..e0616ae9dfe 100644
--- a/source/blender/draw/engines/eevee/eevee_lightcache.c
+++ b/source/blender/draw/engines/eevee/eevee_lightcache.c
@@ -709,7 +709,7 @@ static void eevee_lightbake_cache_create(EEVEE_Data *vedata, EEVEE_LightBake *lb
DRW_render_object_iter(vedata, NULL, lbake->depsgraph, EEVEE_render_cache);
EEVEE_materials_cache_finish(vedata);
- EEVEE_lights_cache_finish(sldata);
+ EEVEE_lights_cache_finish(sldata, vedata);
EEVEE_lightprobes_cache_finish(sldata, vedata);
txl->color = NULL;
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index 3d236a5ddd9..d1e798098bb 100644
--- a/source/blender/draw/engines/eevee/eevee_lightprobes.c
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -972,7 +972,7 @@ static void lightbake_render_scene_face(int face, EEVEE_BakeRenderData *user_dat
struct GPUFrameBuffer **face_fb = user_data->face_fb;
/* Be sure that cascaded shadow maps are updated. */
- EEVEE_draw_shadows(sldata, psl);
+ EEVEE_draw_shadows(sldata, user_data->vedata);
GPU_framebuffer_bind(face_fb[face]);
GPU_framebuffer_clear_depth(face_fb[face], 1.0f);
@@ -1028,7 +1028,7 @@ static void lightbake_render_scene_reflected(int layer, EEVEE_BakeRenderData *us
DRW_stats_group_start("Planar Reflection");
/* Be sure that cascaded shadow maps are updated. */
- EEVEE_draw_shadows(sldata, psl);
+ EEVEE_draw_shadows(sldata, vedata);
/* Since we are rendering with an inverted view matrix, we need
* to invert the facing for backface culling to be the same. */
DRW_state_invert_facing();
diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c
index 7319572d7eb..44bc4653037 100644
--- a/source/blender/draw/engines/eevee/eevee_lights.c
+++ b/source/blender/draw/engines/eevee/eevee_lights.c
@@ -26,6 +26,7 @@
#include "DRW_render.h"
#include "BLI_dynstr.h"
+#include "BLI_rand.h"
#include "BLI_rect.h"
#include "BKE_object.h"
@@ -38,6 +39,7 @@
#define SHADOW_CASTER_ALLOC_CHUNK 16
// #define DEBUG_CSM
+// #define DEBUG_SHADOW_DISTRIBUTION
static struct {
struct GPUShader *shadow_sh;
@@ -138,6 +140,7 @@ void EEVEE_lights_init(EEVEE_ViewLayerData *sldata)
int sh_cube_size = scene_eval->eevee.shadow_cube_size;
int sh_cascade_size = scene_eval->eevee.shadow_cascade_size;
const bool sh_high_bitdepth = (scene_eval->eevee.flag & SCE_EEVEE_SHADOW_HIGH_BITDEPTH) != 0;
+ sldata->lamps->soft_shadows = (scene_eval->eevee.flag & SCE_EEVEE_SHADOW_SOFT) != 0;
EEVEE_LampsInfo *linfo = sldata->lamps;
if ((linfo->shadow_cube_size != sh_cube_size) ||
@@ -518,7 +521,7 @@ void EEVEE_lights_cache_shcaster_object_add(EEVEE_ViewLayerData *sldata, Object
oedata->need_update = false;
}
-void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata)
+void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_LampsInfo *linfo = sldata->lamps;
GPUTextureFormat shadow_pool_format = GPU_R32F;
@@ -587,7 +590,7 @@ void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata)
});
/* Update Lamps UBOs. */
- EEVEE_lights_update(sldata);
+ EEVEE_lights_update(sldata, vedata);
}
/* Update buffer with lamp data */
@@ -670,7 +673,108 @@ static void eevee_light_setup(Object *ob, EEVEE_Light *evli)
evli->shadowid = -1.0f;
}
-static void eevee_shadow_cube_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led)
+/**
+ * Special ball distribution:
+ * Point are distributed in a way that when they are orthogonaly
+ * projected into any plane, the resulting distribution is (close to)
+ * a uniform disc distribution.
+ **/
+static void sample_ball(int sample_ofs, float radius, float rsample[3])
+{
+ double ht_point[3];
+ double ht_offset[3] = {0.0, 0.0, 0.0};
+ uint ht_primes[3] = {2, 3, 7};
+
+ BLI_halton_3D(ht_primes, ht_offset, sample_ofs, ht_point);
+
+ float omega = ht_point[1] * 2.0f * M_PI;
+
+ rsample[2] = ht_point[0] * 2.0f - 1.0f; /* cos theta */
+
+ float r = sqrtf(fmaxf(0.0f, 1.0f - rsample[2]*rsample[2])); /* sin theta */
+
+ rsample[0] = r * cosf(omega);
+ rsample[1] = r * sinf(omega);
+
+ radius *= sqrt(sqrt(ht_point[2]));
+ mul_v3_fl(rsample, radius);
+}
+
+static void sample_rectangle(
+ int sample_ofs, float x_axis[3], float y_axis[3], float size_x, float size_y,
+ float rsample[3])
+{
+ double ht_point[2];
+ double ht_offset[2] = {0.0, 0.0};
+ uint ht_primes[2] = {2, 3};
+
+ BLI_halton_2D(ht_primes, ht_offset, sample_ofs, ht_point);
+
+ /* Change ditribution center to be 0,0 */
+ ht_point[0] = (ht_point[0] > 0.5f) ? ht_point[0] - 1.0f : ht_point[0];
+ ht_point[1] = (ht_point[1] > 0.5f) ? ht_point[1] - 1.0f : ht_point[1];
+
+ zero_v3(rsample);
+ madd_v3_v3fl(rsample, x_axis, (ht_point[0] * 2.0f) * size_x);
+ madd_v3_v3fl(rsample, y_axis, (ht_point[1] * 2.0f) * size_y);
+}
+
+static void sample_ellipse(
+ int sample_ofs, float x_axis[3], float y_axis[3], float size_x, float size_y,
+ float rsample[3])
+{
+ double ht_point[2];
+ double ht_offset[2] = {0.0, 0.0};
+ uint ht_primes[2] = {2, 3};
+
+ BLI_halton_2D(ht_primes, ht_offset, sample_ofs, ht_point);
+
+ /* Uniform disc sampling. */
+ float omega = ht_point[1] * 2.0f * M_PI;
+ float r = sqrtf(ht_point[0]);
+ ht_point[0] = r * cosf(omega) * size_x;
+ ht_point[1] = r * sinf(omega) * size_y;
+
+ zero_v3(rsample);
+ madd_v3_v3fl(rsample, x_axis, ht_point[0]);
+ madd_v3_v3fl(rsample, y_axis, ht_point[1]);
+}
+
+
+static void shadow_cube_random_position_set(
+ EEVEE_Light *evli, Lamp *la,
+ int sample_ofs,
+ float ws_sample_pos[3])
+{
+ float jitter[3];
+
+#ifndef DEBUG_SHADOW_DISTRIBUTION
+ int i = sample_ofs;
+#else
+ for (int i = 1; i <= sample_ofs; ++i) {
+#endif
+ switch (la->type) {
+ case LA_AREA:
+ if (ELEM(la->area_shape, LA_AREA_RECT, LA_AREA_SQUARE)) {
+ sample_rectangle(i, evli->rightvec, evli->upvec, evli->sizex, evli->sizey, jitter);
+ }
+ else {
+ sample_ellipse(i, evli->rightvec, evli->upvec, evli->sizex, evli->sizey, jitter);
+ }
+ break;
+ default:
+ sample_ball(i, evli->radius, jitter);
+ }
+#ifdef DEBUG_SHADOW_DISTRIBUTION
+ float p[3];
+ add_v3_v3v3(p, jitter, ws_sample_pos);
+ DRW_debug_sphere(p, 0.01f, (float[4]){1.0f, (sample_ofs == i) ? 1.0f : 0.0f, 0.0f, 1.0f});
+ }
+#endif
+ add_v3_v3(ws_sample_pos, jitter);
+}
+
+static void eevee_shadow_cube_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led, int sample_ofs)
{
EEVEE_ShadowCubeData *sh_data = &led->data.scd;
EEVEE_Light *evli = linfo->light_data + sh_data->light_id;
@@ -678,11 +782,10 @@ static void eevee_shadow_cube_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_La
EEVEE_ShadowCube *cube_data = linfo->shadow_cube_data + sh_data->cube_id;
Lamp *la = (Lamp *)ob->data;
- int sh_nbr = 1; /* TODO: MSM */
+ copy_v3_v3(cube_data->position, ob->obmat[3]);
- for (int i = 0; i < sh_nbr; ++i) {
- /* TODO : choose MSM sample point here. */
- copy_v3_v3(cube_data->position, ob->obmat[3]);
+ if (linfo->soft_shadows) {
+ shadow_cube_random_position_set(evli, la, sample_ofs, cube_data->position);
}
ubo_data->bias = 0.05f * la->bias;
@@ -693,7 +796,6 @@ static void eevee_shadow_cube_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_La
evli->shadowid = (float)(sh_data->shadow_id);
ubo_data->shadow_start = (float)(sh_data->layer_id);
ubo_data->data_start = (float)(sh_data->cube_id);
- ubo_data->multi_shadow_count = (float)(sh_nbr);
ubo_data->shadow_blur = la->soft * 0.02f; /* Used by translucence shadowmap blur */
ubo_data->contact_dist = (la->mode & LA_SHAD_CONTACT) ? la->contact_dist : 0.0f;
@@ -702,6 +804,27 @@ static void eevee_shadow_cube_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_La
ubo_data->contact_thickness = la->contact_thickness;
}
+static void shadow_cascade_random_matrix_set(float mat[4][4], float radius, int sample_ofs)
+{
+ float jitter[3];
+
+#ifndef DEBUG_SHADOW_DISTRIBUTION
+ int i = sample_ofs;
+#else
+ for (int i = 1; i <= sample_ofs; ++i) {
+#endif
+ sample_ellipse(i, mat[0], mat[1], radius, radius, jitter);
+#ifdef DEBUG_SHADOW_DISTRIBUTION
+ float p[3];
+ add_v3_v3v3(p, jitter, mat[2]);
+ DRW_debug_sphere(p, 0.01f, (float[4]){1.0f, (sample_ofs == i) ? 1.0f : 0.0f, 0.0f, 1.0f});
+ }
+#endif
+
+ add_v3_v3(mat[2], jitter);
+ orthogonalize_m4(mat, 2);
+}
+
#define LERP(t, a, b) ((a) + (t) * ((b) - (a)))
static double round_to_digits(double value, int digits)
@@ -752,7 +875,7 @@ static void frustum_min_bounding_sphere(const float corners[8][3], float r_cente
static void eevee_shadow_cascade_setup(
Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led,
- DRWMatrixState *saved_mats, float view_near, float view_far)
+ DRWMatrixState *saved_mats, float view_near, float view_far, int sample_ofs)
{
Lamp *la = (Lamp *)ob->data;
@@ -762,7 +885,6 @@ static void eevee_shadow_cascade_setup(
bool is_persp = DRW_viewport_is_persp_get();
/* Lamps Matrices */
- int sh_nbr = 1; /* TODO : MSM */
int cascade_nbr = la->cascade_count;
EEVEE_ShadowCascadeData *sh_data = &led->data.scad;
@@ -776,8 +898,13 @@ static void eevee_shadow_cascade_setup(
#if 0 /* done at culling time */
normalize_m4_m4(viewmat, ob->obmat);
#endif
+
+ if (linfo->soft_shadows) {
+ shadow_cascade_random_matrix_set(viewmat, evli->radius, sample_ofs);
+ }
+
+ copy_m4_m4(sh_data->viewinv, viewmat);
invert_m4(viewmat);
- invert_m4_m4(sh_data->viewinv, viewmat);
/* The technique consists into splitting
* the view frustum into several sub-frustum
@@ -953,7 +1080,6 @@ static void eevee_shadow_cascade_setup(
evli->shadowid = (float)(sh_data->shadow_id);
ubo_data->shadow_start = (float)(sh_data->layer_id);
ubo_data->data_start = (float)(sh_data->cascade_id);
- ubo_data->multi_shadow_count = (float)(sh_nbr);
ubo_data->shadow_blur = la->soft * 0.02f; /* Used by translucence shadowmap blur */
ubo_data->contact_dist = (la->mode & LA_SHAD_CONTACT) ? la->contact_dist : 0.0f;
@@ -974,8 +1100,10 @@ static bool sphere_bbox_intersect(const EEVEE_BoundSphere *bs, const EEVEE_Bound
return x && y && z;
}
-void EEVEE_lights_update(EEVEE_ViewLayerData *sldata)
+void EEVEE_lights_update(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
EEVEE_LampsInfo *linfo = sldata->lamps;
Object *ob;
int i;
@@ -1031,8 +1159,8 @@ void EEVEE_lights_update(EEVEE_ViewLayerData *sldata)
for (i = 0; (i < MAX_SHADOW_CUBE) && (ob = linfo->shadow_cube_ref[i]); i++) {
EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob);
- eevee_shadow_cube_setup(ob, linfo, led);
- if (lightbits_get(&update_bits, i) != 0) {
+ eevee_shadow_cube_setup(ob, linfo, led, effects->taa_current_sample - 1);
+ if (lightbits_get(&update_bits, i) != 0 || linfo->soft_shadows) {
led->need_update = true;
}
}
@@ -1047,8 +1175,11 @@ void EEVEE_lights_update(EEVEE_ViewLayerData *sldata)
}
/* this refresh lamps shadow buffers */
-void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
+void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_EffectsInfo *effects = stl->effects;
EEVEE_LampsInfo *linfo = sldata->lamps;
Object *ob;
int i;
@@ -1071,6 +1202,7 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
EEVEE_ShadowCascadeData *sh_data = &led->data.scad;
float plane[4];
normalize_m4_m4(sh_data->viewmat, ob->obmat);
+
plane_from_point_normal_v3(plane, sh_data->viewmat[3], sh_data->viewmat[2]);
/* TODO: check against near/far instead of "local Z = 0" plane.
* Or even the cascades AABB. */
@@ -1098,12 +1230,13 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
EEVEE_ShadowRender *srd = &linfo->shadow_render_data;
EEVEE_ShadowCubeData *evscd = &led->data.scd;
+ EEVEE_ShadowCube *cube_data = linfo->shadow_cube_data + evscd->cube_id;
perspective_m4(winmat, -la->clipsta, la->clipsta, -la->clipsta, la->clipsta, la->clipsta, la->clipend);
srd->clip_near = la->clipsta;
srd->clip_far = la->clipend;
- copy_v3_v3(srd->position, ob->obmat[3]);
+ copy_v3_v3(srd->position, cube_data->position);
srd->stored_texel_size = 1.0 / (float)linfo->shadow_cube_store_size;
@@ -1178,7 +1311,9 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
DRWPass *store_pass = eevee_lights_cube_store_pass_get(psl, sldata, linfo->shadow_method, srd->shadow_samples_len);
DRW_draw_pass(store_pass);
- led->need_update = false;
+ if (linfo->soft_shadows == false) {
+ led->need_update = false;
+ }
}
linfo->update_flag &= ~LIGHT_UPDATE_SHADOW_CUBE;
DRW_stats_group_end();
@@ -1205,7 +1340,7 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl)
float (*viewmat)[4] = render_mats.mat[DRW_MAT_VIEW];
float (*persmat)[4] = render_mats.mat[DRW_MAT_PERS];
- eevee_shadow_cascade_setup(ob, linfo, led, &saved_mats, near, far);
+ eevee_shadow_cascade_setup(ob, linfo, led, &saved_mats, near, far, effects->taa_current_sample);
srd->clip_near = la->clipsta;
srd->clip_far = la->clipend;
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 7a0180074f5..fbabf86074e 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -413,7 +413,7 @@ typedef struct EEVEE_LampsInfo {
int cpu_cube_len, cpu_cascade_len;
int update_flag;
int shadow_cube_size, shadow_cascade_size, shadow_method;
- bool shadow_high_bitdepth;
+ bool shadow_high_bitdepth, soft_shadows;
int shadow_cube_store_size;
int current_shadow_cascade;
int current_shadow_face;
@@ -852,9 +852,9 @@ void EEVEE_lights_cache_shcaster_material_add(
struct GPUMaterial *gpumat, struct GPUBatch *geom, struct Object *ob,
float *alpha_threshold);
void EEVEE_lights_cache_shcaster_object_add(EEVEE_ViewLayerData *sldata, struct Object *ob);
-void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata);
-void EEVEE_lights_update(EEVEE_ViewLayerData *sldata);
-void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl);
+void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_lights_update(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
+void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_lights_free(void);
diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c
index b110b3f253e..06479588017 100644
--- a/source/blender/draw/engines/eevee/eevee_render.c
+++ b/source/blender/draw/engines/eevee/eevee_render.c
@@ -433,7 +433,7 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
/* FINISH CACHE */
EEVEE_materials_cache_finish(vedata);
- EEVEE_lights_cache_finish(sldata);
+ EEVEE_lights_cache_finish(sldata, vedata);
EEVEE_lightprobes_cache_finish(sldata, vedata);
/* Sort transparents before the loop. */
@@ -507,7 +507,8 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
RE_engine_update_stats(engine, NULL, info);
/* Refresh Shadows */
- EEVEE_draw_shadows(sldata, psl);
+ EEVEE_lights_update(sldata, vedata);
+ EEVEE_draw_shadows(sldata, vedata);
GPU_framebuffer_bind(fbl->main_fb);
GPU_framebuffer_clear_color_depth_stencil(fbl->main_fb, clear_col, clear_depth, clear_stencil);
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index ad38c7cfcdf..9045fb4353d 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -2191,6 +2191,7 @@ enum {
SCE_EEVEE_SHOW_IRRADIANCE = (1 << 17),
SCE_EEVEE_SHOW_CUBEMAPS = (1 << 18),
SCE_EEVEE_GI_AUTOBAKE = (1 << 19),
+ SCE_EEVEE_SHADOW_SOFT = (1 << 20),
};
/* SceneEEVEE->shadow_method */
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 1d52b0011c1..466c7573edf 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -6014,6 +6014,12 @@ static void rna_def_scene_eevee(BlenderRNA *brna)
RNA_def_property_boolean_default(prop, 0);
RNA_def_property_ui_text(prop, "High Bitdepth", "Use 32bit shadows");
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
+
+ prop = RNA_def_property(srna, "use_soft_shadows", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_SHADOW_SOFT);
+ RNA_def_property_boolean_default(prop, 0);
+ RNA_def_property_ui_text(prop, "Soft Shadows", "Randomize shadowmaps origin to create soft shadows");
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
}
void RNA_def_scene(BlenderRNA *brna)