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. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to