Eevee: Shadows: Add Contact Shadows
[blender.git] / source / blender / draw / engines / eevee / eevee_lights.c
index 396318872aad8f29e940ba9adc18f97e25ab9014..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. */
@@ -873,14 +884,6 @@ void EEVEE_lights_update(EEVEE_SceneLayerData *sldata)
                eevee_shadow_cube_setup(ob, linfo, led);
                delete_pruned_shadowcaster(led);
        }
-
-       for (i = 0; (ob = linfo->shadow_cascade_ref[i]) && (i < MAX_SHADOW_CASCADE); i++) {
-               EEVEE_LampEngineData *led = EEVEE_lamp_data_get(ob);
-               eevee_shadow_cascade_setup(ob, linfo, led);
-       }
-
-       DRW_uniformbuffer_update(sldata->light_ubo, &linfo->light_data);
-       DRW_uniformbuffer_update(sldata->shadow_ubo, &linfo->shadow_data); /* Update all data at once */
 }
 
 /* this refresh lamps shadow buffers */
@@ -892,6 +895,7 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
        float clear_col[4] = {FLT_MAX};
 
        /* Cube Shadow Maps */
+       DRW_stats_group_start("Cube Shadow Maps");
        DRW_framebuffer_texture_attach(sldata->shadow_target_fb, sldata->shadow_cube_target, 0, 0);
        /* Render each shadow to one layer of the array */
        for (i = 0; (ob = linfo->shadow_cube_ref[i]) && (i < MAX_SHADOW_CUBE); i++) {
@@ -903,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;
@@ -962,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);
 
@@ -972,8 +977,10 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
        linfo->update_flag &= ~LIGHT_UPDATE_SHADOW_CUBE;
 
        DRW_framebuffer_texture_detach(sldata->shadow_cube_target);
+       DRW_stats_group_end();
 
        /* Cascaded Shadow Maps */
+       DRW_stats_group_start("Cascaded Shadow Maps");
        DRW_framebuffer_texture_attach(sldata->shadow_target_fb, sldata->shadow_cascade_target, 0, 0);
        for (i = 0; (ob = linfo->shadow_cascade_ref[i]) && (i < MAX_SHADOW_CASCADE); i++) {
                EEVEE_LampEngineData *led = EEVEE_lamp_data_get(ob);
@@ -982,6 +989,8 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
                EEVEE_ShadowCascadeData *evscd = (EEVEE_ShadowCascadeData *)led->storage;
                EEVEE_ShadowRender *srd = &linfo->shadow_render_data;
 
+               eevee_shadow_cascade_setup(ob, linfo, led);
+
                srd->clip_near = la->clipsta;
                srd->clip_far = la->clipend;
                for (int j = 0; j < la->cascade_count; ++j) {
@@ -1040,6 +1049,10 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
        }
 
        DRW_framebuffer_texture_detach(sldata->shadow_cascade_target);
+       DRW_stats_group_end();
+
+       DRW_uniformbuffer_update(sldata->light_ubo, &linfo->light_data);
+       DRW_uniformbuffer_update(sldata->shadow_ubo, &linfo->shadow_data); /* Update all data at once */
 }
 
 void EEVEE_lights_free(void)