Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/draw/engines/eevee/shaders/effect_reflection_resolve_frag.glsl')
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_reflection_resolve_frag.glsl220
1 files changed, 220 insertions, 0 deletions
diff --git a/source/blender/draw/engines/eevee/shaders/effect_reflection_resolve_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_reflection_resolve_frag.glsl
new file mode 100644
index 00000000000..6f2619127e3
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/effect_reflection_resolve_frag.glsl
@@ -0,0 +1,220 @@
+
+#pragma BLENDER_REQUIRE(common_math_lib.glsl)
+#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl)
+#pragma BLENDER_REQUIRE(closure_eval_glossy_lib.glsl)
+#pragma BLENDER_REQUIRE(closure_eval_lib.glsl)
+#pragma BLENDER_REQUIRE(lightprobe_lib.glsl)
+#pragma BLENDER_REQUIRE(bsdf_common_lib.glsl)
+#pragma BLENDER_REQUIRE(surface_lib.glsl)
+#pragma BLENDER_REQUIRE(effect_reflection_lib.glsl)
+
+/* Based on:
+ * "Stochastic Screen Space Reflections"
+ * by Tomasz Stachowiak.
+ * https://www.ea.com/frostbite/news/stochastic-screen-space-reflections
+ * and
+ * "Stochastic all the things: raytracing in hybrid real-time rendering"
+ * by Tomasz Stachowiak.
+ * https://media.contentapi.ea.com/content/dam/ea/seed/presentations/dd18-seed-raytracing-in-hybrid-real-time-rendering.pdf
+ */
+
+uniform sampler2D colorBuffer;
+uniform sampler2D normalBuffer;
+uniform sampler2D specroughBuffer;
+uniform sampler2D hitBuffer;
+uniform sampler2D hitDepth;
+
+uniform int samplePoolOffset;
+
+in vec4 uvcoordsvar;
+
+out vec4 fragColor;
+
+vec4 ssr_get_scene_color_and_mask(vec3 hit_vP, int planar_index, float mip)
+{
+ vec2 uv;
+ if (planar_index != -1) {
+ uv = get_uvs_from_view(hit_vP);
+ /* Planar X axis is flipped. */
+ uv.x = 1.0 - uv.x;
+ }
+ else {
+ /* Find hit position in previous frame. */
+ /* TODO Combine matrices. */
+ vec3 hit_P = transform_point(ViewMatrixInverse, hit_vP);
+ /* TODO real reprojection with motion vectors, etc... */
+ uv = project_point(pastViewProjectionMatrix, hit_P).xy * 0.5 + 0.5;
+ }
+
+ vec3 color;
+ if (planar_index != -1) {
+ color = textureLod(probePlanars, vec3(uv, planar_index), mip).rgb;
+ }
+ else {
+ color = textureLod(colorBuffer, uv * hizUvScale.xy, mip).rgb;
+ }
+
+ /* Clamped brightness. */
+ float luma = max_v3(color);
+ color *= 1.0 - max(0.0, luma - ssrFireflyFac) * safe_rcp(luma);
+
+ float mask = screen_border_mask(uv);
+ return vec4(color, mask);
+}
+
+void resolve_reflection_sample(int planar_index,
+ vec2 sample_uv,
+ vec3 vP,
+ vec3 vN,
+ vec3 vV,
+ float roughness_squared,
+ float cone_tan,
+ inout float weight_accum,
+ inout vec4 ssr_accum)
+{
+ vec4 hit_data = texture(hitBuffer, sample_uv);
+ float hit_depth = texture(hitDepth, sample_uv).r;
+ HitData data = decode_hit_data(hit_data, hit_depth);
+
+ float hit_dist = length(data.hit_dir);
+
+ /* Slide 54. */
+ float bsdf = bsdf_ggx(vN, data.hit_dir / hit_dist, vV, roughness_squared);
+
+ float weight = bsdf * data.ray_pdf_inv;
+
+ /* Do not reuse hitpoint from planar reflections for normal reflections and vice versa. */
+ if ((planar_index == -1 && data.is_planar) || (planar_index != -1 && !data.is_planar)) {
+ return;
+ }
+ /* Do not add light if ray has failed but still weight it. */
+ if (!data.is_hit) {
+ weight_accum += weight;
+ return;
+ }
+
+ vec3 hit_vP = vP + data.hit_dir;
+
+ /* Compute cone footprint in screen space. */
+ float cone_footprint = hit_dist * cone_tan;
+ float homcoord = ProjectionMatrix[2][3] * hit_vP.z + ProjectionMatrix[3][3];
+ cone_footprint *= max(ProjectionMatrix[0][0], ProjectionMatrix[1][1]) / homcoord;
+ cone_footprint *= ssrBrdfBias * 0.5;
+ /* Estimate a cone footprint to sample a corresponding mipmap level. */
+ float mip = log2(cone_footprint * max_v2(vec2(textureSize(specroughBuffer, 0))));
+
+ vec4 radiance_mask = ssr_get_scene_color_and_mask(hit_vP, planar_index, mip);
+
+ ssr_accum += radiance_mask * weight;
+ weight_accum += weight;
+}
+
+void raytrace_resolve(ClosureInputGlossy cl_in,
+ inout ClosureEvalGlossy cl_eval,
+ inout ClosureEvalCommon cl_common,
+ inout ClosureOutputGlossy cl_out)
+{
+ float roughness = cl_in.roughness;
+
+ vec4 ssr_accum = vec4(0.0);
+ float weight_acc = 0.0;
+
+ if (roughness < ssrMaxRoughness + 0.2) {
+ /* Find Planar Reflections affecting this pixel */
+ int planar_index = -1;
+ for (int i = 0; i < MAX_PLANAR && i < prbNumPlanar; i++) {
+ float fade = probe_attenuation_planar(planars_data[i], cl_common.P);
+ fade *= probe_attenuation_planar_normal_roughness(planars_data[i], cl_in.N, 0.0);
+ if (fade > 0.5) {
+ planar_index = i;
+ break;
+ }
+ }
+
+ vec3 V, P, N;
+ if (planar_index != -1) {
+ PlanarData pd = planars_data[planar_index];
+ /* Evaluate everything in refected space. */
+ P = line_plane_intersect(cl_common.P, cl_common.V, pd.pl_plane_eq);
+ V = reflect(cl_common.V, pd.pl_normal);
+ N = reflect(cl_in.N, pd.pl_normal);
+ }
+ else {
+ V = cl_common.V;
+ P = cl_common.P;
+ N = cl_in.N;
+ }
+
+ /* Using view space */
+ vec3 vV = transform_direction(ViewMatrix, cl_common.V);
+ vec3 vP = transform_point(ViewMatrix, cl_common.P);
+ vec3 vN = transform_direction(ViewMatrix, cl_in.N);
+
+ float roughness_squared = max(1e-3, sqr(roughness));
+ float cone_cos = cone_cosine(roughness_squared);
+ float cone_tan = sqrt(1.0 - cone_cos * cone_cos) / cone_cos;
+ cone_tan *= mix(saturate(dot(vN, -vV) * 2.0), 1.0, roughness); /* Elongation fit */
+
+ int sample_pool = int((uint(gl_FragCoord.x) & 1u) + (uint(gl_FragCoord.y) & 1u) * 2u);
+ sample_pool = (sample_pool + (samplePoolOffset / 5)) % 4;
+
+ for (int i = 0; i < resolve_samples_count; i++) {
+ int sample_id = sample_pool * resolve_samples_count + i;
+ vec2 texture_size = vec2(textureSize(hitBuffer, 0));
+ vec2 sample_texel = texture_size * uvcoordsvar.xy * ssrUvScale;
+ vec2 sample_uv = (sample_texel + resolve_sample_offsets[sample_id]) / texture_size;
+
+ resolve_reflection_sample(
+ planar_index, sample_uv, vP, vN, vV, roughness_squared, cone_tan, weight_acc, ssr_accum);
+ }
+ }
+
+ /* Compute SSR contribution */
+ ssr_accum *= safe_rcp(weight_acc);
+ /* fade between 0.5 and 1.0 roughness */
+ ssr_accum.a *= smoothstep(ssrMaxRoughness + 0.2, ssrMaxRoughness, roughness);
+
+ cl_eval.raytrace_radiance = ssr_accum.rgb * ssr_accum.a;
+ cl_common.specular_accum -= ssr_accum.a;
+}
+
+CLOSURE_EVAL_FUNCTION_DECLARE_1(ssr_resolve, Glossy)
+
+void main()
+{
+ float depth = textureLod(maxzBuffer, uvcoordsvar.xy * hizUvScale.xy, 0.0).r;
+
+ if (depth == 1.0) {
+ discard;
+ }
+
+ ivec2 texel = ivec2(gl_FragCoord.xy);
+ vec4 speccol_roughness = texelFetch(specroughBuffer, texel, 0).rgba;
+ vec3 brdf = speccol_roughness.rgb;
+ float roughness = speccol_roughness.a;
+
+ if (max_v3(brdf) <= 0.0) {
+ discard;
+ }
+
+ FragDepth = depth;
+
+ viewPosition = get_view_space_from_depth(uvcoordsvar.xy, depth);
+ worldPosition = transform_point(ViewMatrixInverse, viewPosition);
+
+ vec2 normal_encoded = texelFetch(normalBuffer, texel, 0).rg;
+ viewNormal = normal_decode(normal_encoded, viewCameraVec(viewPosition));
+ worldNormal = transform_direction(ViewMatrixInverse, viewNormal);
+
+ CLOSURE_VARS_DECLARE_1(Glossy);
+
+ in_Glossy_0.N = worldNormal;
+ in_Glossy_0.roughness = roughness;
+
+ /* Do a full deferred evaluation of the glossy BSDF. The only difference is that we inject the
+ * SSR resolve before the cubemap iter. BRDF term is already computed during main pass and is
+ * passed as specular color. */
+ CLOSURE_EVAL_FUNCTION_1(ssr_resolve, Glossy);
+
+ fragColor = vec4(out_Glossy_0.radiance * brdf, 1.0);
+}