|
|
|
|
@@ -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;
|
|
|
|
|
|