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

irradiance_lib.glsl « shaders « eevee « engines « draw « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 64ea87001f45178ad6e17ddc3863b0c1a1ae9be3 (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
150
151
152
153
154
155
156
157

uniform sampler2DArray irradianceGrid;

#define IRRADIANCE_LIB

#if defined(IRRADIANCE_SH_L2)
struct IrradianceData {
  vec3 shcoefs[9];
};
#else /* defined(IRRADIANCE_HL2) */
struct IrradianceData {
  vec3 cubesides[3];
};
#endif

IrradianceData load_irradiance_cell(int cell, vec3 N)
{
  /* Keep in sync with diffuse_filter_probe() */

#if defined(IRRADIANCE_SH_L2)

  ivec2 cell_co = ivec2(3, 3);
  int cell_per_row = textureSize(irradianceGrid, 0).x / cell_co.x;
  cell_co.x *= cell % cell_per_row;
  cell_co.y *= cell / cell_per_row;

  ivec3 ofs = ivec3(0, 1, 2);

  IrradianceData ir;
  ir.shcoefs[0] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.xx, 0), 0).rgb;
  ir.shcoefs[1] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.yx, 0), 0).rgb;
  ir.shcoefs[2] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.zx, 0), 0).rgb;
  ir.shcoefs[3] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.xy, 0), 0).rgb;
  ir.shcoefs[4] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.yy, 0), 0).rgb;
  ir.shcoefs[5] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.zy, 0), 0).rgb;
  ir.shcoefs[6] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.xz, 0), 0).rgb;
  ir.shcoefs[7] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.yz, 0), 0).rgb;
  ir.shcoefs[8] = texelFetch(irradianceGrid, ivec3(cell_co + ofs.zz, 0), 0).rgb;

#else /* defined(IRRADIANCE_HL2) */

  ivec2 cell_co = ivec2(3, 2);
  int cell_per_row = textureSize(irradianceGrid, 0).x / cell_co.x;
  cell_co.x *= cell % cell_per_row;
  cell_co.y *= cell / cell_per_row;

  ivec3 is_negative = ivec3(step(0.0, -N));

  IrradianceData ir;
  ir.cubesides[0] = irradiance_decode(
      texelFetch(irradianceGrid, ivec3(cell_co + ivec2(0, is_negative.x), 0), 0));
  ir.cubesides[1] = irradiance_decode(
      texelFetch(irradianceGrid, ivec3(cell_co + ivec2(1, is_negative.y), 0), 0));
  ir.cubesides[2] = irradiance_decode(
      texelFetch(irradianceGrid, ivec3(cell_co + ivec2(2, is_negative.z), 0), 0));

#endif

  return ir;
}

float load_visibility_cell(int cell, vec3 L, float dist, float bias, float bleed_bias, float range)
{
  /* Keep in sync with diffuse_filter_probe() */
  ivec2 cell_co = ivec2(prbIrradianceVisSize);
  ivec2 cell_per_row_col = textureSize(irradianceGrid, 0).xy / prbIrradianceVisSize;
  cell_co.x *= (cell % cell_per_row_col.x);
  cell_co.y *= (cell / cell_per_row_col.x) % cell_per_row_col.y;
  float layer = 1.0 + float((cell / cell_per_row_col.x) / cell_per_row_col.y);

  vec2 texel_size = 1.0 / vec2(textureSize(irradianceGrid, 0).xy);
  vec2 co = vec2(cell_co) * texel_size;

  vec2 uv = mapping_octahedron(-L, vec2(1.0 / float(prbIrradianceVisSize)));
  uv *= vec2(prbIrradianceVisSize) * texel_size;

  vec4 data = texture(irradianceGrid, vec3(co + uv, layer));

  /* Decoding compressed data */
  vec2 moments = visibility_decode(data, range);

  /* Doing chebishev test */
  float variance = abs(moments.x * moments.x - moments.y);
  variance = max(variance, bias / 10.0);

  float d = dist - moments.x;
  float p_max = variance / (variance + d * d);

  /* Increase contrast in the weight by squaring it */
  p_max *= p_max;

  /* Now reduce light-bleeding by removing the [0, x] tail and linearly rescaling (x, 1] */
  p_max = clamp((p_max - bleed_bias) / (1.0 - bleed_bias), 0.0, 1.0);

  return (dist <= moments.x) ? 1.0 : p_max;
}

/* http://seblagarde.wordpress.com/2012/01/08/pi-or-not-to-pi-in-game-lighting-equation/ */
vec3 spherical_harmonics_L1(vec3 N, vec3 shcoefs[4])
{
  vec3 sh = vec3(0.0);

  sh += 0.282095 * shcoefs[0];

  sh += -0.488603 * N.z * shcoefs[1];
  sh += 0.488603 * N.y * shcoefs[2];
  sh += -0.488603 * N.x * shcoefs[3];

  return sh;
}

vec3 spherical_harmonics_L2(vec3 N, vec3 shcoefs[9])
{
  vec3 sh = vec3(0.0);

  sh += 0.282095 * shcoefs[0];

  sh += -0.488603 * N.z * shcoefs[1];
  sh += 0.488603 * N.y * shcoefs[2];
  sh += -0.488603 * N.x * shcoefs[3];

  sh += 1.092548 * N.x * N.z * shcoefs[4];
  sh += -1.092548 * N.z * N.y * shcoefs[5];
  sh += 0.315392 * (3.0 * N.y * N.y - 1.0) * shcoefs[6];
  sh += -1.092548 * N.x * N.y * shcoefs[7];
  sh += 0.546274 * (N.x * N.x - N.z * N.z) * shcoefs[8];

  return sh;
}

vec3 hl2_basis(vec3 N, vec3 cubesides[3])
{
  vec3 irradiance = vec3(0.0);

  vec3 n_squared = N * N;

  irradiance += n_squared.x * cubesides[0];
  irradiance += n_squared.y * cubesides[1];
  irradiance += n_squared.z * cubesides[2];

  return irradiance;
}

vec3 compute_irradiance(vec3 N, IrradianceData ird)
{
#if defined(IRRADIANCE_SH_L2)
  return spherical_harmonics_L2(N, ird.shcoefs);
#else /* defined(IRRADIANCE_HL2) */
  return hl2_basis(N, ird.cubesides);
#endif
}

vec3 irradiance_from_cell_get(int cell, vec3 ir_dir)
{
  IrradianceData ir_data = load_irradiance_cell(cell, ir_dir);
  return compute_irradiance(ir_dir, ir_data);
}