Merge branch 'master' into blender2.8
[blender.git] / source / blender / draw / engines / eevee / shaders / ltc_lib.glsl
1 /* Mainly From https://eheitzresearch.wordpress.com/415-2/ */
2
3 #define USE_LTC
4
5 #ifndef UTIL_TEX
6 #define UTIL_TEX
7 uniform sampler2DArray utilTex;
8 #endif /* UTIL_TEX */
9
10 /* from Real-Time Area Lighting: a Journey from Research to Production
11  * Stephen Hill and Eric Heitz */
12 float edge_integral(vec3 p1, vec3 p2)
13 {
14 #if 0
15         /* more accurate replacement of acos */
16         float x = dot(p1, p2);
17         float y = abs(x);
18
19         float a = 5.42031 + (3.12829 + 0.0902326 * y) * y;
20         float b = 3.45068 + (4.18814 + y) * y;
21         float theta_sintheta = a / b;
22
23         if (x < 0.0) {
24                 theta_sintheta = (M_PI / sqrt(1.0 - x * x)) - theta_sintheta;
25         }
26         vec3 u = cross(p1, p2);
27         return theta_sintheta * dot(u, N);
28 #endif
29         float cos_theta = dot(p1, p2);
30         cos_theta = clamp(cos_theta, -0.9999, 0.9999);
31
32         float theta = acos(cos_theta);
33         vec3 u = normalize(cross(p1, p2));
34         return theta * cross(p1, p2).z / sin(theta);
35 }
36
37 int clip_quad_to_horizon(inout vec3 L[5])
38 {
39         /* detect clipping config */
40         int config = 0;
41         if (L[0].z > 0.0) config += 1;
42         if (L[1].z > 0.0) config += 2;
43         if (L[2].z > 0.0) config += 4;
44         if (L[3].z > 0.0) config += 8;
45
46         /* clip */
47         int n = 0;
48
49         if (config == 0)
50         {
51                 /* clip all */
52         }
53         else if (config == 1) /* V1 clip V2 V3 V4 */
54         {
55                 n = 3;
56                 L[1] = -L[1].z * L[0] + L[0].z * L[1];
57                 L[2] = -L[3].z * L[0] + L[0].z * L[3];
58         }
59         else if (config == 2) /* V2 clip V1 V3 V4 */
60         {
61                 n = 3;
62                 L[0] = -L[0].z * L[1] + L[1].z * L[0];
63                 L[2] = -L[2].z * L[1] + L[1].z * L[2];
64         }
65         else if (config == 3) /* V1 V2 clip V3 V4 */
66         {
67                 n = 4;
68                 L[2] = -L[2].z * L[1] + L[1].z * L[2];
69                 L[3] = -L[3].z * L[0] + L[0].z * L[3];
70         }
71         else if (config == 4) /* V3 clip V1 V2 V4 */
72         {
73                 n = 3;
74                 L[0] = -L[3].z * L[2] + L[2].z * L[3];
75                 L[1] = -L[1].z * L[2] + L[2].z * L[1];
76         }
77         else if (config == 5) /* V1 V3 clip V2 V4) impossible */
78         {
79                 n = 0;
80         }
81         else if (config == 6) /* V2 V3 clip V1 V4 */
82         {
83                 n = 4;
84                 L[0] = -L[0].z * L[1] + L[1].z * L[0];
85                 L[3] = -L[3].z * L[2] + L[2].z * L[3];
86         }
87         else if (config == 7) /* V1 V2 V3 clip V4 */
88         {
89                 n = 5;
90                 L[4] = -L[3].z * L[0] + L[0].z * L[3];
91                 L[3] = -L[3].z * L[2] + L[2].z * L[3];
92         }
93         else if (config == 8) /* V4 clip V1 V2 V3 */
94         {
95                 n = 3;
96                 L[0] = -L[0].z * L[3] + L[3].z * L[0];
97                 L[1] = -L[2].z * L[3] + L[3].z * L[2];
98                 L[2] =  L[3];
99         }
100         else if (config == 9) /* V1 V4 clip V2 V3 */
101         {
102                 n = 4;
103                 L[1] = -L[1].z * L[0] + L[0].z * L[1];
104                 L[2] = -L[2].z * L[3] + L[3].z * L[2];
105         }
106         else if (config == 10) /* V2 V4 clip V1 V3) impossible */
107         {
108                 n = 0;
109         }
110         else if (config == 11) /* V1 V2 V4 clip V3 */
111         {
112                 n = 5;
113                 L[4] = L[3];
114                 L[3] = -L[2].z * L[3] + L[3].z * L[2];
115                 L[2] = -L[2].z * L[1] + L[1].z * L[2];
116         }
117         else if (config == 12) /* V3 V4 clip V1 V2 */
118         {
119                 n = 4;
120                 L[1] = -L[1].z * L[2] + L[2].z * L[1];
121                 L[0] = -L[0].z * L[3] + L[3].z * L[0];
122         }
123         else if (config == 13) /* V1 V3 V4 clip V2 */
124         {
125                 n = 5;
126                 L[4] = L[3];
127                 L[3] = L[2];
128                 L[2] = -L[1].z * L[2] + L[2].z * L[1];
129                 L[1] = -L[1].z * L[0] + L[0].z * L[1];
130         }
131         else if (config == 14) /* V2 V3 V4 clip V1 */
132         {
133                 n = 5;
134                 L[4] = -L[0].z * L[3] + L[3].z * L[0];
135                 L[0] = -L[0].z * L[1] + L[1].z * L[0];
136         }
137         else if (config == 15) /* V1 V2 V3 V4 */
138         {
139                 n = 4;
140         }
141
142         if (n == 3)
143                 L[3] = L[0];
144         if (n == 4)
145                 L[4] = L[0];
146
147         return n;
148 }
149
150 mat3 ltc_matrix(vec4 lut)
151 {
152         /* load inverse matrix */
153         mat3 Minv = mat3(
154                 vec3(  1,   0, lut.y),
155                 vec3(  0, lut.z,   0),
156                 vec3(lut.w,   0, lut.x)
157         );
158
159         return Minv;
160 }
161
162 float ltc_evaluate(vec3 N, vec3 V, mat3 Minv, vec3 corners[4])
163 {
164         /* construct orthonormal basis around N */
165         vec3 T1, T2;
166         T1 = normalize(V - N*dot(V, N));
167         T2 = cross(N, T1);
168
169         /* rotate area light in (T1, T2, R) basis */
170         Minv = Minv * transpose(mat3(T1, T2, N));
171
172         /* polygon (allocate 5 vertices for clipping) */
173         vec3 L[5];
174         L[0] = Minv * corners[0];
175         L[1] = Minv * corners[1];
176         L[2] = Minv * corners[2];
177         L[3] = Minv * corners[3];
178
179         int n = clip_quad_to_horizon(L);
180
181         if (n == 0)
182                 return 0.0;
183
184         /* project onto sphere */
185         L[0] = normalize(L[0]);
186         L[1] = normalize(L[1]);
187         L[2] = normalize(L[2]);
188         L[3] = normalize(L[3]);
189         L[4] = normalize(L[4]);
190
191         /* integrate */
192         float sum = 0.0;
193
194         sum += edge_integral(L[0], L[1]);
195         sum += edge_integral(L[1], L[2]);
196         sum += edge_integral(L[2], L[3]);
197         if (n >= 4)
198                 sum += edge_integral(L[3], L[4]);
199         if (n == 5)
200                 sum += edge_integral(L[4], L[0]);
201
202         return abs(sum);
203 }
204
205 /* Aproximate circle with an octogone */
206 #define LTC_CIRCLE_RES 8
207 float ltc_evaluate_circle(vec3 N, vec3 V, mat3 Minv, vec3 p[LTC_CIRCLE_RES])
208 {
209         /* construct orthonormal basis around N */
210         vec3 T1, T2;
211         T1 = normalize(V - N*dot(V, N));
212         T2 = cross(N, T1);
213
214         /* rotate area light in (T1, T2, R) basis */
215         Minv = Minv * transpose(mat3(T1, T2, N));
216
217         for (int i = 0; i < LTC_CIRCLE_RES; ++i) {
218                 p[i] = Minv * p[i];
219                 /* clip to horizon */
220                 p[i].z = max(0.0, p[i].z);
221                 /* project onto sphere */
222                 p[i] = normalize(p[i]);
223         }
224
225         /* integrate */
226         float sum = 0.0;
227         for (int i = 0; i < LTC_CIRCLE_RES - 1; ++i) {
228                 sum += edge_integral(p[i], p[i + 1]);
229         }
230         sum += edge_integral(p[LTC_CIRCLE_RES - 1], p[0]);
231
232         return max(0.0, sum);
233 }
234