Eevee: Shadows: Add Contact Shadows
[blender.git] / source / blender / draw / engines / eevee / eevee_lights.c
index 41537a9f1e36d26983e806a1d4f233956d05b886..8138b9a0ffd8b0baf610ab05be620d6a81a52542 100644 (file)
@@ -227,9 +227,9 @@ void EEVEE_lights_cache_add(EEVEE_SceneLayerData *sldata, Object *ob)
        EEVEE_LampsInfo *linfo = sldata->lamps;
 
        /* Step 1 find all lamps in the scene and setup them */
-       if (linfo->num_light > MAX_LIGHT) {
+       if (linfo->num_light >= MAX_LIGHT) {
                printf("Too much lamps in the scene !!!\n");
-               linfo->num_light = MAX_LIGHT;
+               linfo->num_light = MAX_LIGHT - 1;
        }
        else {
                Lamp *la = (Lamp *)ob->data;
@@ -320,9 +320,10 @@ void EEVEE_lights_cache_shcaster_add(EEVEE_SceneLayerData *sldata, EEVEE_PassLis
 }
 
 void EEVEE_lights_cache_shcaster_material_add(
-       EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl, struct GPUMaterial *gpumat, struct Gwn_Batch *geom, float (*obmat)[4], float *alpha_threshold)
+       EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl, struct GPUMaterial *gpumat,
+       struct Gwn_Batch *geom, struct Object *ob, float (*obmat)[4], float *alpha_threshold)
 {
-       DRWShadingGroup *grp = DRW_shgroup_material_instance_create(gpumat, psl->shadow_cube_pass, geom);
+       DRWShadingGroup *grp = DRW_shgroup_material_instance_create(gpumat, psl->shadow_cube_pass, geom, ob);
 
        if (grp == NULL) return;
 
@@ -335,7 +336,7 @@ void EEVEE_lights_cache_shcaster_material_add(
        for (int i = 0; i < 6; ++i)
                DRW_shgroup_call_dynamic_add_empty(grp);
 
-       grp = DRW_shgroup_material_instance_create(gpumat, psl->shadow_cascade_pass, geom);
+       grp = DRW_shgroup_material_instance_create(gpumat, psl->shadow_cascade_pass, geom, ob);
        DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
        DRW_shgroup_uniform_mat4(grp, "ShadowModelMatrix", (float *)obmat);
 
@@ -508,6 +509,11 @@ static void eevee_shadow_cube_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_La
        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->contact_dist = (la->mode & LA_SHAD_CONTACT) ? la->contact_dist : 0.0f;
+       ubo_data->contact_bias = 0.05f * la->contact_bias;
+       ubo_data->contact_spread = la->contact_spread;
+       ubo_data->contact_thickness = la->contact_thickness;
 }
 
 #define LERP(t, a, b) ((a) + (t) * ((b) - (a)))
@@ -749,6 +755,11 @@ static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE
        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->contact_dist = (la->mode & LA_SHAD_CONTACT) ? la->contact_dist : 0.0f;
+       ubo_data->contact_bias = 0.05f * la->contact_bias;
+       ubo_data->contact_spread = la->contact_spread;
+       ubo_data->contact_thickness = la->contact_thickness;
 }
 
 /* Used for checking if object is inside the shadow volume. */
@@ -896,6 +907,7 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
 
                if (led->need_update) {
                        EEVEE_ShadowRender *srd = &linfo->shadow_render_data;
+                       EEVEE_ShadowCubeData *evscd = (EEVEE_ShadowCubeData *)led->storage;
 
                        srd->clip_near = la->clipsta;
                        srd->clip_far = la->clipend;
@@ -955,7 +967,7 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
                        srd->shadow_inv_samples_ct = 1.0f / (float)srd->shadow_samples_ct;
                        DRW_uniformbuffer_update(sldata->shadow_render_ubo, srd);
 
-                       DRW_framebuffer_texture_layer_attach(sldata->shadow_store_fb, sldata->shadow_pool, 0, i, 0);
+                       DRW_framebuffer_texture_layer_attach(sldata->shadow_store_fb, sldata->shadow_pool, 0, evscd->layer_id, 0);
                        DRW_framebuffer_bind(sldata->shadow_store_fb);
                        DRW_draw_pass(psl->shadow_cube_store_pass);