[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