[Bf-blender-cvs] [f3e8cd97fa8] temp-ssr: Eevee: SSR: Add simple raytracing.

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


Commit: f3e8cd97fa8dd8531f3af1a2ef41531c52fece9a
Author: Clément Foucault
Date:   Tue Jul 18 16:48:24 2017 +0200
Branches: temp-ssr
https://developer.blender.org/rBf3e8cd97fa8dd8531f3af1a2ef41531c52fece9a

Eevee: SSR: Add simple raytracing.

Still imprecise.

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

M	source/blender/draw/CMakeLists.txt
M	source/blender/draw/engines/eevee/eevee_effects.c
M	source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl
A	source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl

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

diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index d27979a458d..3ebdea06093 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -157,6 +157,7 @@ data_to_c_simple(engines/eevee/shaders/bsdf_common_lib.glsl SRC)
 data_to_c_simple(engines/eevee/shaders/irradiance_lib.glsl SRC)
 data_to_c_simple(engines/eevee/shaders/octahedron_lib.glsl SRC)
 data_to_c_simple(engines/eevee/shaders/bsdf_sampling_lib.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/raytrace_lib.glsl SRC)
 data_to_c_simple(engines/eevee/shaders/ltc_lib.glsl SRC)
 data_to_c_simple(engines/eevee/shaders/volumetric_frag.glsl SRC)
 
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c
index 8138ddbbacf..9b069db9469 100644
--- a/source/blender/draw/engines/eevee/eevee_effects.c
+++ b/source/blender/draw/engines/eevee/eevee_effects.c
@@ -82,6 +82,8 @@ static struct {
 	struct GPUShader *ssr_resolve_sh;
 
 	struct GPUTexture *depth_src;
+
+	float pixelprojmat[4][4];
 } e_data = {NULL}; /* Engine data */
 
 extern char datatoc_bsdf_common_lib_glsl[];
@@ -94,6 +96,7 @@ extern char datatoc_effect_dof_vert_glsl[];
 extern char datatoc_effect_dof_geom_glsl[];
 extern char datatoc_effect_dof_frag_glsl[];
 extern char datatoc_lightprobe_lib_glsl[];
+extern char datatoc_raytrace_lib_glsl[];
 extern char datatoc_tonemap_frag_glsl[];
 extern char datatoc_volumetric_frag_glsl[];
 
@@ -171,6 +174,7 @@ void EEVEE_effects_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata)
 		BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
 		BLI_dynstr_append(ds_frag, datatoc_octahedron_lib_glsl);
 		BLI_dynstr_append(ds_frag, datatoc_lightprobe_lib_glsl);
+		BLI_dynstr_append(ds_frag, datatoc_raytrace_lib_glsl);
 		BLI_dynstr_append(ds_frag, datatoc_effect_ssr_frag_glsl);
 		char *ssr_shader_str = BLI_dynstr_get_cstring(ds_frag);
 		BLI_dynstr_free(ds_frag);
@@ -527,6 +531,24 @@ void EEVEE_effects_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata)
 		DRWFboTexture tex_output[2] = {{&txl->ssr_hit_output, (record_two_hit) ? DRW_TEX_RGBA_16 : DRW_TEX_RG_16, 0},
 		                               {&txl->ssr_pdf_output, (record_two_hit) ? DRW_TEX_RG_16 : DRW_TEX_R_16, 0}};
 
+		/* Compute pixel projection matrix */
+		{
+			float uvpix[4][4], ndcuv[4][4], tmp[4][4], winmat[4][4];
+			DRW_viewport_matrix_get(winmat, DRW_MAT_WIN);
+
+			/* NDC to UVs */
+			unit_m4(ndcuv);
+			ndcuv[0][0] = ndcuv[1][1] = ndcuv[3][0] = ndcuv[3][1] = 0.5f;
+
+			/* UVs to pixels */
+			unit_m4(uvpix);
+			uvpix[0][0] = tracing_res[0];
+			uvpix[1][1] = tracing_res[1];
+
+			mul_m4_m4m4(tmp, uvpix, ndcuv);
+			mul_m4_m4m4(e_data.pixelprojmat, tmp, winmat);
+		}
+
 		DRW_framebuffer_init(&fbl->screen_tracing_fb, &draw_engine_eevee_type, tracing_res[0], tracing_res[1], tex_output, 2);
 	}
 	else {
@@ -631,6 +653,8 @@ void EEVEE_effects_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata)
 		DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src);
 		DRW_shgroup_uniform_buffer(grp, "normalBuffer", &txl->ssr_normal_input);
 		DRW_shgroup_uniform_buffer(grp, "specRoughBuffer", &txl->ssr_specrough_input);
+		DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
+		DRW_shgroup_uniform_mat4(grp, "PixelProjMatrix", (float *)&e_data.pixelprojmat);
 		DRW_shgroup_call_add(grp, quad, NULL);
 
 		psl->ssr_resolve = DRW_pass_create("SSR Resolve", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE);
@@ -852,13 +876,13 @@ void EEVEE_effects_do_ssr(EEVEE_SceneLayerData *UNUSED(sldata), EEVEE_Data *veda
 	if ((effects->enabled_effects & EFFECT_SSR) != 0) {
 		DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
 
-		e_data.depth_src = dtxl->depth;
-
 		/* Raytrace at halfres. */
+		e_data.depth_src = stl->g_data->minmaxz;
 		DRW_framebuffer_bind(fbl->screen_tracing_fb);
 		DRW_draw_pass(psl->ssr_raytrace);
 
 		/* Resolve at fullres */
+		e_data.depth_src = dtxl->depth;
 		DRW_framebuffer_texture_detach(dtxl->depth);
 		DRW_framebuffer_texture_detach(txl->ssr_normal_input);
 		DRW_framebuffer_texture_detach(txl->ssr_specrough_input);
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 63f87da1468..62644c0ac74 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl
@@ -1,4 +1,9 @@
 
+vec3 generate_ray(vec3 V, vec3 N)
+{
+	return -reflect(-V, N);
+}
+
 #ifdef STEP_RAYTRACE
 
 uniform sampler2D depthBuffer;
@@ -11,13 +16,46 @@ layout(location = 1) out vec4 pdfData;
 void main()
 {
 	ivec2 fullres_texel = ivec2(gl_FragCoord.xy) * 2;
-	float depth = texelFetch(depthBuffer, fullres_texel, 0).r;
+	ivec2 halfres_texel = ivec2(gl_FragCoord.xy);
+	float depth = texelFetch(depthBuffer, halfres_texel, 0).r;
 
 	/* Early discard */
 	if (depth == 1.0)
 		discard;
 
-	hitData = vec4(0.2);
+	vec2 uvs = gl_FragCoord.xy / vec2(textureSize(depthBuffer, 0));
+
+	/* Using view space */
+	vec3 viewPosition = get_view_space_from_depth(uvs, depth);
+	vec3 V = viewCameraVec;
+	vec3 N = normal_decode(texelFetch(normalBuffer, fullres_texel, 0).rg, V);
+
+	/* Retrieve pixel data */
+	vec4 speccol_roughness = texelFetch(specroughBuffer, fullres_texel, 0).rgba;
+	float roughness = speccol_roughness.a;
+	float roughnessSquared = roughness * roughness;
+
+	/* Generate Ray */
+	vec3 R = generate_ray(V, N);
+
+	/* Search for the planar reflection affecting this pixel */
+	/* If no planar is found, fallback to screen space */
+
+	/* Raycast over planar reflection */
+	/* Potentially lots of time waisted here for pixels
+	 * that does not have planar reflections. TODO Profile it. */
+	/* TODO: Idea, rasterize boxes around planar
+	 * reflection volumes (frontface culling to avoid overdraw)
+	 * and do the raycasting, discard pixel that are not in influence.
+	 * Add stencil test to discard the main SSR.
+	 * Cons: - Potentially raytrace multiple times
+	 *         if Planar Influence overlaps. */
+	//float hit_dist = raycast(depthBuffer, W, R);
+
+	/* Raycast over screen */
+	float hit = raycast(depthBuffer, viewPosition, R);
+
+	hitData = vec4(hit, hit, hit, 1.0);
 	pdfData = vec4(0.5);
 }
 
@@ -32,6 +70,8 @@ uniform sampler2D pdfBuffer;
 
 uniform int probe_count;
 
+uniform mat4 ViewProjectionMatrix;
+
 out vec4 fragColor;
 
 void fallback_cubemap(vec3 N, vec3 V, vec3 W, float roughness, float roughnessSquared, inout vec4 spec_accum)
@@ -70,6 +110,7 @@ void main()
 	if (depth == 1.0)
 		discard;
 
+	/* Using world space */
 	vec3 worldPosition = get_world_space_from_depth(uvs, depth);
 	vec3 V = cameraVec;
 	vec3 N = mat3(ViewMatrixInverse) * normal_decode(texelFetch(normalBuffer, fullres_texel, 0).rg, V);
@@ -81,12 +122,27 @@ void main()
 
 	/* Resolve SSR and compute contribution */
 
+	/* We generate the same rays that has been genearted in the raycast step.
+	 * But we add this ray from our resolve pixel position, increassing accuracy. */
+	vec3 R = generate_ray(-V, N);
+	float ray_length = texelFetch(hitBuffer, halfres_texel, 0).r;
+
+	if (ray_length != -1.0) {
+		vec3 hit_pos = worldPosition + R * ray_length;
+		vec4 hit_co = ViewProjectionMatrix * vec4(hit_pos, 1.0);
+		spec_accum.xy = (hit_co.xy / hit_co.w) * 0.5 + 0.5;
+		spec_accum.xyz = vec3(mod(dot(floor(hit_pos.xyz * 5.0), vec3(1.0)), 2.0));
+		spec_accum.a = 1.0;
+	}
+
 	/* If SSR contribution is not 1.0, blend with cubemaps */
 	if (spec_accum.a < 1.0) {
 		fallback_cubemap(N, V, worldPosition, roughness, roughnessSquared, spec_accum);
 	}
 
 	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
diff --git a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl
new file mode 100644
index 00000000000..6f6ced3c668
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl
@@ -0,0 +1,162 @@
+/* Based on work from Morgan McGuire and Michael Mara at Williams College 2014
+ * Released as open source under the BSD 2-Clause License
+ * http://opensource.org/licenses/BSD-2-Clause
+ * http://casual-effects.blogspot.fr/2014/08/screen-space-ray-tracing.html */
+
+#define MAX_STEP 256
+
+uniform mat4 PixelProjMatrix; /* View > NDC > Texel : maps view coords to texel coord */
+
+void swapIfBigger(inout float a, inout float b)
+{
+	if (a > b) {
+		float temp = a;
+		a = b;
+		b = temp;
+	}
+}
+
+/* Return the length of the ray if there is a hit, and -1.0 if not hit occured */
+float raycast(sampler2D depth_texture, vec3 ray_origin, vec3 ray_dir)
+{
+	float near = get_view_z_from_depth(0.0); /* TODO optimize */
+
+	/* Clip ray to a near plane in 3D */
+	float ray_length = 1e16;
+	if ((ray_origin.z + ray_dir.z * ray_length) > near)
+		ray_length = (near - ray_origin.z) / ray_dir.z;
+
+	vec3 ray_end = ray_dir * ray_length + ray_origin;
+
+	/* Project into screen space */
+	vec4 H0 = PixelProjMatrix * vec4(ray_origin, 1.0);
+	vec4 H1 = PixelProjMatrix * vec4(ray_end, 1.0);
+
+	/* There are a lot of divisions by w that can be turned into multiplications
+	* at some minor precision loss...and we need to interpolate these 1/w values
+	* anyway. */
+	float k0 = 1.0 / H0.w;
+	float k1 = 1.0 / H1.w;
+
+	/* Switch the original points to values that interpolate linearly in 2D */
+	vec3 Q0 = ray_origin * k0;
+	vec3 Q1 = ray_end * k1;
+
+	/* Screen-space endpoints */
+	vec2 P0 = H0.xy * k0;
+	vec2 P1 = H1.xy * k1;
+
+	/* [Optional clipping to frustum sides here] */
+
+	/* Initialize to off screen */
+	vec2 hitpixel = vec2(-1.0, -1.0);
+
+	/* If the line is degenerate, make it cover at least one pixel
+	 * to not have to handle zero-pixel extent as a special case later */
+	P1 += vec2((distance_squared(P0, P1) < 0.0001) ? 0.01 : 0.0);
+
+	vec2 delta = P1 - P0;
+
+	/* Permute so that the primary iteration is in x to reduce large branches later.
+	 * After this, "x" is the primary iteration direction and "y" is the secondary one
+	 * If it is a more-vertical line, create

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list