[Bf-blender-cvs] [9857ee6cf17] temp-ssr: Eevee: SSR: Add per pixel resolve of multiple rays.

Clément Foucault noreply at git.blender.org
Mon Jul 24 15:25:16 CEST 2017


Commit: 9857ee6cf171ff21a9fcfbb8d42a2181a963f127
Author: Clément Foucault
Date:   Wed Jul 19 19:21:16 2017 +0200
Branches: temp-ssr
https://developer.blender.org/rB9857ee6cf171ff21a9fcfbb8d42a2181a963f127

Eevee: SSR: Add per pixel resolve of multiple rays.

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

M	source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
M	source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl
M	source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl

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

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 4bae519b52b..059f0598156 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -29,7 +29,7 @@ flat in int shFace; /* Shadow layer we are rendering to. */
 #define cameraForward   normalize(ViewMatrixInverse[2].xyz)
 #define cameraPos       ViewMatrixInverse[3].xyz
 #define cameraVec      ((ProjectionMatrix[3][3] == 0.0) ? normalize(cameraPos - worldPosition) : cameraForward)
-#define viewCameraVec  ((ProjectionMatrix[3][3] == 0.0) ? normalize(viewPosition) : vec3(0.0, 0.0, -1.0))
+#define viewCameraVec  ((ProjectionMatrix[3][3] == 0.0) ? normalize(-viewPosition) : vec3(0.0, 0.0, 1.0))
 
 /* ------- Structures -------- */
 struct LightData {
@@ -95,6 +95,10 @@ struct ShadowCascadeData {
 vec3 mul(mat3 m, vec3 v) { return m * v; }
 mat3 mul(mat3 m1, mat3 m2) { return m1 * m2; }
 vec3 transform_point(mat4 m, vec3 v) { return (m * vec4(v, 1.0)).xyz; }
+vec3 project_point(mat4 m, vec3 v) {
+	vec4 tmp = m * vec4(v, 1.0);
+	return tmp.xyz / tmp.w;
+}
 
 float min_v3(vec3 v) { return min(v.x, min(v.y, v.z)); }
 float max_v2(vec2 v) { return max(v.x, v.y); }
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl
index 5caf3c17e82..c7daea77782 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl
@@ -46,7 +46,7 @@ float pdf_hemisphere()
 	return 0.5 * M_1_PI;
 }
 
-vec3 sample_ggx(vec3 rand, float a2, vec3 N, vec3 T, vec3 B)
+vec3 sample_ggx(vec3 rand, float a2)
 {
 	/* Theta is the aperture angle of the cone */
 	float z = sqrt( (1.0 - rand.x) / ( 1.0 + a2 * rand.x - rand.x ) ); /* cos theta */
@@ -55,7 +55,13 @@ vec3 sample_ggx(vec3 rand, float a2, vec3 N, vec3 T, vec3 B)
 	float y = r * rand.z;
 
 	/* Microfacet Normal */
-	vec3 Ht = vec3(x, y, z);
+	return vec3(x, y, z);
+}
+
+vec3 sample_ggx(vec3 rand, float a2, vec3 N, vec3 T, vec3 B, out float NH)
+{
+	vec3 Ht = sample_ggx(rand, a2);
+	NH = Ht.z;
 	return tangent_to_world(Ht, N, T, B);
 }
 
@@ -63,7 +69,8 @@ vec3 sample_ggx(vec3 rand, float a2, vec3 N, vec3 T, vec3 B)
 vec3 sample_ggx(float nsample, float a2, vec3 N, vec3 T, vec3 B)
 {
 	vec3 Xi = hammersley_3d(nsample);
-	return sample_ggx(Xi, a2, N, T, B);
+	vec3 Ht = sample_ggx(Xi, a2);
+	return tangent_to_world(Ht, N, T, B);
 }
 
 vec3 sample_hemisphere(float nsample, vec3 N, vec3 T, vec3 B)
diff --git a/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl
index 9e3d3fc64bb..3c0b1952e7a 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl
@@ -4,13 +4,15 @@
 uniform sampler2DArray utilTex;
 #endif /* UTIL_TEX */
 
-vec3 generate_ray(ivec2 pix, vec3 V, vec3 N, float roughnessSquared)
+vec3 generate_ray(ivec2 pix, vec3 V, vec3 N, float roughnessSquared, out float pdf)
 {
+	float NH;
 	vec3 T, B;
 	make_orthonormal_basis(N, T, B); /* Generate tangent space */
 	vec3 rand = texelFetch(utilTex, ivec3(pix % LUT_SIZE, 2), 0).rba;
-	vec3 H = sample_ggx(rand, roughnessSquared, N, T, B); /* Microfacet normal */
-	return -reflect(-V, H);
+	vec3 H = sample_ggx(rand, roughnessSquared, N, T, B, NH); /* Microfacet normal */
+	pdf = max(32e32, pdf_ggx_reflect(NH, roughnessSquared)); /* Theoretical limit of 10bit float (not in practice?) */
+	return reflect(-V, H);
 }
 
 #ifdef STEP_RAYTRACE
@@ -45,7 +47,8 @@ void main()
 	float roughnessSquared = roughness * roughness;
 
 	/* Generate Ray */
-	vec3 R = generate_ray(halfres_texel, V, N, roughnessSquared);
+	float pdf;
+	vec3 R = generate_ray(halfres_texel, V, N, roughnessSquared, pdf);
 
 	/* Search for the planar reflection affecting this pixel */
 	/* If no planar is found, fallback to screen space */
@@ -62,10 +65,13 @@ void main()
 	//float hit_dist = raycast(depthBuffer, W, R);
 
 	/* Raycast over screen */
-	float hit = raycast(depthBuffer, viewPosition, R);
+	float hit_dist = raycast(depthBuffer, viewPosition, R);
 
-	hitData = vec4(hit, hit, hit, 1.0);
-	pdfData = vec4(0.5);
+	/* TODO Check if has hit a backface */
+
+	vec2 hit_co = project_point(ProjectionMatrix, viewPosition + R * hit_dist).xy * 0.5 + 0.5;
+	hitData = hit_co.xyxy;
+	pdfData = vec4(pdf) * step(-0.1, hit_dist);
 }
 
 #else /* STEP_RESOLVE */
@@ -144,8 +150,7 @@ vec2 get_reprojected_reflection(vec3 hit, vec3 pos, vec3 N)
 	/* Reproject */
 	// vec3 hit_reprojected = find_reflection_incident_point(cameraPos, hit, pos, N);
 
-	vec4 hit_co = PastViewProjectionMatrix * vec4(hit, 1.0);
-	return (hit_co.xy / hit_co.w) * 0.5 + 0.5;
+	return project_point(PastViewProjectionMatrix, hit).xy * 0.5 + 0.5;
 }
 
 float screen_border_mask(vec2 past_hit_co, vec3 hit)
@@ -165,6 +170,8 @@ float screen_border_mask(vec2 past_hit_co, vec3 hit)
 	return screenfade;
 }
 
+#define NUM_NEIGHBORS 4
+
 void main()
 {
 	ivec2 halfres_texel = ivec2(gl_FragCoord.xy / 2.0);
@@ -178,9 +185,10 @@ void main()
 		discard;
 
 	/* Using world space */
-	vec3 worldPosition = get_world_space_from_depth(uvs, depth);
+	vec3 viewPosition = get_view_space_from_depth(uvs, depth); /* Needed for viewCameraVec */
+	vec3 worldPosition = transform_point(ViewMatrixInverse, viewPosition);
 	vec3 V = cameraVec;
-	vec3 N = mat3(ViewMatrixInverse) * normal_decode(texelFetch(normalBuffer, fullres_texel, 0).rg, V);
+	vec3 N = mat3(ViewMatrixInverse) * normal_decode(texelFetch(normalBuffer, fullres_texel, 0).rg, viewCameraVec);
 	vec4 speccol_roughness = texelFetch(specroughBuffer, fullres_texel, 0).rgba;
 	float roughness = speccol_roughness.a;
 	float roughnessSquared = roughness * roughness;
@@ -191,14 +199,40 @@ void main()
 
 	/* We generate the same rays that has been generated in the raycast step.
 	 * But we add this ray from our resolve pixel position, increassing accuracy. */
-	vec3 R = generate_ray(halfres_texel, -V, N, roughnessSquared);
-	float ray_length = texelFetch(hitBuffer, halfres_texel, 0).r;
-
-	if (ray_length != -1.0) {
-		vec3 hit_pos = worldPosition + R * ray_length;
-		vec2 ref_uvs = get_reprojected_reflection(hit_pos, worldPosition, N);
-		spec_accum.a = screen_border_mask(ref_uvs, hit_pos);
-		spec_accum.xyz = textureLod(colorBuffer, ref_uvs, 0.0).rgb * spec_accum.a;
+	vec3 ssr_accum = vec3(0.0);
+	float weight_acc = 0.0;
+	float mask = 0.0;
+	const ivec2 neighbors[7] = ivec2[7](ivec2(0, 0), ivec2(2, 1), ivec2(-2, 1), ivec2(0, -2), ivec2(-2, -1), ivec2(2, -1), ivec2(0, 2));
+	int invert_neighbor = ((((fullres_texel.x & 0x1) + (fullres_texel.y & 0x1)) & 0x1) == 0) ? 1 : -1;
+	for (int i = 0; i < NUM_NEIGHBORS; i++) {
+		ivec2 target_texel = halfres_texel + neighbors[i] * invert_neighbor;
+
+		float pdf = texelFetch(pdfBuffer, target_texel, 0).r;
+
+		/* Check if there was a hit */
+		if (pdf != 0.0) {
+			vec2 hit_co = texelFetch(hitBuffer, target_texel, 0).rg;
+
+			/* Reconstruct ray */
+			float hit_depth = textureLod(depthBuffer, hit_co, 0.0).r;
+			vec3 hit_pos = get_world_space_from_depth(hit_co, hit_depth);
+
+			/* Find hit position in previous frame */
+			vec2 ref_uvs = get_reprojected_reflection(hit_pos, worldPosition, N);
+
+			/* Evaluate BSDF */
+			vec3 L = normalize(hit_pos - worldPosition);
+			float bsdf = bsdf_ggx(N, L, V, max(1e-3, roughness));
+
+			float weight = bsdf / max(1e-8, pdf);
+			mask += screen_border_mask(ref_uvs, hit_pos);
+			ssr_accum += textureLod(colorBuffer, ref_uvs, 0.0).rgb * weight;
+			weight_acc += weight;
+		}
+	}
+
+	if (weight_acc > 0.0) {
+		accumulate_light(ssr_accum / weight_acc, mask / float(NUM_NEIGHBORS), spec_accum);
 	}
 
 	/* If SSR contribution is not 1.0, blend with cubemaps */
@@ -208,7 +242,6 @@ void main()
 
 	fragColor = vec4(spec_accum.rgb * speccol_roughness.rgb, 1.0);
 	// fragColor = vec4(texelFetch(hitBuffer, halfres_texel, 0).rgb, 1.0);
-	// fragColor = vec4(R, 1.0);
 }
 
 #endif




More information about the Bf-blender-cvs mailing list