@@ -6,75 +6,56 @@ uniform mat4 MVPM;
6
6
7
7
out vec4 color;
8
8
9
- // ----------------------------------------------------------------------------
10
- // Rayleigh and Mie scattering atmosphere system
11
- //
12
- // implementation of the techniques described here:
13
- // http://www.scratchapixel.com/old/lessons/3d-advanced-lessons/simulating-the-colors-of-the-sky/atmospheric-scattering/
14
- // ----------------------------------------------------------------------------
15
-
16
- #define _in(T) const in T
17
- #define _inout(T) inout T
18
- #define _out(T) out T
19
- #define _begin(type) type (
20
- #define _end )
21
- #define mul(a, b) (a) * (b)
9
+ /*
10
+ Atmospheric scattering based off of:
11
+ */
22
12
23
13
#define PI 3.14159265359
14
+ #define BIAS 1e-4 // small offset to avoid self-intersections
15
+
16
+ // scattering coefficients at sea level (m)
17
+ const vec3 betaR = vec3 (5.5e-6 , 13.0e-6 , 22.4e-6 ); // Rayleigh
18
+ const vec3 betaM = vec3 (21e-6 ); // Mie
19
+
20
+ // scale height (m)
21
+ // thickness of the atmosphere if its density were uniform
22
+ const float hR = 7994.0 ; // Rayleigh
23
+ const float hM = 1200.0 ; // Mie
24
+
25
+ const float earth_radius = 6360e3 ; // (m)
26
+ const float atmosphere_radius = 6420e3 ; // (m)
27
+
28
+ vec3 sun_dir = vec3 (0 , 1 , 0 );
29
+ const float sun_power = 30.0 ;
30
+
31
+
32
+ const int num_samples = 16 ;
33
+ const int num_samples_light = 8 ;
34
+
24
35
25
- // Shadertoy specific uniforms
26
- #define u_res resolution
27
- #define u_time time
28
36
29
37
struct ray_t {
30
38
vec3 origin;
31
39
vec3 direction;
32
40
};
33
- #define BIAS 1e-4 // small offset to avoid self-intersections
34
41
35
42
struct sphere_t {
36
43
vec3 origin;
37
44
float radius;
38
- int material;
39
45
};
40
46
41
- struct plane_t {
42
- vec3 direction;
43
- float distance ;
44
- int material;
45
- };
47
+ const sphere_t atmosphere = sphere_t(vec3 (0 , 0 , 0 ), atmosphere_radius);
46
48
47
- int check_pos(vec2 x, float size) {
48
- return int (mod (floor (x.x), size) + mod (floor (x.y), size)* size);
49
- }
50
49
51
- mat3 rotate_around_x(_in( float ) angle_degrees)
50
+ mat3 rotate_around_x(const in float angle_degrees)
52
51
{
53
52
float angle = radians (angle_degrees);
54
53
float _sin = sin (angle);
55
54
float _cos = cos (angle);
56
55
return mat3 (1 , 0 , 0 , 0 , _cos, - _sin, 0 , _sin, _cos);
57
56
}
58
57
59
-
60
- ray_t get_primary_ray(
61
- _in(vec3 ) cam_local_point,
62
- _inout(vec3 ) cam_origin,
63
- _inout(vec3 ) cam_look_at
64
- ){
65
- vec3 fwd = normalize (cam_look_at - cam_origin);
66
- vec3 up = vec3 (0 , 1 , 0 );
67
- vec3 right = cross (up, fwd);
68
- up = cross (fwd, right);
69
-
70
- ray_t r = _begin(ray_t)
71
- cam_origin,
72
- normalize (fwd + up * cam_local_point.y + right * cam_local_point.x)
73
- _end;
74
- return r;
75
- }
76
-
77
- bool isect_sphere(_in(ray_t) ray, _in(sphere_t) sphere, _inout(float ) t0, _inout(float ) t1)
58
+ bool isect_sphere(const in ray_t ray, const in sphere_t sphere, inout float t0, inout float t1)
78
59
{
79
60
vec3 rc = sphere.origin - ray.origin;
80
61
float radius2 = sphere.radius * sphere.radius;
@@ -88,15 +69,6 @@ bool isect_sphere(_in(ray_t) ray, _in(sphere_t) sphere, _inout(float) t0, _inout
88
69
return true;
89
70
}
90
71
91
- // scattering coefficients at sea level (m)
92
- const vec3 betaR = vec3 (5.5e-6 , 13.0e-6 , 22.4e-6 ); // Rayleigh
93
- const vec3 betaM = vec3 (21e-6 ); // Mie
94
-
95
- // scale height (m)
96
- // thickness of the atmosphere if its density were uniform
97
- const float hR = 7994.0 ; // Rayleigh
98
- const float hM = 1200.0 ; // Mie
99
-
100
72
float rayleigh_phase_func(float mu)
101
73
{
102
74
return
@@ -109,43 +81,19 @@ float rayleigh_phase_func(float mu)
109
81
// represents the average cosine of the scattered directions
110
82
// 0 is isotropic scattering
111
83
// > 1 is forward scattering, < 1 is backwards
112
- const float g = 0.76 ;
113
84
float henyey_greenstein_phase_func(float mu)
114
85
{
86
+ const float g = 0.76 ;
115
87
return
116
88
(1 . - g* g)
117
89
/ // ---------------------------------------------
118
90
((4 . + PI) * pow (1 . + g* g - 2 .*g* mu, 1.5 ));
119
91
}
120
92
121
- // Schlick Phase Function factor
122
- // Pharr and Humphreys [2004] equivalence to g above
123
- const float k = 1.55 * g - 0.55 * (g* g* g);
124
- float schlick_phase_func(float mu)
125
- {
126
- return
127
- (1 . - k* k)
128
- / // -------------------------------------------
129
- (4 . * PI * (1 . + k* mu) * (1 . + k* mu));
130
- }
131
-
132
- const float earth_radius = 6360e3 ; // (m)
133
- const float atmosphere_radius = 6420e3 ; // (m)
134
-
135
- vec3 sun_dir = vec3 (0 , 1 , 0 );
136
- const float sun_power = 20.0 ;
137
-
138
- const sphere_t atmosphere = _begin(sphere_t)
139
- vec3 (0 , 0 , 0 ), atmosphere_radius, 0
140
- _end;
141
-
142
- const int num_samples = 16 ;
143
- const int num_samples_light = 8 ;
144
-
145
93
bool get_sun_light(
146
- _in( ray_t) ray,
147
- _inout( float ) optical_depthR,
148
- _inout( float ) optical_depthM
94
+ const in ray_t ray,
95
+ inout float optical_depthR,
96
+ inout float optical_depthM
149
97
){
150
98
float t0 = 0.0 ;
151
99
float t1 = 0.0 ;
@@ -171,7 +119,7 @@ bool get_sun_light(
171
119
return true;
172
120
}
173
121
174
- vec3 get_incident_light(_in( ray_t) ray)
122
+ vec3 get_incident_light(const in ray_t ray)
175
123
{
176
124
// "pierce" the atmosphere with the viewing ray
177
125
float t0 = 0.0 ;
@@ -194,11 +142,7 @@ vec3 get_incident_light(_in(ray_t) ray)
194
142
// * integrates to 1 over the entire sphere of directions
195
143
float phaseR = rayleigh_phase_func(mu);
196
144
float phaseM =
197
- #if 1
198
- henyey_greenstein_phase_func(mu);
199
- #else
200
- schlick_phase_func(mu);
201
- #endif
145
+ henyey_greenstein_phase_func(mu);
202
146
203
147
// optical depth (or "average density")
204
148
// represents the accumulated extinction coefficients
@@ -223,10 +167,7 @@ vec3 get_incident_light(_in(ray_t) ray)
223
167
optical_depthM += hm;
224
168
225
169
// gather the sunlight
226
- ray_t light_ray = _begin(ray_t)
227
- s,
228
- sun_dir
229
- _end;
170
+ ray_t light_ray = ray_t(s, sun_dir);
230
171
float optical_depth_lightR = 0 .;
231
172
float optical_depth_lightM = 0 .;
232
173
bool overground = get_sun_light(
@@ -253,40 +194,38 @@ vec3 get_incident_light(_in(ray_t) ray)
253
194
sumM * phaseM * betaM);
254
195
}
255
196
256
- vec3 ACESFilm( vec3 x )
257
- {
258
- float a = 2 .51f;
259
- float b = 0 .03f;
260
- float c = 2 .43f;
261
- float d = 0 .59f;
262
- float e = 0 .14f;
263
- return clamp ((x* (a* x+ b))/ (x* (c* x+ d)+ e), 0.0 , 1.0 );
197
+ vec3 U2Tone(vec3 x) {
198
+ const float A = 0.15 ;
199
+ const float B = 0.50 ;
200
+ const float C = 0.10 ;
201
+ const float D = 0.20 ;
202
+ const float E = 0.02 ;
203
+ const float F = 0.30 ;
204
+
205
+ return ((x* (A* x+ C* B)+ D* E)/ (x* (A* x+ B)+ D* F))- E/ F;
264
206
}
265
207
266
208
void main()
267
209
{
268
- vec2 aspect_ratio = vec2 (u_res.x / u_res.y, 1 );
269
- float fov = tan (radians (45.0 ));
270
- vec2 point_ndc = gl_FragCoord .xy / u_res.xy;
271
- vec3 point_cam = vec3 ((2.0 * point_ndc - 1.0 ) * aspect_ratio * fov, 1.0 );
210
+ vec2 aspect_ratio = vec2 (resolution.x / resolution.y, 1 );
211
+ vec2 point_ndc = gl_FragCoord .xy / resolution.xy;
212
+ vec3 point_cam = vec3 ((2.0 * point_ndc - 1.0 ) * aspect_ratio, 1.0 );
272
213
273
214
vec4 worldPos = (inverse((MVPM))* vec4 (point_cam, 1.0 ));
274
215
worldPos.xyz /= worldPos.w;
275
216
point_cam = normalize (worldPos.xyz);
276
217
277
- vec3 col = vec3 (0 );
218
+ vec3 col = vec3 (0.4 );
278
219
if (point_cam.y>-0.05 ) {
279
220
// sun
280
- mat3 rot = rotate_around_x(- abs (sin (u_time / 20 .)) * 90 .);
221
+ mat3 rot = rotate_around_x(- abs (sin (time / 20 .)) * 90 .);
281
222
sun_dir *= rot;
282
-
283
- vec3 eye = vec3 (0 , earth_radius + 1 ., 0 );
284
- vec3 look_at = vec3 (0 , earth_radius + 1.0 , - 1 );
285
223
286
- // ray_t ray = get_primary_ray(point_cam, eye, look_at);
287
224
ray_t ray = ray_t(vec3 (0.0 , earth_radius+ 1.0 , 0.0 ), point_cam);
288
225
col = get_incident_light(ray);
289
226
}
290
- col = ACESFilm(col);
227
+ col = U2Tone(col);
228
+ col /= U2Tone(vec3 (2.5 ));
229
+ col = sqrt (col);
291
230
color = vec4 (col, 1 );
292
231
}
0 commit comments