[Bf-blender-cvs] [779c950098e] blender2.8: Eevee: Ambient Occlusion: Initial implementation.

Clément Foucault noreply at git.blender.org
Thu Jun 22 04:01:11 CEST 2017


Commit: 779c950098e46a34f89f1705be61b4b24be11568
Author: Clément Foucault
Date:   Thu Jun 22 03:10:39 2017 +0200
Branches: blender2.8
https://developer.blender.org/rB779c950098e46a34f89f1705be61b4b24be11568

Eevee: Ambient Occlusion: Initial implementation.

Implement GTAO (Ground Truth Ambient Occlusion) which is a special case of Horizon Based Ambient Occlusion that is more physically accurate.
Also add a bent normal option to sample indirect irradiance (diffuse lighting) with the least occluded direction.

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

M	source/blender/draw/CMakeLists.txt
M	source/blender/draw/engines/eevee/eevee_effects.c
M	source/blender/draw/engines/eevee/eevee_materials.c
M	source/blender/draw/engines/eevee/eevee_private.h
A	source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
M	source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
M	source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
M	source/blender/gpu/shaders/gpu_shader_material.glsl

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

diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 7c4b5428d75..eb3a016f295 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -118,6 +118,7 @@ data_to_c_simple(engines/clay/shaders/ssao_groundtruth.glsl SRC)
 data_to_c_simple(engines/eevee/shaders/default_frag.glsl SRC)
 data_to_c_simple(engines/eevee/shaders/default_world_frag.glsl SRC)
 data_to_c_simple(engines/eevee/shaders/background_vert.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/ambient_occlusion_lib.glsl SRC)
 data_to_c_simple(engines/eevee/shaders/effect_minmaxz_frag.glsl SRC)
 data_to_c_simple(engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl SRC)
 data_to_c_simple(engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl SRC)
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c
index e7fa51ad929..0aa72f6bc2c 100644
--- a/source/blender/draw/engines/eevee/eevee_effects.c
+++ b/source/blender/draw/engines/eevee/eevee_effects.c
@@ -386,6 +386,14 @@ void EEVEE_effects_init(EEVEE_Data *vedata)
 		                    (int)viewport_size[0], (int)viewport_size[1],
 		                    &tex, 1);
 	}
+
+	{
+		/* Ambient Occlusion*/
+		stl->effects->ao_dist = BKE_collection_engine_property_value_get_float(props, "gtao_distance");
+		stl->effects->ao_samples = BKE_collection_engine_property_value_get_int(props, "gtao_samples");
+		stl->effects->ao_factor = 1.0f - BKE_collection_engine_property_value_get_float(props, "gtao_factor");
+	}
+
 	/* MinMax Pyramid */
 	/* TODO reduce precision */
 	DRWFboTexture tex = {&stl->g_data->minmaxz, DRW_TEX_RG_32, DRW_TEX_MIPMAP | DRW_TEX_TEMP};
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index 09c30ff5a69..1043915c894 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -75,6 +75,7 @@ static struct {
 	float viewvecs[2][4];
 } e_data = {NULL}; /* Engine data */
 
+extern char datatoc_ambient_occlusion_lib_glsl[];
 extern char datatoc_prepass_frag_glsl[];
 extern char datatoc_prepass_vert_glsl[];
 extern char datatoc_default_frag_glsl[];
@@ -215,6 +216,13 @@ static void add_standard_uniforms(DRWShadingGroup *shgrp, EEVEE_SceneLayerData *
 	DRW_shgroup_uniform_buffer(shgrp, "irradianceGrid", &sldata->irradiance_pool);
 	DRW_shgroup_uniform_buffer(shgrp, "shadowCubes", &sldata->shadow_depth_cube_pool);
 	DRW_shgroup_uniform_buffer(shgrp, "shadowCascades", &sldata->shadow_depth_cascade_pool);
+	if (vedata->stl->effects->use_ao) {
+		DRW_shgroup_uniform_vec4(shgrp, "viewvecs[0]", (float *)e_data.viewvecs, 3);
+		DRW_shgroup_uniform_buffer(shgrp, "minMaxDepthTex", &vedata->stl->g_data->minmaxz);
+		DRW_shgroup_uniform_float(shgrp, "aoDistance", &vedata->stl->effects->ao_dist, 1);
+		DRW_shgroup_uniform_float(shgrp, "aoSamples", &vedata->stl->effects->ao_samples, 1);
+		DRW_shgroup_uniform_float(shgrp, "aoFactor", &vedata->stl->effects->ao_factor, 1);
+	}
 }
 
 static void create_default_shader(int options)
@@ -232,6 +240,7 @@ static void create_default_shader(int options)
 	MEM_freeN(defines);
 	MEM_freeN(frag_str);
 }
+
 void EEVEE_materials_init(void)
 {
 	if (!e_data.frag_shader_lib) {
@@ -240,6 +249,7 @@ void EEVEE_materials_init(void)
 		/* Shaders */
 		DynStr *ds_frag = BLI_dynstr_new();
 		BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
+		BLI_dynstr_append(ds_frag, datatoc_ambient_occlusion_lib_glsl);
 		BLI_dynstr_append(ds_frag, datatoc_octahedron_lib_glsl);
 		BLI_dynstr_append(ds_frag, datatoc_irradiance_lib_glsl);
 		BLI_dynstr_append(ds_frag, datatoc_ltc_lib_glsl);
@@ -287,14 +297,57 @@ void EEVEE_materials_init(void)
 
 		for (int i = 0; i < 64 * 64; i++) {
 			texels_layer[i][0] = blue_noise[i][0];
-			texels_layer[i][1] = blue_noise[i][1];
+			texels_layer[i][1] = blue_noise[i][1] * 0.5 + 0.5;
 			texels_layer[i][2] = blue_noise[i][2];
 			texels_layer[i][3] = blue_noise[i][3];
 		}
 
-		e_data.util_tex = DRW_texture_create_2D_array(64, 64, layers, DRW_TEX_RGBA_16, DRW_TEX_FILTER, (float *)texels);
+		e_data.util_tex = DRW_texture_create_2D_array(64, 64, layers, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_WRAP, (float *)texels);
 		MEM_freeN(texels);
 	}
+
+	{
+		/* Update viewvecs */
+		const bool is_persp = DRW_viewport_is_persp_get();
+		float invproj[4][4], winmat[4][4];
+		/* view vectors for the corners of the view frustum.
+		 * Can be used to recreate the world space position easily */
+		float viewvecs[3][4] = {
+		    {-1.0f, -1.0f, -1.0f, 1.0f},
+		    {1.0f, -1.0f, -1.0f, 1.0f},
+		    {-1.0f, 1.0f, -1.0f, 1.0f}
+		};
+
+		/* invert the view matrix */
+		DRW_viewport_matrix_get(winmat, DRW_MAT_WIN);
+		invert_m4_m4(invproj, winmat);
+
+		/* convert the view vectors to view space */
+		for (int i = 0; i < 3; i++) {
+			mul_m4_v4(invproj, viewvecs[i]);
+			/* normalized trick see:
+			 * http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
+			mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]);
+			if (is_persp)
+				mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]);
+			viewvecs[i][3] = 1.0;
+		}
+
+		copy_v4_v4(e_data.viewvecs[0], viewvecs[0]);
+		copy_v4_v4(e_data.viewvecs[1], viewvecs[1]);
+
+		/* we need to store the differences */
+		e_data.viewvecs[1][0] -= viewvecs[0][0];
+		e_data.viewvecs[1][1] = viewvecs[2][1] - viewvecs[0][1];
+
+		/* calculate a depth offset as well */
+		if (!is_persp) {
+			float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f};
+			mul_m4_v4(invproj, vec_far);
+			mul_v3_fl(vec_far, 1.0f / vec_far[3]);
+			e_data.viewvecs[1][2] = vec_far[2] - viewvecs[0][2];
+		}
+	}
 }
 
 struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, World *wo)
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index bd9e1bf9e89..2f96da1cf4f 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -273,6 +273,10 @@ enum {
 typedef struct EEVEE_EffectsInfo {
 	int enabled_effects;
 
+	/* Ambient Occlusion */
+	bool use_ao, use_bent_normals;
+	float ao_dist, ao_samples, ao_factor;
+
 	/* Motion Blur */
 	float current_ndc_to_world[4][4];
 	float past_world_to_ndc[4][4];
@@ -402,7 +406,6 @@ EEVEE_ObjectEngineData *EEVEE_object_data_get(Object *ob);
 EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_get(Object *ob);
 EEVEE_LampEngineData *EEVEE_lamp_data_get(Object *ob);
 
-
 /* eevee_materials.c */
 void EEVEE_materials_init(void);
 void EEVEE_materials_cache_init(EEVEE_Data *vedata);
diff --git a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
new file mode 100644
index 00000000000..a3a1d989475
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
@@ -0,0 +1,153 @@
+
+/* Based on Practical Realtime Strategies for Accurate Indirect Occlusion
+ * http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pdf
+ * http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pptx */
+
+#define MAX_PHI_STEP 32
+/* NOTICE : this is multiplied by 2 */
+#define MAX_THETA_STEP 6.0
+
+uniform sampler2D minMaxDepthTex;
+uniform float aoDistance;
+uniform float aoSamples;
+uniform float aoFactor;
+
+float sample_depth(vec2 co, int level)
+{
+	return textureLod(minMaxDepthTex, co, float(level)).g;
+}
+
+float get_max_horizon(vec2 co, vec3 x, float h, float step)
+{
+	if (co.x > 1.0 || co.x < 0.0 || co.y > 1.0 || co.y < 0.0)
+		return h;
+
+	float depth = sample_depth(co, int(step));
+
+	/* Background case */
+	if (depth == 1.0)
+		return h;
+
+	vec3 s = get_view_space_from_depth(co, depth); /* s View coordinate */
+	vec3 omega_s = s - x;
+	float len = length(omega_s);
+
+	float max_h = max(h, omega_s.z / len);
+	/* Blend weight after half the aoDistance to fade artifacts */
+	float blend = saturate((1.0 - len / aoDistance) * 2.0);
+
+	return mix(h, max_h, blend);
+}
+
+void gtao(vec3 normal, vec3 position, vec2 noise, out float visibility
+#ifdef USE_BENT_NORMAL
+	, out vec3 bent_normal
+#endif
+	)
+{
+	vec2 screenres = vec2(textureSize(minMaxDepthTex, 0)) * 2.0;
+	vec2 pixel_size = vec2(1.0) / screenres.xy;
+
+	/* Renaming */
+	vec2 x_ = gl_FragCoord.xy * pixel_size; /* x^ Screen coordinate */
+	vec3 x = position; /* x view space coordinate */
+
+	/* NOTE : We set up integration domain around the camera forward axis
+	 * and not the view vector like in the paper.
+	 * This allows us to save a lot of dot products. */
+	/* omega_o = vec3(0.0, 0.0, 1.0); */
+
+	vec2 pixel_ratio = vec2(screenres.y / screenres.x, 1.0);
+	float pixel_len = length(pixel_size);
+	float homcco = ProjectionMatrix[2][3] * position.z + ProjectionMatrix[3][3];
+	float max_dist = aoDistance / homcco; /* Search distance */
+
+	/* Integral over PI */
+	visibility = 0.0;
+#ifdef USE_BENT_NORMAL
+	bent_normal = vec3(0.0);
+#endif
+	for (float i = 0.0; i < aoSamples && i < MAX_PHI_STEP; i++) {
+		float phi = M_PI * ((noise.r + i) / aoSamples);
+
+		/* Rotate with random direction to get jittered result. */
+		vec2 t_phi = vec2(cos(phi), sin(phi)); /* Screen space direction */
+
+		/* Search maximum horizon angles h1 and h2 */
+		float h1 = -1.0, h2 = -1.0; /* init at cos(pi) */
+		float ofs = 1.5 * pixel_len;
+		for (float j = 0.0; ofs < max_dist && j < MAX_THETA_STEP; j += 0.5) {
+			ofs += ofs; /* Step size is doubled each iteration */
+
+			vec2 s_ = t_phi * ofs * noise.g * pixel_ratio; /* s^ Screen coordinate */
+			vec2 co;
+
+			co = x_ + s_;
+			h1 = get_max_horizon(co, x, h1, j);
+
+			co = x_ - s_;
+			h2 = get_max_horizon(co, x, h2, j);
+		}
+
+		/* (Slide 54) */
+		h1 = -acos(h1);
+		h2 = acos(h2);
+
+		/* Projecting Normal to Plane P defined by t_phi and omega_o */
+		vec3 h = vec3(t_phi.y, -t_phi.x, 0.0); /* Normal vector to Integration plane */
+		vec3 t = vec3(-t_phi, 0.0);
+		vec3 n_proj = normal - h * dot(h, normal);
+		float n_proj_len = max(1e-16, length(n_proj));
+
+		/* Clampin

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list