diff options
Diffstat (limited to 'source/blender/draw/engines/eevee/shaders')
5 files changed, 86 insertions, 65 deletions
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 c190ca0e245..7ce95a4aff2 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl @@ -1,32 +1,14 @@ +/** + * Sampling distribution routines for Monte-carlo integration. + **/ + #pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) #pragma BLENDER_REQUIRE(bsdf_common_lib.glsl) -uniform sampler1D texHammersley; - -vec3 tangent_to_world(vec3 vector, vec3 N, vec3 T, vec3 B) -{ - return T * vector.x + B * vector.y + N * vector.z; -} - -vec3 world_to_tangent(vec3 vector, vec3 N, vec3 T, vec3 B) -{ - return vec3(dot(T, vector), dot(B, vector), dot(N, vector)); -} - -#ifdef HAMMERSLEY_SIZE -vec3 hammersley_3d(float i, float invsamplenbr) -{ - vec3 Xi; /* Theta, cos(Phi), sin(Phi) */ - - Xi.x = i * invsamplenbr; - Xi.yz = texelFetch(texHammersley, int(i), 0).rg; - - return Xi; -} -#endif - -/* -------------- BSDFS -------------- */ +/* -------------------------------------------------------------------- */ +/** \name Microfacet GGX distribution + * \{ */ #define USE_VISIBLE_NORMAL 1 @@ -89,12 +71,18 @@ vec3 sample_ggx(vec3 rand, float alpha, vec3 V, vec3 N, vec3 T, vec3 B, out floa return tangent_to_world(Ht, N, T, B); } -float pdf_hemisphere() +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Uniform Hemisphere + * \{ */ + +float pdf_uniform_hemisphere() { return 0.5 * M_1_PI; } -vec3 sample_hemisphere(vec3 rand) +vec3 sample_uniform_hemisphere(vec3 rand) { float z = rand.x; /* cos theta */ float r = sqrt(max(0.0, 1.0 - z * z)); /* sin theta */ @@ -103,45 +91,33 @@ vec3 sample_hemisphere(vec3 rand) return vec3(x, y, z); } -vec3 sample_hemisphere(vec3 rand, vec3 N, vec3 T, vec3 B, out float pdf) +vec3 sample_uniform_hemisphere(vec3 rand, vec3 N, vec3 T, vec3 B, out float pdf) { - vec3 Ht = sample_hemisphere(rand); - pdf = pdf_hemisphere(); + vec3 Ht = sample_uniform_hemisphere(rand); + pdf = pdf_uniform_hemisphere(); return tangent_to_world(Ht, N, T, B); } -#ifdef HAMMERSLEY_SIZE -vec3 sample_ggx(float nsample, - float inv_sample_count, - float alpha, - vec3 V, - vec3 N, - vec3 T, - vec3 B, - out float pdf) -{ - vec3 Xi = hammersley_3d(nsample, inv_sample_count); - return sample_ggx(Xi, alpha, V, N, T, B, pdf); -} +/** \} */ -vec3 sample_hemisphere( - float nsample, float inv_sample_count, vec3 N, vec3 T, vec3 B, out float pdf) -{ - vec3 Xi = hammersley_3d(nsample, inv_sample_count); - return sample_hemisphere(Xi, N, T, B, pdf); -} +/* -------------------------------------------------------------------- */ +/** \name Uniform Cone sampling + * \{ */ -vec3 sample_cone(float nsample, float inv_sample_count, float angle, vec3 N, vec3 T, vec3 B) +vec3 sample_uniform_cone(vec3 rand, float angle) { - vec3 Xi = hammersley_3d(nsample, inv_sample_count); - - float z = cos(angle * Xi.x); /* cos theta */ + float z = cos(angle * rand.x); /* cos theta */ float r = sqrt(max(0.0, 1.0 - z * z)); /* sin theta */ - float x = r * Xi.y; - float y = r * Xi.z; - - vec3 Ht = vec3(x, y, z); + float x = r * rand.y; + float y = r * rand.z; + return vec3(x, y, z); +} +vec3 sample_uniform_cone(vec3 rand, float angle, vec3 N, vec3 T, vec3 B) +{ + vec3 Ht = sample_uniform_cone(rand, angle); + /* TODO pdf? */ return tangent_to_world(Ht, N, T, B); } -#endif + +/** \} */ diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl index 18fcfd4fd41..9ecc50d9df5 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl @@ -1,4 +1,5 @@ +#pragma BLENDER_REQUIRE(random_lib.glsl) #pragma BLENDER_REQUIRE(bsdf_sampling_lib.glsl) #pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) #pragma BLENDER_REQUIRE(irradiance_lib.glsl) @@ -10,7 +11,6 @@ uniform float lodMax; uniform float intensityFac; uniform float sampleCount; -uniform float invSampleCount; in vec3 worldPosition; @@ -147,8 +147,10 @@ void main() float weight = 0.0; vec3 out_radiance = vec3(0.0); for (float i = 0; i < sampleCount; i++) { + vec3 Xi = rand2d_to_cylinder(hammersley_2d(i, sampleCount)); + float pdf; - vec3 L = sample_hemisphere(i, invSampleCount, N, T, B, pdf); + vec3 L = sample_uniform_hemisphere(Xi, N, T, B, pdf); float NL = dot(N, L); if (NL > 0.0) { diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl index 99cbf2839ad..11fc1fb4295 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl @@ -1,4 +1,5 @@ +#pragma BLENDER_REQUIRE(random_lib.glsl) #pragma BLENDER_REQUIRE(bsdf_sampling_lib.glsl) #pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) @@ -12,7 +13,6 @@ uniform float intensityFac; uniform float fireflyFactor; uniform float sampleCount; -uniform float invSampleCount; in vec3 worldPosition; @@ -52,9 +52,11 @@ void main() float weight = 0.0; vec3 out_radiance = vec3(0.0); for (float i = 0; i < sampleCount; i++) { + vec3 Xi = rand2d_to_cylinder(hammersley_2d(i, sampleCount)); + float pdf; /* Microfacet normal */ - vec3 H = sample_ggx(i, invSampleCount, roughness, V, N, T, B, pdf); + vec3 H = sample_ggx(Xi, roughness, V, N, T, B, pdf); vec3 L = -reflect(V, H); float NL = dot(N, L); diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_visibility_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_visibility_frag.glsl index b802b39c56e..d25ef23a706 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_visibility_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_visibility_frag.glsl @@ -1,4 +1,5 @@ +#pragma BLENDER_REQUIRE(random_lib.glsl) #pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) #pragma BLENDER_REQUIRE(bsdf_sampling_lib.glsl) #pragma BLENDER_REQUIRE(irradiance_lib.glsl) @@ -14,7 +15,7 @@ uniform float visibilityRange; uniform float visibilityBlur; uniform float sampleCount; -uniform float invSampleCount; +uniform float; out vec4 FragColor; @@ -80,13 +81,15 @@ void main() vec2 accum = vec2(0.0); for (float i = 0; i < sampleCount; i++) { - vec3 samp = sample_cone(i, invSampleCount, M_PI_2 * visibilityBlur, cos, T, B); + vec3 Xi = rand2d_to_cylinder(hammersley_2d(i, sampleCount)); + + vec3 samp = sample_uniform_cone(Xi, M_PI_2 * visibilityBlur, cos, T, B); float depth = texture(probeDepth, samp).r; depth = get_world_distance(depth, samp); accum += vec2(depth, depth * depth); } - accum *= invSampleCount; + accum /= sampleCount; accum = abs(accum); /* Encode to normalized RGBA 8 */ diff --git a/source/blender/draw/engines/eevee/shaders/random_lib.glsl b/source/blender/draw/engines/eevee/shaders/random_lib.glsl new file mode 100644 index 00000000000..25a3e0f56b4 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/random_lib.glsl @@ -0,0 +1,38 @@ + +/** + * Random numbers and low discrepency sequences utilities. + **/ + +#pragma BLENDER_REQUIRE(common_math_lib.glsl) + +/* From: http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html */ +float van_der_corput_radical_inverse(uint bits) +{ + bits = (bits << 16u) | (bits >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + /* Same as dividing by 0x100000000. */ + return float(bits) * 2.3283064365386963e-10; +} + +vec2 hammersley_2d(float i, float sample_count) +{ + vec2 rand; + rand.x = i / sample_count; + rand.y = van_der_corput_radical_inverse(uint(i)); + return rand; +} + +/* This transform a 2d random sample (in [0..1] range) to a sample located on a cylinder of the + * same range. This is because the sampling functions expect such a random sample which is + * normally precomputed. */ +vec3 rand2d_to_cylinder(vec2 rand) +{ + float theta = rand.x; + float phi = (rand.y - 0.5) * M_2PI; + float cos_phi = cos(phi); + float sin_phi = sqrt(1.0 - sqr(cos_phi)) * sign(phi); + return vec3(theta, cos_phi, sin_phi); +} |