[Bf-blender-cvs] [90efcd6df71] blender2.8: Eevee: Shadows: Add cubemap filtering and adaptive sample count.

Clément Foucault noreply at git.blender.org
Sun Sep 10 03:16:56 CEST 2017


Commit: 90efcd6df7189d5c3634add848ef238b45dc6121
Author: Clément Foucault
Date:   Sat Sep 9 21:11:22 2017 +0200
Branches: blender2.8
https://developer.blender.org/rB90efcd6df7189d5c3634add848ef238b45dc6121

Eevee: Shadows: Add cubemap filtering and adaptive sample count.

Filter size is constant in world space and not dependant of shadow resolution.
The filter size is limited to the number of precomputed samples.

===================================================================

M	source/blender/draw/engines/eevee/eevee_lights.c
M	source/blender/draw/engines/eevee/eevee_private.h
M	source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
M	source/blender/draw/engines/eevee/shaders/shadow_copy_frag.glsl
M	source/blender/draw/engines/eevee/shaders/shadow_geom.glsl
M	source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl

===================================================================

diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c
index ca25e6e13b0..396318872aa 100644
--- a/source/blender/draw/engines/eevee/eevee_lights.c
+++ b/source/blender/draw/engines/eevee/eevee_lights.c
@@ -135,6 +135,8 @@ void EEVEE_lights_init(EEVEE_SceneLayerData *sldata)
 		DRW_TEXTURE_FREE_SAFE(sldata->shadow_pool);
 		DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_target);
 		DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_target);
+		DRW_TEXTURE_FREE_SAFE(sldata->shadow_cube_blur);
+		DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_blur);
 
 		linfo->shadow_high_bitdepth = sh_high_bitdepth;
 		linfo->shadow_method = sh_method;
@@ -169,7 +171,7 @@ void EEVEE_lights_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
 		psl->shadow_cube_store_pass = DRW_pass_create("Shadow Storage Pass", DRW_STATE_WRITE_COLOR);
 
 		DRWShadingGroup *grp = DRW_shgroup_create(e_data.shadow_store_cube_sh[linfo->shadow_method], psl->shadow_cube_store_pass);
-		DRW_shgroup_uniform_buffer(grp, "shadowTexture", &sldata->shadow_cube_target);
+		DRW_shgroup_uniform_buffer(grp, "shadowTexture", &sldata->shadow_cube_blur);
 		DRW_shgroup_uniform_block(grp, "shadow_render_block", sldata->shadow_render_ubo);
 		DRW_shgroup_uniform_float(grp, "shadowFilterSize", &linfo->filter_size, 1);
 		DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL);
@@ -902,8 +904,6 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
 		if (led->need_update) {
 			EEVEE_ShadowRender *srd = &linfo->shadow_render_data;
 
-			srd->shadow_samples_ct = 32.0f;
-			srd->shadow_inv_samples_ct = 1.0f / srd->shadow_samples_ct;
 			srd->clip_near = la->clipsta;
 			srd->clip_far = la->clipend;
 			copy_v3_v3(srd->position, ob->obmat[3]);
@@ -924,12 +924,17 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
 			/* Render shadow cube */
 			DRW_draw_pass(psl->shadow_cube_pass);
 
+			/* 0.001f is arbitrary, but it should be relatively small so that filter size is not too big. */
+			float filter_texture_size = la->soft * 0.001f;
+			float filter_pixel_size = ceil(filter_texture_size / linfo->shadow_render_data.cube_texel_size);
+			linfo->filter_size = linfo->shadow_render_data.cube_texel_size * ((filter_pixel_size > 1.0f) ? 1.5f : 0.0f);
+
+			/* TODO: OPTI: Filter all faces in one/two draw call */
 			for (linfo->current_shadow_face = 0;
 			     linfo->current_shadow_face < 6;
 			     linfo->current_shadow_face++)
 			{
 				/* Copy using a small 3x3 box filter */
-				linfo->filter_size = (la->soft > 0.00001f) ? 1.0f : 0.0f;
 				DRW_framebuffer_cubeface_attach(sldata->shadow_store_fb, sldata->shadow_cube_blur, 0, linfo->current_shadow_face, 0);
 				DRW_framebuffer_bind(sldata->shadow_store_fb);
 				DRW_draw_pass(psl->shadow_cube_copy_pass);
@@ -937,7 +942,26 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
 			}
 
 			/* Push it to shadowmap array */
-			linfo->filter_size = la->soft * 0.0005f;
+
+			/* Adjust constants if concentric samples change. */
+			const float max_filter_size = 7.5f;
+			const float previous_box_filter_size = 9.0f; /* Dunno why but that works. */
+			const int max_sample = 256;
+
+			if (filter_pixel_size > 2.0f) {
+				linfo->filter_size = linfo->shadow_render_data.cube_texel_size * max_filter_size * previous_box_filter_size;
+				filter_pixel_size = max_ff(0.0f, filter_pixel_size - 3.0f);
+				/* Compute number of concentric samples. Depends directly on filter size. */
+				float pix_size_sqr = filter_pixel_size * filter_pixel_size;
+				srd->shadow_samples_ct = min_ii(max_sample, 4 + 8 * (int)filter_pixel_size + 4 * (int)(pix_size_sqr));
+			}
+			else {
+				linfo->filter_size = 0.0f;
+				srd->shadow_samples_ct = 4;
+			}
+			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_bind(sldata->shadow_store_fb);
 			DRW_draw_pass(psl->shadow_cube_store_pass);
@@ -958,8 +982,6 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
 		EEVEE_ShadowCascadeData *evscd = (EEVEE_ShadowCascadeData *)led->storage;
 		EEVEE_ShadowRender *srd = &linfo->shadow_render_data;
 
-		srd->shadow_samples_ct = 32.0f;
-		srd->shadow_inv_samples_ct = 1.0f / srd->shadow_samples_ct;
 		srd->clip_near = la->clipsta;
 		srd->clip_far = la->clipend;
 		for (int j = 0; j < la->cascade_count; ++j) {
@@ -973,19 +995,43 @@ void EEVEE_draw_shadows(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
 		/* Render shadow cascades */
 		DRW_draw_pass(psl->shadow_cascade_pass);
 
+		/* TODO: OPTI: Filter all cascade in one/two draw call */
 		for (linfo->current_shadow_cascade = 0;
 		     linfo->current_shadow_cascade < la->cascade_count;
 		     ++linfo->current_shadow_cascade)
 		{
+			/* 0.01f factor to convert to percentage */
+			float filter_texture_size = la->soft * 0.01f / evscd->radius[linfo->current_shadow_cascade];
+			float filter_pixel_size = ceil(linfo->shadow_size * filter_texture_size);
+
 			/* Copy using a small 3x3 box filter */
-			linfo->filter_size = (la->soft > 0.00001f) ? 1.0f : 0.0f;
+			linfo->filter_size = linfo->shadow_render_data.stored_texel_size * ((filter_pixel_size > 1.0f) ? 1.0f : 0.0f);
 			DRW_framebuffer_texture_layer_attach(sldata->shadow_store_fb, sldata->shadow_cascade_blur, 0, linfo->current_shadow_cascade, 0);
 			DRW_framebuffer_bind(sldata->shadow_store_fb);
 			DRW_draw_pass(psl->shadow_cascade_copy_pass);
 			DRW_framebuffer_texture_detach(sldata->shadow_cascade_blur);
 
 			/* Push it to shadowmap array and blur more */
-			linfo->filter_size = la->soft * 0.0005f / (evscd->radius[linfo->current_shadow_cascade] * 0.05f);
+
+			/* Adjust constants if concentric samples change. */
+			const float max_filter_size = 7.5f;
+			const float previous_box_filter_size = 3.2f; /* Arbitrary: less banding */
+			const int max_sample = 256;
+
+			if (filter_pixel_size > 2.0f) {
+				linfo->filter_size = linfo->shadow_render_data.stored_texel_size * max_filter_size * previous_box_filter_size;
+				filter_pixel_size = max_ff(0.0f, filter_pixel_size - 3.0f);
+				/* Compute number of concentric samples. Depends directly on filter size. */
+				float pix_size_sqr = filter_pixel_size * filter_pixel_size;
+				srd->shadow_samples_ct = min_ii(max_sample, 4 + 8 * (int)filter_pixel_size + 4 * (int)(pix_size_sqr));
+			}
+			else {
+				linfo->filter_size = 0.0f;
+				srd->shadow_samples_ct = 4;
+			}
+			srd->shadow_inv_samples_ct = 1.0f / (float)srd->shadow_samples_ct;
+			DRW_uniformbuffer_update(sldata->shadow_render_ubo, &linfo->shadow_render_data);
+
 			int layer = evscd->layer_id + linfo->current_shadow_cascade;
 			DRW_framebuffer_texture_layer_attach(sldata->shadow_store_fb, sldata->shadow_pool, 0, layer, 0);
 			DRW_framebuffer_bind(sldata->shadow_store_fb);
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 72bd04a5958..e5994a0c147 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -237,7 +237,7 @@ typedef struct EEVEE_ShadowRender {
 	float stored_texel_size;
 	float clip_near;
 	float clip_far;
-	float shadow_samples_ct;
+	int shadow_samples_ct;
 	float shadow_inv_samples_ct;
 } EEVEE_ShadowRender;
 
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
index 6ad5b46f683..92d4b5aaed0 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -23,7 +23,7 @@ layout(std140) uniform shadow_render_block {
 	float storedTexelSize;
 	float nearClip;
 	float farClip;
-	float shadowSampleCount;
+	int shadowSampleCount;
 	float shadowInvSampleCount;
 };
 
diff --git a/source/blender/draw/engines/eevee/shaders/shadow_copy_frag.glsl b/source/blender/draw/engines/eevee/shaders/shadow_copy_frag.glsl
index b70d6faa73d..8742bd99def 100644
--- a/source/blender/draw/engines/eevee/shaders/shadow_copy_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/shadow_copy_frag.glsl
@@ -9,7 +9,7 @@ layout(std140) uniform shadow_render_block {
 	float storedTexelSize;
 	float nearClip;
 	float farClip;
-	float shadowSampleCount;
+	int shadowSampleCount;
 	float shadowInvSampleCount;
 };
 
@@ -18,7 +18,7 @@ uniform sampler2DArray shadowTexture;
 uniform int cascadeId;
 #else
 uniform samplerCube shadowTexture;
-uniform vec3 cubeFaceVec[3];
+uniform int faceId;
 #endif
 uniform float shadowFilterSize;
 
@@ -57,7 +57,7 @@ vec4 get_world_distance(vec4 depths, vec3 cos[4])
 {
 	vec4 is_background = step(vec4(1.0), depths);
 	depths = linear_depth(depths);
-	depths += vec4(1e16) * is_background;
+	depths += vec4(1e1) * is_background;
 	cos[0] = normalize(abs(cos[0]));
 	cos[1] = normalize(abs(cos[1]));
 	cos[2] = normalize(abs(cos[2]));
@@ -74,7 +74,7 @@ float get_world_distance(float depth, vec3 cos)
 {
 	float is_background = step(1.0, depth);
 	depth = linear_depth(depth);
-	depth += 1e16 * is_background;
+	depth += 1e1 * is_background;
 	cos = normalize(abs(cos));
 	float cos_vec = max(cos.x, max(cos.y, cos.z));
 	return depth / cos_vec;
@@ -123,25 +123,25 @@ const vec3 minorAxisX[6] = vec3[6](
 const vec3 minorAxisY[6] = vec3[6](
 	vec3(0.0f, -1.0f, 0.0f),
 	vec3(0.0f, -1.0f, 0.0f),
-	vec3(0.0f, 0.0f, -1.0f),
 	vec3(0.0f, 0.0f, 1.0f),
+	vec3(0.0f, 0.0f, -1.0f),
 	vec3(0.0f, -1.0f, 0.0f),
 	vec3(0.0f, -1.0f, 0.0f)
 );
 
 const vec3 majorAxis[6] = vec3[6](
-	vec3(-1.0f, 0.0f, 0.0f),
 	vec3(1.0f, 0.0f, 0.0f),
+	vec3(-1.0f, 0.0f, 0.0f),
 	vec3(0.0f, 1.0f, 0.0f),
 	vec3(0.0f, -1.0f, 0.0f),
-	vec3(0.0f, 0.0f, -1.0f),
-	vec3(0.0f, 0.0f, 1.0f)
+	vec3(0.0f, 0.0f, 1.0f),
+	vec3(0.0f, 0.0f, -1.0f)
 );
 
 vec3 get_texco(vec2 uvs, vec2 ofs)
 {
 	uvs += ofs;
-	return majorAxis[0] + uvs.x * minorAxisX[1] + uvs.y * minorAxisY[2];
+	return majorAxis[faceId] + uvs.x * minorAxisX[faceId] + uvs.y * minorAxisY[faceId];
 }
 #endif
 
@@ -152,13 +15

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list