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

effect_reflection_trace_frag.glsl « shaders « eevee « engines « draw « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: c9010749060c6c298af22cc17de70f5c67784282 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149

#pragma BLENDER_REQUIRE(common_math_lib.glsl)
#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl)
#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
#pragma BLENDER_REQUIRE(raytrace_lib.glsl)
#pragma BLENDER_REQUIRE(lightprobe_lib.glsl)
#pragma BLENDER_REQUIRE(bsdf_sampling_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 normalBuffer;
uniform sampler2D specroughBuffer;
uniform vec2 targetSize;
uniform float randomScale;

in vec4 uvcoordsvar;

layout(location = 0) out vec4 hitData;
layout(location = 1) out float hitDepth;

void main()
{
  vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy);
  /* Decorrelate from AA. */
  /* TODO(@fclem): we should use a more general approach for more random number dimensions. */
  vec2 random_px = floor(fract(rand.xy * 2.2074408460575947536) * 1.99999) - 0.5;
  rand.xy = fract(rand.xy * 3.2471795724474602596);

  /* Randomly choose the pixel to start the ray from when tracing at lower resolution.
   * This method also make sure we always start from the center of a fullres texel. */
  vec2 uvs = (gl_FragCoord.xy + random_px * randomScale) / (targetSize * ssrUvScale);

  float depth = textureLod(maxzBuffer, uvs * hizUvScale.xy, 0.0).r;

  HitData data;
  data.is_planar = false;
  data.ray_pdf_inv = 0.0;
  data.is_hit = false;
  data.hit_dir = vec3(0.0, 0.0, 0.0);
  /* Default: not hits. */
  encode_hit_data(data, data.hit_dir, data.hit_dir, hitData, hitDepth);

  /* Early out */
  /* We can't do discard because we don't clear the render target. */
  if (depth == 1.0) {
    return;
  }

  /* Using view space */
  vec3 vP = get_view_space_from_depth(uvs, depth);
  vec3 P = transform_point(ViewMatrixInverse, vP);
  vec3 vV = viewCameraVec(vP);
  vec3 V = cameraVec(P);
  vec3 vN = normal_decode(textureLod(normalBuffer, uvs, 0.0).rg, vV);
  vec3 N = transform_direction(ViewMatrixInverse, vN);

  /* Retrieve pixel data */
  vec4 speccol_roughness = textureLod(specroughBuffer, uvs, 0.0).rgba;

  /* Early out */
  if (dot(speccol_roughness.rgb, vec3(1.0)) == 0.0) {
    return;
  }

  float roughness = speccol_roughness.a;
  float alpha = max(1e-3, roughness * roughness);

  /* Early out */
  if (roughness > ssrMaxRoughness + 0.2) {
    return;
  }

  /* Planar Reflections */
  int planar_id = -1;
  for (int i = 0; i < MAX_PLANAR && i < prbNumPlanar; i++) {
    PlanarData pd = planars_data[i];

    float fade = probe_attenuation_planar(pd, P);
    fade *= probe_attenuation_planar_normal_roughness(pd, N, 0.0);

    if (fade > 0.5) {
      /* Find view vector / reflection plane intersection. */
      /* TODO: optimize, use view space for all. */
      vec3 P_plane = line_plane_intersect(P, V, pd.pl_plane_eq);
      vP = transform_point(ViewMatrix, P_plane);

      planar_id = i;
      data.is_planar = true;
      break;
    }
  }

  /* Gives *perfect* reflection for very small roughness */
  if (roughness < 0.04) {
    rand.xzw *= 0.0;
  }
  /* Importance sampling bias */
  rand.x = mix(rand.x, 0.0, ssrBrdfBias);

  vec3 vT, vB;
  make_orthonormal_basis(vN, vT, vB); /* Generate tangent space */

  float pdf;
  vec3 vH = sample_ggx(rand.xzw, alpha, vV, vN, vT, vB, pdf);
  vec3 vR = reflect(-vV, vH);

  if (isnan(pdf)) {
    /* Seems that somethings went wrong.
     * This only happens on extreme cases where the normal deformed too much to have any valid
     * reflections. */
    return;
  }

  if (data.is_planar) {
    vec3 view_plane_normal = transform_direction(ViewMatrix, planars_data[planar_id].pl_normal);
    /* For planar reflections, we trace inside the reflected view. */
    vR = reflect(vR, view_plane_normal);
  }

  Ray ray;
  ray.origin = vP;
  ray.direction = vR * 1e16;

  RayTraceParameters params;
  params.thickness = ssrThickness;
  params.jitter = rand.y;
  params.trace_quality = ssrQuality;
  params.roughness = alpha * alpha;

  vec3 hit_sP;
  if (data.is_planar) {
    data.is_hit = raytrace_planar(ray, params, planar_id, hit_sP);
  }
  else {
    data.is_hit = raytrace(ray, params, true, false, hit_sP);
  }
  data.ray_pdf_inv = safe_rcp(pdf);

  encode_hit_data(data, hit_sP, ray.origin, hitData, hitDepth);
}