Eevee: Transparency: Add support for Clip and Stochastic shadows.
authorClément Foucault <foucault.clem@gmail.com>
Mon, 10 Jul 2017 23:10:57 +0000 (01:10 +0200)
committerClément Foucault <foucault.clem@gmail.com>
Tue, 11 Jul 2017 10:39:35 +0000 (12:39 +0200)
source/blender/draw/engines/eevee/eevee_lights.c
source/blender/draw/engines/eevee/eevee_materials.c
source/blender/draw/engines/eevee/eevee_private.h
source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
source/blender/draw/engines/eevee/shaders/prepass_frag.glsl
source/blender/draw/engines/eevee/shaders/shadow_frag.glsl
source/blender/draw/engines/eevee/shaders/shadow_geom.glsl
source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl
source/blender/draw/engines/eevee/shaders/shadow_store_geom.glsl
source/blender/draw/engines/eevee/shaders/shadow_vert.glsl

index c6436d5b92375affec5dfd2d2a58c9795a6dab47..37b33e210215f3c091975ca22255ceacd29af669 100644 (file)
@@ -196,6 +196,30 @@ void EEVEE_lights_cache_shcaster_add(EEVEE_SceneLayerData *sldata, EEVEE_PassLis
                DRW_shgroup_call_dynamic_add_empty(grp);
 }
 
+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)
+{
+       DRWShadingGroup *grp = DRW_shgroup_material_instance_create(gpumat, psl->shadow_cube_pass, geom);
+       DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
+       DRW_shgroup_uniform_mat4(grp, "ShadowModelMatrix", (float *)obmat);
+
+       if (alpha_threshold != NULL)
+               DRW_shgroup_uniform_float(grp, "alphaThreshold", alpha_threshold, 1);
+
+       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);
+       DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
+       DRW_shgroup_uniform_mat4(grp, "ShadowModelMatrix", (float *)obmat);
+
+       if (alpha_threshold != NULL)
+               DRW_shgroup_uniform_float(grp, "alphaThreshold", alpha_threshold, 1);
+
+       for (int i = 0; i < MAX_CASCADE_NUM; ++i)
+               DRW_shgroup_call_dynamic_add_empty(grp);
+}
+
 void EEVEE_lights_cache_finish(EEVEE_SceneLayerData *sldata)
 {
        EEVEE_LampsInfo *linfo = sldata->lamps;
@@ -727,6 +751,12 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
                        srd->exponent = la->bleedexp;
                        copy_v3_v3(srd->position, ob->obmat[3]);
                        for (int j = 0; j < 6; ++j) {
+                               float tmp[4][4];
+
+                               unit_m4(tmp);
+                               negate_v3_v3(tmp[3], ob->obmat[3]);
+                               mul_m4_m4m4(srd->viewmat[j], cubefacemat[i], tmp);
+
                                copy_m4_m4(srd->shadowmat[j], evscd->viewprojmat[j]);
                        }
                        DRW_uniformbuffer_update(sldata->shadow_render_ubo, &linfo->shadow_render_data);
index bd6c4b9ccc09387c008ccfbe5c5717c308e12b9f..ab56b90841689a7a237517cb9e95f83cd97cde83 100644 (file)
@@ -94,9 +94,8 @@ extern char datatoc_irradiance_lib_glsl[];
 extern char datatoc_octahedron_lib_glsl[];
 extern char datatoc_lit_surface_frag_glsl[];
 extern char datatoc_lit_surface_vert_glsl[];
-extern char datatoc_shadow_frag_glsl[];
-extern char datatoc_shadow_geom_glsl[];
 extern char datatoc_shadow_vert_glsl[];
+extern char datatoc_shadow_geom_glsl[];
 extern char datatoc_lightprobe_geom_glsl[];
 extern char datatoc_lightprobe_vert_glsl[];
 extern char datatoc_background_vert_glsl[];
@@ -203,6 +202,9 @@ static char *eevee_get_defines(int options)
        if ((options & VAR_MAT_CLIP) != 0) {
                BLI_dynstr_appendf(ds, "#define USE_ALPHA_CLIP\n");
        }
+       if ((options & VAR_MAT_SHADOW) != 0) {
+               BLI_dynstr_appendf(ds, "#define SHADOW_SHADER\n");
+       }
        if ((options & VAR_MAT_HASH) != 0) {
                BLI_dynstr_appendf(ds, "#define USE_ALPHA_HASH\n");
        }
@@ -503,7 +505,9 @@ struct GPUMaterial *EEVEE_material_mesh_get(
        return mat;
 }
 
-struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene, Material *ma, bool use_hashed_alpha)
+struct GPUMaterial *EEVEE_material_mesh_depth_get(
+        struct Scene *scene, Material *ma,
+        bool use_hashed_alpha, bool is_shadow)
 {
        const void *engine = &DRW_engine_viewport_eevee_type;
        int options = VAR_MAT_MESH;
@@ -515,6 +519,9 @@ struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene, Material
                options |= VAR_MAT_CLIP;
        }
 
+       if (is_shadow)
+               options |= VAR_MAT_SHADOW;
+
        GPUMaterial *mat = GPU_material_from_nodetree_find(&ma->gpumaterial, engine, options);
        if (mat) {
                return mat;
@@ -530,7 +537,9 @@ struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene, Material
 
        mat = GPU_material_from_nodetree(
                scene, ma->nodetree, &ma->gpumaterial, engine, options,
-               datatoc_lit_surface_vert_glsl, NULL, frag_str,
+               (is_shadow) ? datatoc_shadow_vert_glsl : datatoc_lit_surface_vert_glsl,
+               (is_shadow) ? datatoc_shadow_geom_glsl : NULL,
+               frag_str,
                defines);
 
        MEM_freeN(frag_str);
@@ -758,7 +767,7 @@ static void material_opaque(
                *gpumat = (use_gpumat) ? EEVEE_material_mesh_get(
                        scene, ma, stl->effects->use_ao, stl->effects->use_bent_normals, false, false) : NULL;
                *gpumat_depth = (use_gpumat) ? EEVEE_material_mesh_depth_get(
-                       scene, ma, (ma->blend_method == MA_BM_HASHED)) : NULL;
+                       scene, ma, (ma->blend_method == MA_BM_HASHED), false) : NULL;
                return;
        }
 
@@ -784,7 +793,7 @@ static void material_opaque(
                 * fail the depth test for shading. */
                if (ELEM(ma->blend_method, MA_BM_CLIP, MA_BM_HASHED)) {
                        *gpumat_depth = EEVEE_material_mesh_depth_get(scene, ma,
-                               (ma->blend_method == MA_BM_HASHED));
+                               (ma->blend_method == MA_BM_HASHED), false);
 
                        *shgrp_depth = DRW_shgroup_material_create(*gpumat_depth, do_cull ? psl->depth_pass_cull : psl->depth_pass);
                        *shgrp_depth_clip = DRW_shgroup_material_create(*gpumat_depth, do_cull ? psl->depth_pass_clip_cull : psl->depth_pass_clip);
@@ -911,6 +920,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_SceneLayerData *sl
        EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
        EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
        const DRWContextState *draw_ctx = DRW_context_state_get();
+       Scene *scene = draw_ctx->scene;
        GHash *material_hash = stl->g_data->material_hash;
 
        IDProperty *ces_mode_ob = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_OBJECT, "");
@@ -974,6 +984,11 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_SceneLayerData *sl
                struct Gwn_Batch **mat_geom = DRW_cache_object_surface_material_get(ob, gpumat_array, materials_len);
                if (mat_geom) {
                        for (int i = 0; i < materials_len; ++i) {
+                               Material *ma = give_current_material(ob, i + 1);
+
+                               if (ma == NULL)
+                                       ma = &defmaterial;
+
                                /* Shading pass */
                                ADD_SHGROUP_CALL(shgrp_array[i], ob, mat_geom[i]);
 
@@ -982,7 +997,16 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_SceneLayerData *sl
                                ADD_SHGROUP_CALL_SAFE(shgrp_depth_clip_array[i], ob, mat_geom[i]);
 
                                /* Shadow Pass */
-                               EEVEE_lights_cache_shcaster_add(sldata, psl, mat_geom[i], ob->obmat);
+                               if (ma->blend_method == MA_BM_SOLID)
+                                       EEVEE_lights_cache_shcaster_add(sldata, psl, mat_geom[i], ob->obmat);
+                               else if (ma->blend_method == MA_BM_HASHED) {
+                                       struct GPUMaterial *gpumat = EEVEE_material_mesh_depth_get(scene, ma, true, true);
+                                       EEVEE_lights_cache_shcaster_material_add(sldata, psl, gpumat, mat_geom[i], ob->obmat, NULL);
+                               }
+                               else if (ma->blend_method == MA_BM_CLIP) {
+                                       struct GPUMaterial *gpumat = EEVEE_material_mesh_depth_get(scene, ma, false, true);
+                                       EEVEE_lights_cache_shcaster_material_add(sldata, psl, gpumat, mat_geom[i], ob->obmat, &ma->alpha_threshold);
+                               }
                        }
                }
        }
@@ -1026,7 +1050,6 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_SceneLayerData *sl
                                                        }
                                                        else {
                                                                if (ma->use_nodes && ma->nodetree) {
-                                                                       Scene *scene = draw_ctx->scene;
                                                                        struct GPUMaterial *gpumat = EEVEE_material_hair_get(scene, ma,
                                                                                stl->effects->use_ao, stl->effects->use_bent_normals);
 
index 5e0d3ea177b83b48c51c1ecf0083edd3ab65fc66..eb420e2a8c735c529f5b3cdf637f7da4160a3ba1 100644 (file)
@@ -76,6 +76,7 @@ enum {
        VAR_MAT_CLIP     = (1 << 8),
        VAR_MAT_HASH     = (1 << 9),
        VAR_MAT_MULT     = (1 << 10),
+       VAR_MAT_SHADOW   = (1 << 11),
 };
 
 typedef struct EEVEE_PassList {
@@ -187,6 +188,7 @@ typedef struct EEVEE_ShadowCascade {
 
 typedef struct EEVEE_ShadowRender {
        float shadowmat[6][4][4]; /* World->Lamp->NDC : used to render the shadow map. 6 frustrum for cubemap shadow */
+       float viewmat[6][4][4]; /* World->Lamp : used to render the shadow map. 6 viewmat for cubemap shadow */
        float position[3];
        float pad;
        int layer;
@@ -453,7 +455,7 @@ struct GPUMaterial *EEVEE_material_world_volume_get(
         struct Scene *scene, struct World *wo, bool use_lights, bool use_volume_shadows, bool is_homogeneous, bool use_color_transmit);
 struct GPUMaterial *EEVEE_material_mesh_get(
         struct Scene *scene, Material *ma, bool use_ao, bool use_bent_normals, bool use_blend, bool use_multiply);
-struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene, Material *ma, bool use_hashed_alpha);
+struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene, Material *ma, bool use_hashed_alpha, bool is_shadow);
 struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma, bool use_ao, bool use_bent_normals);
 void EEVEE_materials_free(void);
 void EEVEE_draw_default_passes(EEVEE_PassList *psl);
@@ -463,6 +465,9 @@ void EEVEE_lights_init(EEVEE_SceneLayerData *sldata);
 void EEVEE_lights_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl);
 void EEVEE_lights_cache_add(EEVEE_SceneLayerData *sldata, struct Object *ob);
 void EEVEE_lights_cache_shcaster_add(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl, struct Gwn_Batch *geom, float (*obmat)[4]);
+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);
 void EEVEE_lights_cache_finish(EEVEE_SceneLayerData *sldata);
 void EEVEE_lights_update(EEVEE_SceneLayerData *sldata);
 void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl);
index 5aac853da002a0e61c213a4979340b4e25771823..ceed99a7b80ef78288b544b7ab7709285dac33fa 100644 (file)
 
 uniform mat4 ProjectionMatrix;
 uniform mat4 ViewMatrixInverse;
-uniform mat4 ViewMatrix;
 uniform vec4 viewvecs[2];
+#ifndef SHADOW_SHADER
+uniform mat4 ViewMatrix;
+#else
+layout(std140) uniform shadow_render_block {
+       mat4 ShadowMatrix[6];
+       mat4 FaceViewMatrix[6];
+       vec4 lampPosition;
+       int layer;
+       float exponent;
+};
+
+flat in int shFace; /* Shadow layer we are rendering to. */
+#define ViewMatrix      FaceViewMatrix[shFace]
+#endif
 
 #define cameraForward   normalize(ViewMatrixInverse[2].xyz)
 #define cameraPos       ViewMatrixInverse[3].xyz
 
+
 /* ------- Structures -------- */
 #ifdef VOLUMETRICS
 
index f921d56e3bc4850f01900fb9befa12a28f2cafbe..cf59b29548a50dbbed47b0f07a1b96d0198f4a89 100644 (file)
@@ -62,6 +62,10 @@ float hashed_alpha_threshold(vec3 co)
 uniform float alphaThreshold;
 #endif
 
+#ifdef SHADOW_SHADER
+out vec4 FragColor;
+#endif
+
 void main()
 {
        /* For now do nothing.
@@ -82,4 +86,9 @@ void main()
                discard;
 #endif
 #endif
+
+#ifdef SHADOW_SHADER
+       float dist = distance(lampPosition.xyz, worldPosition.xyz);
+       FragColor = vec4(dist, 0.0, 0.0, 1.0);
+#endif
 }
index 3fc3c146c66b46c99b8ace27bedcf0a176ed360e..df6fbc4c2fe647a5b08104daabbfe1c454057c87 100644 (file)
@@ -1,6 +1,7 @@
 
 layout(std140) uniform shadow_render_block {
        mat4 ShadowMatrix[6];
+       mat4 FaceViewMatrix[6];
        vec4 lampPosition;
        int layer;
        float exponent;
index afc78c4a8f8900b2a351dfbf8e15718ba41644cc..d9d30c4d9e6d223a7d421354a984413dca084b06 100644 (file)
@@ -1,6 +1,7 @@
 
 layout(std140) uniform shadow_render_block {
        mat4 ShadowMatrix[6];
+       mat4 FaceViewMatrix[6];
        vec4 lampPosition;
        int layer;
        float exponent;
@@ -12,15 +13,36 @@ layout(triangle_strip, max_vertices=3) out;
 in vec4 vPos[];
 flat in int face[];
 
+#ifdef MESH_SHADER
+in vec3 vNor[];
+in vec3 vNor[];
+#endif
+
 out vec3 worldPosition;
+#ifdef MESH_SHADER
+out vec3 viewPosition; /* Required. otherwise generate linking error. */
+out vec3 worldNormal; /* Required. otherwise generate linking error. */
+out vec3 viewNormal; /* Required. otherwise generate linking error. */
+flat out int shFace;
+#else
+int shFace;
+#endif
 
 void main() {
-       int f = face[0];
-       gl_Layer = f;
+       shFace = face[0];
+       gl_Layer = shFace;
 
        for (int v = 0; v < 3; ++v) {
-               gl_Position = ShadowMatrix[f] * vPos[v];
+               gl_Position = ShadowMatrix[shFace] * vPos[v];
                worldPosition = vPos[v].xyz;
+#ifdef MESH_SHADER
+               worldNormal = vNor[v];
+               viewPosition = (FaceViewMatrix[shFace] * vec4(worldPosition, 1.0)).xyz;
+               viewNormal = (FaceViewMatrix[shFace] * vec4(worldNormal, 0.0)).xyz;
+#ifdef ATTRIB
+               pass_attrib(v);
+#endif
+#endif
                EmitVertex();
        }
 
index 40b980b39046bfe2b4eeefe9909f0d1306585387..6782922a2e4a2037c1c4c0479ec9c9fc3ebeaa7d 100644 (file)
@@ -1,6 +1,7 @@
 
 layout(std140) uniform shadow_render_block {
        mat4 ShadowMatrix[6];
+       mat4 FaceViewMatrix[6];
        vec4 lampPosition;
        int layer;
        float exponent;
index 1d456095e02813da7222a2970d045f83fa0262a2..78ccb025ce6afa3f9b243fec31409522311898c9 100644 (file)
@@ -1,6 +1,7 @@
 
 layout(std140) uniform shadow_render_block {
        mat4 ShadowMatrix[6];
+       mat4 FaceViewMatrix[6];
        vec4 lampPosition;
        int layer;
        float exponent;
index 288098ba771dc99c3f1d291ca3b063eebd3082b1..777902ccba8220e8891789e94b02581626ae9b73 100644 (file)
@@ -1,13 +1,29 @@
 
 uniform mat4 ShadowModelMatrix;
+#ifdef MESH_SHADER
+uniform mat3 WorldNormalMatrix;
+#endif
 
 in vec3 pos;
+#ifdef MESH_SHADER
+in vec3 nor;
+#endif
 
 out vec4 vPos;
+#ifdef MESH_SHADER
+out vec3 vNor;
+#endif
 
 flat out int face;
 
 void main() {
        vPos = ShadowModelMatrix * vec4(pos, 1.0);
        face = gl_InstanceID;
-}
\ No newline at end of file
+
+#ifdef MESH_SHADER
+       vNor = WorldNormalMatrix * nor;
+#ifdef ATTRIB
+       pass_attrib(pos);
+#endif
+#endif
+}