Eevee: Add Cascaded Shadow Map options.
This commit is contained in:
@@ -386,6 +386,13 @@ class DATA_PT_EEVEE_shadow(DataButtonsPanel, Panel):
|
|||||||
col.prop(lamp, "shadow_buffer_exp", text="Exponent")
|
col.prop(lamp, "shadow_buffer_exp", text="Exponent")
|
||||||
col.prop(lamp, "shadow_buffer_bleed_bias", text="Bleed Bias")
|
col.prop(lamp, "shadow_buffer_bleed_bias", text="Bleed Bias")
|
||||||
|
|
||||||
|
col = layout.column()
|
||||||
|
col.label("Cascaded Shadow Map:")
|
||||||
|
col.prop(lamp, "shadow_cascade_max_distance", text="Max Distance")
|
||||||
|
col.prop(lamp, "shadow_cascade_count", text="Count")
|
||||||
|
col.prop(lamp, "shadow_cascade_exponent", text="Distribution")
|
||||||
|
col.prop(lamp, "shadow_cascade_fade", text="Fade")
|
||||||
|
|
||||||
|
|
||||||
class DATA_PT_area(DataButtonsPanel, Panel):
|
class DATA_PT_area(DataButtonsPanel, Panel):
|
||||||
bl_label = "Area Shape"
|
bl_label = "Area Shape"
|
||||||
|
|||||||
@@ -102,6 +102,10 @@ void BKE_lamp_init(Lamp *la)
|
|||||||
la->sky_colorspace = BLI_XYZ_CIE;
|
la->sky_colorspace = BLI_XYZ_CIE;
|
||||||
la->sky_exposure = 1.0f;
|
la->sky_exposure = 1.0f;
|
||||||
la->shadow_frustum_size = 10.0f;
|
la->shadow_frustum_size = 10.0f;
|
||||||
|
la->cascade_max_dist = 1000.0f;
|
||||||
|
la->cascade_count = 4;
|
||||||
|
la->cascade_exponent = 0.8f;
|
||||||
|
la->cascade_fade = 0.1f;
|
||||||
|
|
||||||
curvemapping_initialize(la->curfalloff);
|
curvemapping_initialize(la->curfalloff);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -432,6 +432,15 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!DNA_struct_elem_find(fd->filesdna, "Lamp", "float", "cascade_max_dist")) {
|
||||||
|
for (Lamp *la = main->lamp.first; la; la = la->id.next) {
|
||||||
|
la->cascade_max_dist = 1000.0f;
|
||||||
|
la->cascade_count = 4;
|
||||||
|
la->cascade_exponent = 0.8f;
|
||||||
|
la->cascade_fade = 0.1f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
typedef enum eNTreeDoVersionErrors {
|
typedef enum eNTreeDoVersionErrors {
|
||||||
NTREE_DOVERSION_NO_ERROR = 0,
|
NTREE_DOVERSION_NO_ERROR = 0,
|
||||||
|
|||||||
@@ -493,10 +493,12 @@ static void frustum_min_bounding_sphere(const float corners[8][4], float r_cente
|
|||||||
|
|
||||||
static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led)
|
static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led)
|
||||||
{
|
{
|
||||||
|
Lamp *la = (Lamp *)ob->data;
|
||||||
|
|
||||||
/* Camera Matrices */
|
/* Camera Matrices */
|
||||||
float persmat[4][4], persinv[4][4];
|
float persmat[4][4], persinv[4][4];
|
||||||
float viewprojmat[4][4], projinv[4][4];
|
float viewprojmat[4][4], projinv[4][4];
|
||||||
float near, far;
|
float view_near, view_far;
|
||||||
float near_v[4] = {0.0f, 0.0f, -1.0f, 1.0f};
|
float near_v[4] = {0.0f, 0.0f, -1.0f, 1.0f};
|
||||||
float far_v[4] = {0.0f, 0.0f, 1.0f, 1.0f};
|
float far_v[4] = {0.0f, 0.0f, 1.0f, 1.0f};
|
||||||
bool is_persp = DRW_viewport_is_persp_get();
|
bool is_persp = DRW_viewport_is_persp_get();
|
||||||
@@ -507,75 +509,134 @@ static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE
|
|||||||
invert_m4_m4(projinv, viewprojmat);
|
invert_m4_m4(projinv, viewprojmat);
|
||||||
mul_m4_v4(projinv, near_v);
|
mul_m4_v4(projinv, near_v);
|
||||||
mul_m4_v4(projinv, far_v);
|
mul_m4_v4(projinv, far_v);
|
||||||
near = near_v[2];
|
view_near = near_v[2];
|
||||||
far = far_v[2]; /* TODO: Should be a shadow parameter */
|
view_far = far_v[2]; /* TODO: Should be a shadow parameter */
|
||||||
if (is_persp) {
|
if (is_persp) {
|
||||||
near /= near_v[3];
|
view_near /= near_v[3];
|
||||||
far /= far_v[3];
|
view_far /= far_v[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lamps Matrices */
|
/* Lamps Matrices */
|
||||||
float viewmat[4][4], projmat[4][4];
|
float viewmat[4][4], projmat[4][4];
|
||||||
int sh_nbr = 1; /* TODO : MSM */
|
int sh_nbr = 1; /* TODO : MSM */
|
||||||
int cascade_nbr = MAX_CASCADE_NUM; /* TODO : Custom cascade number */
|
int cascade_nbr = la->cascade_count;
|
||||||
|
|
||||||
EEVEE_ShadowCascadeData *sh_data = (EEVEE_ShadowCascadeData *)led->storage;
|
EEVEE_ShadowCascadeData *sh_data = (EEVEE_ShadowCascadeData *)led->storage;
|
||||||
EEVEE_Light *evli = linfo->light_data + sh_data->light_id;
|
EEVEE_Light *evli = linfo->light_data + sh_data->light_id;
|
||||||
EEVEE_Shadow *ubo_data = linfo->shadow_data + sh_data->shadow_id;
|
EEVEE_Shadow *ubo_data = linfo->shadow_data + sh_data->shadow_id;
|
||||||
EEVEE_ShadowCascade *cascade_data = linfo->shadow_cascade_data + sh_data->cascade_id;
|
EEVEE_ShadowCascade *cascade_data = linfo->shadow_cascade_data + sh_data->cascade_id;
|
||||||
Lamp *la = (Lamp *)ob->data;
|
|
||||||
|
|
||||||
/* The technique consists into splitting
|
/* The technique consists into splitting
|
||||||
* the view frustum into several sub-frustum
|
* the view frustum into several sub-frustum
|
||||||
* that are individually receiving one shadow map */
|
* that are individually receiving one shadow map */
|
||||||
|
|
||||||
|
float csm_start, csm_end;
|
||||||
|
|
||||||
|
if (is_persp) {
|
||||||
|
csm_start = view_near;
|
||||||
|
csm_end = max_ff(view_far, -la->cascade_max_dist);
|
||||||
|
/* Avoid artifacts */
|
||||||
|
csm_end = min_ff(view_near, csm_end);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
csm_start = -view_far;
|
||||||
|
csm_end = view_far;
|
||||||
|
}
|
||||||
|
|
||||||
/* init near/far */
|
/* init near/far */
|
||||||
for (int c = 0; c < MAX_CASCADE_NUM; ++c) {
|
for (int c = 0; c < MAX_CASCADE_NUM; ++c) {
|
||||||
cascade_data->split[c] = far;
|
cascade_data->split_start[c] = csm_end;
|
||||||
|
cascade_data->split_end[c] = csm_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compute split planes */
|
/* Compute split planes */
|
||||||
float splits_ndc[MAX_CASCADE_NUM + 1];
|
float splits_start_ndc[MAX_CASCADE_NUM];
|
||||||
splits_ndc[0] = -1.0f;
|
float splits_end_ndc[MAX_CASCADE_NUM];
|
||||||
splits_ndc[cascade_nbr] = 1.0f;
|
|
||||||
for (int c = 1; c < cascade_nbr; ++c) {
|
|
||||||
const float lambda = 0.8f; /* TODO : Parameter */
|
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Nearest plane */
|
||||||
|
float p[4] = {1.0f, 1.0f, csm_start, 1.0f};
|
||||||
|
/* TODO: we don't need full m4 multiply here */
|
||||||
|
mul_m4_v4(viewprojmat, p);
|
||||||
|
splits_start_ndc[0] = p[2];
|
||||||
|
if (is_persp) {
|
||||||
|
splits_start_ndc[0] /= p[3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Farthest plane */
|
||||||
|
float p[4] = {1.0f, 1.0f, csm_end, 1.0f};
|
||||||
|
/* TODO: we don't need full m4 multiply here */
|
||||||
|
mul_m4_v4(viewprojmat, p);
|
||||||
|
splits_end_ndc[cascade_nbr - 1] = p[2];
|
||||||
|
if (is_persp) {
|
||||||
|
splits_end_ndc[cascade_nbr - 1] /= p[3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cascade_data->split_start[0] = csm_start;
|
||||||
|
cascade_data->split_end[cascade_nbr - 1] = csm_end;
|
||||||
|
|
||||||
|
for (int c = 1; c < cascade_nbr; ++c) {
|
||||||
/* View Space */
|
/* View Space */
|
||||||
float linear_split = LERP(((float)(c) / (float)cascade_nbr), near, far);
|
float linear_split = LERP(((float)(c) / (float)cascade_nbr), csm_start, csm_end);
|
||||||
float exp_split = near * powf(far / near, (float)(c) / (float)cascade_nbr);
|
float exp_split = csm_start * powf(csm_end / csm_start, (float)(c) / (float)cascade_nbr);
|
||||||
|
|
||||||
if (is_persp) {
|
if (is_persp) {
|
||||||
cascade_data->split[c-1] = LERP(lambda, linear_split, exp_split);
|
cascade_data->split_start[c] = LERP(la->cascade_exponent, linear_split, exp_split);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
cascade_data->split[c-1] = linear_split;
|
cascade_data->split_start[c] = linear_split;
|
||||||
}
|
}
|
||||||
|
cascade_data->split_end[c-1] = cascade_data->split_start[c];
|
||||||
|
|
||||||
|
/* Add some overlap for smooth transition */
|
||||||
|
cascade_data->split_start[c] = LERP(la->cascade_fade, cascade_data->split_end[c-1],
|
||||||
|
(c > 1) ? cascade_data->split_end[c-2] : cascade_data->split_start[0]);
|
||||||
|
|
||||||
/* NDC Space */
|
/* NDC Space */
|
||||||
float p[4] = {1.0f, 1.0f, cascade_data->split[c-1], 1.0f};
|
{
|
||||||
|
float p[4] = {1.0f, 1.0f, cascade_data->split_start[c], 1.0f};
|
||||||
|
/* TODO: we don't need full m4 multiply here */
|
||||||
mul_m4_v4(viewprojmat, p);
|
mul_m4_v4(viewprojmat, p);
|
||||||
splits_ndc[c] = p[2];
|
splits_start_ndc[c] = p[2];
|
||||||
|
|
||||||
if (is_persp) {
|
if (is_persp) {
|
||||||
splits_ndc[c] /= p[3];
|
splits_start_ndc[c] /= p[3];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
float p[4] = {1.0f, 1.0f, cascade_data->split_end[c-1], 1.0f};
|
||||||
|
/* TODO: we don't need full m4 multiply here */
|
||||||
|
mul_m4_v4(viewprojmat, p);
|
||||||
|
splits_end_ndc[c-1] = p[2];
|
||||||
|
|
||||||
|
if (is_persp) {
|
||||||
|
splits_end_ndc[c-1] /= p[3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set last cascade split fade distance into the first split_start. */
|
||||||
|
float prev_split = (cascade_nbr > 1) ? cascade_data->split_end[cascade_nbr-2] : cascade_data->split_start[0];
|
||||||
|
cascade_data->split_start[0] = LERP(la->cascade_fade, cascade_data->split_end[cascade_nbr-1], prev_split);
|
||||||
|
|
||||||
/* For each cascade */
|
/* For each cascade */
|
||||||
for (int c = 0; c < cascade_nbr; ++c) {
|
for (int c = 0; c < cascade_nbr; ++c) {
|
||||||
/* Given 8 frustum corners */
|
/* Given 8 frustum corners */
|
||||||
float corners[8][4] = {
|
float corners[8][4] = {
|
||||||
/* Near Cap */
|
/* Near Cap */
|
||||||
{-1.0f, -1.0f, splits_ndc[c], 1.0f},
|
{-1.0f, -1.0f, splits_start_ndc[c], 1.0f},
|
||||||
{ 1.0f, -1.0f, splits_ndc[c], 1.0f},
|
{ 1.0f, -1.0f, splits_start_ndc[c], 1.0f},
|
||||||
{-1.0f, 1.0f, splits_ndc[c], 1.0f},
|
{-1.0f, 1.0f, splits_start_ndc[c], 1.0f},
|
||||||
{ 1.0f, 1.0f, splits_ndc[c], 1.0f},
|
{ 1.0f, 1.0f, splits_start_ndc[c], 1.0f},
|
||||||
/* Far Cap */
|
/* Far Cap */
|
||||||
{-1.0f, -1.0f, splits_ndc[c+1], 1.0f},
|
{-1.0f, -1.0f, splits_end_ndc[c], 1.0f},
|
||||||
{ 1.0f, -1.0f, splits_ndc[c+1], 1.0f},
|
{ 1.0f, -1.0f, splits_end_ndc[c], 1.0f},
|
||||||
{-1.0f, 1.0f, splits_ndc[c+1], 1.0f},
|
{-1.0f, 1.0f, splits_end_ndc[c], 1.0f},
|
||||||
{ 1.0f, 1.0f, splits_ndc[c+1], 1.0f}
|
{ 1.0f, 1.0f, splits_end_ndc[c], 1.0f}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Transform them into world space */
|
/* Transform them into world space */
|
||||||
@@ -585,6 +646,7 @@ static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE
|
|||||||
corners[i][3] = 1.0f;
|
corners[i][3] = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Project them into light space */
|
/* Project them into light space */
|
||||||
invert_m4_m4(viewmat, ob->obmat);
|
invert_m4_m4(viewmat, ob->obmat);
|
||||||
normalize_v3(viewmat[0]);
|
normalize_v3(viewmat[0]);
|
||||||
@@ -837,7 +899,7 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
|
|||||||
srd->shadow_inv_samples_ct = 1.0f / srd->shadow_samples_ct;
|
srd->shadow_inv_samples_ct = 1.0f / srd->shadow_samples_ct;
|
||||||
srd->clip_near = la->clipsta;
|
srd->clip_near = la->clipsta;
|
||||||
srd->clip_far = la->clipend;
|
srd->clip_far = la->clipend;
|
||||||
for (int j = 0; j < MAX_CASCADE_NUM; ++j) {
|
for (int j = 0; j < la->cascade_count; ++j) {
|
||||||
copy_m4_m4(srd->shadowmat[j], evscd->viewprojmat[j]);
|
copy_m4_m4(srd->shadowmat[j], evscd->viewprojmat[j]);
|
||||||
}
|
}
|
||||||
DRW_uniformbuffer_update(sldata->shadow_render_ubo, &linfo->shadow_render_data);
|
DRW_uniformbuffer_update(sldata->shadow_render_ubo, &linfo->shadow_render_data);
|
||||||
@@ -849,7 +911,7 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
|
|||||||
DRW_draw_pass(psl->shadow_cascade_pass);
|
DRW_draw_pass(psl->shadow_cascade_pass);
|
||||||
|
|
||||||
for (linfo->current_shadow_cascade = 0;
|
for (linfo->current_shadow_cascade = 0;
|
||||||
linfo->current_shadow_cascade < MAX_CASCADE_NUM;
|
linfo->current_shadow_cascade < la->cascade_count;
|
||||||
++linfo->current_shadow_cascade)
|
++linfo->current_shadow_cascade)
|
||||||
{
|
{
|
||||||
linfo->filter_size = la->soft * 0.0005f / (evscd->radius[linfo->current_shadow_cascade] * 0.05f);
|
linfo->filter_size = la->soft * 0.0005f / (evscd->radius[linfo->current_shadow_cascade] * 0.05f);
|
||||||
|
|||||||
@@ -223,7 +223,8 @@ typedef struct EEVEE_ShadowCube {
|
|||||||
|
|
||||||
typedef struct EEVEE_ShadowCascade {
|
typedef struct EEVEE_ShadowCascade {
|
||||||
float shadowmat[MAX_CASCADE_NUM][4][4]; /* World->Lamp->NDC->Tex : used for sampling the shadow map. */
|
float shadowmat[MAX_CASCADE_NUM][4][4]; /* World->Lamp->NDC->Tex : used for sampling the shadow map. */
|
||||||
float split[4];
|
float split_start[4];
|
||||||
|
float split_end[4];
|
||||||
} EEVEE_ShadowCascade;
|
} EEVEE_ShadowCascade;
|
||||||
|
|
||||||
typedef struct EEVEE_ShadowRender {
|
typedef struct EEVEE_ShadowRender {
|
||||||
|
|||||||
@@ -89,7 +89,8 @@ struct ShadowCubeData {
|
|||||||
|
|
||||||
struct ShadowCascadeData {
|
struct ShadowCascadeData {
|
||||||
mat4 shadowmat[MAX_CASCADE_NUM];
|
mat4 shadowmat[MAX_CASCADE_NUM];
|
||||||
vec4 split_distances;
|
vec4 split_start_distances;
|
||||||
|
vec4 split_end_distances;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* convenience aliases */
|
/* convenience aliases */
|
||||||
|
|||||||
@@ -78,37 +78,15 @@ float shadow_cubemap(ShadowData sd, ShadowCubeData scd, float texid, vec3 W)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
float shadow_cascade(ShadowData sd, ShadowCascadeData scd, float texid, vec3 W)
|
float evaluate_cascade(ShadowData sd, mat4 shadowmat, vec3 W, float range, float texid)
|
||||||
{
|
{
|
||||||
/* Finding Cascade index */
|
|
||||||
vec4 view_z = vec4(dot(W - cameraPos, cameraForward));
|
|
||||||
vec4 comp = step(view_z, scd.split_distances);
|
|
||||||
float cascade = dot(comp, comp);
|
|
||||||
mat4 shadowmat;
|
|
||||||
|
|
||||||
/* Manual Unrolling of a loop for better performance.
|
|
||||||
* Doing fetch directly with cascade index leads to
|
|
||||||
* major performance impact. (0.27ms -> 10.0ms for 1 light) */
|
|
||||||
if (cascade == 0.0) {
|
|
||||||
shadowmat = scd.shadowmat[0];
|
|
||||||
}
|
|
||||||
else if (cascade == 1.0) {
|
|
||||||
shadowmat = scd.shadowmat[1];
|
|
||||||
}
|
|
||||||
else if (cascade == 2.0) {
|
|
||||||
shadowmat = scd.shadowmat[2];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
shadowmat = scd.shadowmat[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 shpos = shadowmat * vec4(W, 1.0);
|
vec4 shpos = shadowmat * vec4(W, 1.0);
|
||||||
float dist = shpos.z * abs(sd.sh_far - sd.sh_near); /* Same factor as in get_cascade_world_distance(). */
|
float dist = shpos.z * range;
|
||||||
|
|
||||||
#if defined(SHADOW_VSM)
|
#if defined(SHADOW_VSM)
|
||||||
vec2 moments = texture(shadowTexture, vec3(shpos.xy, texid + cascade)).rg;
|
vec2 moments = texture(shadowTexture, vec3(shpos.xy, texid)).rg;
|
||||||
#else
|
#else
|
||||||
float z = texture(shadowTexture, vec3(shpos.xy, texid + cascade)).r;
|
float z = texture(shadowTexture, vec3(shpos.xy, texid)).r;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SHADOW_VSM)
|
#if defined(SHADOW_VSM)
|
||||||
@@ -120,6 +98,38 @@ float shadow_cascade(ShadowData sd, ShadowCascadeData scd, float texid, vec3 W)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float shadow_cascade(ShadowData sd, ShadowCascadeData scd, float texid, vec3 W)
|
||||||
|
{
|
||||||
|
vec4 view_z = vec4(dot(W - cameraPos, cameraForward));
|
||||||
|
vec4 weights = smoothstep(scd.split_end_distances, scd.split_start_distances.yzwx, view_z);
|
||||||
|
weights.yzw -= weights.xyz;
|
||||||
|
|
||||||
|
vec4 vis = vec4(1.0);
|
||||||
|
float range = abs(sd.sh_far - sd.sh_near); /* Same factor as in get_cascade_world_distance(). */
|
||||||
|
if (weights.x > 0.0) {
|
||||||
|
vis.x = evaluate_cascade(sd, scd.shadowmat[0], W, range, texid + 0);
|
||||||
|
}
|
||||||
|
if (weights.y > 0.0) {
|
||||||
|
vis.y = evaluate_cascade(sd, scd.shadowmat[1], W, range, texid + 1);
|
||||||
|
}
|
||||||
|
if (weights.z > 0.0) {
|
||||||
|
vis.z = evaluate_cascade(sd, scd.shadowmat[2], W, range, texid + 2);
|
||||||
|
}
|
||||||
|
if (weights.w > 0.0) {
|
||||||
|
vis.w = evaluate_cascade(sd, scd.shadowmat[3], W, range, texid + 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
float weight_sum = dot(vec4(1.0), weights);
|
||||||
|
if (weight_sum > 0.9999) {
|
||||||
|
float vis_sum = dot(vec4(1.0), vis * weights);
|
||||||
|
return vis_sum / weight_sum;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
float vis_sum = dot(vec4(1.0), vis * step(0.001, weights));
|
||||||
|
return mix(1.0, vis_sum, weight_sum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------- */
|
/* ----------------------------------------------------------- */
|
||||||
/* --------------------- Light Functions --------------------- */
|
/* --------------------- Light Functions --------------------- */
|
||||||
/* ----------------------------------------------------------- */
|
/* ----------------------------------------------------------- */
|
||||||
|
|||||||
@@ -57,6 +57,10 @@ float linear_depth(float z)
|
|||||||
float get_cascade_world_distance(vec2 uvs)
|
float get_cascade_world_distance(vec2 uvs)
|
||||||
{
|
{
|
||||||
float zdepth = texture(shadowTexture, vec3(uvs, float(cascadeId))).r;
|
float zdepth = texture(shadowTexture, vec3(uvs, float(cascadeId))).r;
|
||||||
|
if (zdepth == 1.0) {
|
||||||
|
/* Background case */
|
||||||
|
return 1e16;
|
||||||
|
}
|
||||||
return zdepth * abs(farClip - nearClip); /* Same factor as in shadow_cascade(). */
|
return zdepth * abs(farClip - nearClip); /* Same factor as in shadow_cascade(). */
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -106,6 +106,12 @@ typedef struct Lamp {
|
|||||||
short pr_texture, use_nodes;
|
short pr_texture, use_nodes;
|
||||||
char pad6[4];
|
char pad6[4];
|
||||||
|
|
||||||
|
/* Eevee */
|
||||||
|
float cascade_max_dist;
|
||||||
|
float cascade_exponent;
|
||||||
|
float cascade_fade;
|
||||||
|
int cascade_count;
|
||||||
|
|
||||||
/* preview */
|
/* preview */
|
||||||
struct PreviewImage *preview;
|
struct PreviewImage *preview;
|
||||||
|
|
||||||
|
|||||||
@@ -476,7 +476,7 @@ static void rna_def_lamp_falloff(StructRNA *srna)
|
|||||||
RNA_def_property_update(prop, 0, "rna_Lamp_draw_update");
|
RNA_def_property_update(prop, 0, "rna_Lamp_draw_update");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rna_def_lamp_shadow(StructRNA *srna, int spot, int area)
|
static void rna_def_lamp_shadow(StructRNA *srna, int spot, int area, int sun)
|
||||||
{
|
{
|
||||||
PropertyRNA *prop;
|
PropertyRNA *prop;
|
||||||
|
|
||||||
@@ -698,6 +698,32 @@ static void rna_def_lamp_shadow(StructRNA *srna, int spot, int area)
|
|||||||
RNA_def_property_boolean_sdna(prop, NULL, "mode", LA_LAYER_SHADOW);
|
RNA_def_property_boolean_sdna(prop, NULL, "mode", LA_LAYER_SHADOW);
|
||||||
RNA_def_property_ui_text(prop, "Shadow Layer", "Objects on the same layers only cast shadows");
|
RNA_def_property_ui_text(prop, "Shadow Layer", "Objects on the same layers only cast shadows");
|
||||||
RNA_def_property_update(prop, 0, "rna_Lamp_update");
|
RNA_def_property_update(prop, 0, "rna_Lamp_update");
|
||||||
|
|
||||||
|
if (sun) {
|
||||||
|
prop = RNA_def_property(srna, "shadow_cascade_max_distance", PROP_FLOAT, PROP_DISTANCE);
|
||||||
|
RNA_def_property_float_sdna(prop, NULL, "cascade_max_dist");
|
||||||
|
RNA_def_property_range(prop, 0.0f, 9999.0f);
|
||||||
|
RNA_def_property_ui_text(prop, "Cascade Max Distance", "End distance of the cascaded shadow map (only in perspective view)");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Lamp_update");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "shadow_cascade_count", PROP_INT, PROP_NONE);
|
||||||
|
RNA_def_property_int_sdna(prop, NULL, "cascade_count");
|
||||||
|
RNA_def_property_range(prop, 1, 4);
|
||||||
|
RNA_def_property_ui_text(prop, "Cascade Count", "Number of texture used by the cascaded shadow map");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Lamp_update");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "shadow_cascade_exponent", PROP_FLOAT, PROP_FACTOR);
|
||||||
|
RNA_def_property_float_sdna(prop, NULL, "cascade_exponent");
|
||||||
|
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||||
|
RNA_def_property_ui_text(prop, "Exponential Distribution", "Higher value increase resolution towards the viewpoint");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Lamp_update");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "shadow_cascade_fade", PROP_FLOAT, PROP_FACTOR);
|
||||||
|
RNA_def_property_float_sdna(prop, NULL, "cascade_fade");
|
||||||
|
RNA_def_property_range(prop, 0.0f, 1.0f);
|
||||||
|
RNA_def_property_ui_text(prop, "Cascade Fade", "How smooth is the transition between each cascade");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Lamp_update");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rna_def_point_lamp(BlenderRNA *brna)
|
static void rna_def_point_lamp(BlenderRNA *brna)
|
||||||
@@ -710,7 +736,7 @@ static void rna_def_point_lamp(BlenderRNA *brna)
|
|||||||
RNA_def_struct_ui_icon(srna, ICON_LAMP_POINT);
|
RNA_def_struct_ui_icon(srna, ICON_LAMP_POINT);
|
||||||
|
|
||||||
rna_def_lamp_falloff(srna);
|
rna_def_lamp_falloff(srna);
|
||||||
rna_def_lamp_shadow(srna, 0, 0);
|
rna_def_lamp_shadow(srna, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rna_def_area_lamp(BlenderRNA *brna)
|
static void rna_def_area_lamp(BlenderRNA *brna)
|
||||||
@@ -729,7 +755,7 @@ static void rna_def_area_lamp(BlenderRNA *brna)
|
|||||||
RNA_def_struct_ui_text(srna, "Area Lamp", "Directional area lamp");
|
RNA_def_struct_ui_text(srna, "Area Lamp", "Directional area lamp");
|
||||||
RNA_def_struct_ui_icon(srna, ICON_LAMP_AREA);
|
RNA_def_struct_ui_icon(srna, ICON_LAMP_AREA);
|
||||||
|
|
||||||
rna_def_lamp_shadow(srna, 0, 1);
|
rna_def_lamp_shadow(srna, 0, 1, 0);
|
||||||
rna_def_lamp_falloff(srna);
|
rna_def_lamp_falloff(srna);
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "use_umbra", PROP_BOOLEAN, PROP_NONE);
|
prop = RNA_def_property(srna, "use_umbra", PROP_BOOLEAN, PROP_NONE);
|
||||||
@@ -786,7 +812,7 @@ static void rna_def_spot_lamp(BlenderRNA *brna)
|
|||||||
RNA_def_struct_ui_icon(srna, ICON_LAMP_SPOT);
|
RNA_def_struct_ui_icon(srna, ICON_LAMP_SPOT);
|
||||||
|
|
||||||
rna_def_lamp_falloff(srna);
|
rna_def_lamp_falloff(srna);
|
||||||
rna_def_lamp_shadow(srna, 1, 0);
|
rna_def_lamp_shadow(srna, 1, 0, 0);
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "use_square", PROP_BOOLEAN, PROP_NONE);
|
prop = RNA_def_property(srna, "use_square", PROP_BOOLEAN, PROP_NONE);
|
||||||
RNA_def_property_boolean_sdna(prop, NULL, "mode", LA_SQUARE);
|
RNA_def_property_boolean_sdna(prop, NULL, "mode", LA_SQUARE);
|
||||||
@@ -839,7 +865,7 @@ static void rna_def_sun_lamp(BlenderRNA *brna)
|
|||||||
RNA_def_struct_ui_text(srna, "Sun Lamp", "Constant direction parallel ray lamp");
|
RNA_def_struct_ui_text(srna, "Sun Lamp", "Constant direction parallel ray lamp");
|
||||||
RNA_def_struct_ui_icon(srna, ICON_LAMP_SUN);
|
RNA_def_struct_ui_icon(srna, ICON_LAMP_SUN);
|
||||||
|
|
||||||
rna_def_lamp_shadow(srna, 0, 0);
|
rna_def_lamp_shadow(srna, 0, 0, 1);
|
||||||
|
|
||||||
/* sky */
|
/* sky */
|
||||||
prop = RNA_def_property(srna, "sky", PROP_POINTER, PROP_NONE);
|
prop = RNA_def_property(srna, "sky", PROP_POINTER, PROP_NONE);
|
||||||
|
|||||||
Reference in New Issue
Block a user