86 lines
3.0 KiB
GLSL
86 lines
3.0 KiB
GLSL
#version 330 core
|
|
out vec4 FragColor;
|
|
|
|
in vec3 TexCoords;
|
|
|
|
uniform sampler2D u_CloudTexture;
|
|
uniform vec3 u_SunPos;
|
|
|
|
const float PI = 3.14159265359;
|
|
|
|
/* Atmosphere parameters. */
|
|
const float ATMOSPHERE_RADIUS = 6520275.0;
|
|
const float PLANET_RADIUS = 6371000.0;
|
|
const float RAYLEIGH_SCALE_HEIGHT = 8000.0;
|
|
const float MIE_SCALE_HEIGHT = 1200.0;
|
|
|
|
/* Scattering coefficients. */
|
|
const vec3 RAYLEIGH_SCATTERING_COEFF = vec3(0.0000058, 0.0000135, 0.0000331);
|
|
const vec3 MIE_SCATTERING_COEFF = vec3(0.00002);
|
|
|
|
/* Mie scattering parameters. */
|
|
const float MIE_G = 0.76;
|
|
|
|
/* Number of samples for ray marching. */
|
|
const int SAMPLES = 16;
|
|
const int LIGHT_SAMPLES = 8;
|
|
|
|
float ray_sphere_intersect(vec3 origin, vec3 dir, float radius) {
|
|
float a = dot(dir, dir);
|
|
float b = 2.0 * dot(origin, dir);
|
|
float c = dot(origin, origin) - radius * radius;
|
|
float d = b * b - 4.0 * a * c;
|
|
if (d < 0.0) {
|
|
return -1.0;
|
|
}
|
|
return (-b + sqrt(d)) / (2.0 * a);
|
|
}
|
|
|
|
vec3 get_sky_color(vec3 dir) {
|
|
vec3 eye = vec3(0.0, PLANET_RADIUS + 1.0, 0.0);
|
|
float dist = ray_sphere_intersect(eye, dir, ATMOSPHERE_RADIUS);
|
|
vec3 totalRayleigh = vec3(0.0);
|
|
vec3 totalMie = vec3(0.0);
|
|
float stepSize = dist / float(SAMPLES);
|
|
for (int i = 0; i < SAMPLES; i++) {
|
|
vec3 p = eye + dir * (float(i) + 0.5) * stepSize;
|
|
float h = length(p) - PLANET_RADIUS;
|
|
float rayleighDensity = exp(-h / RAYLEIGH_SCALE_HEIGHT);
|
|
float mieDensity = exp(-h / MIE_SCALE_HEIGHT);
|
|
float lightDist = ray_sphere_intersect(p, normalize(u_SunPos), ATMOSPHERE_RADIUS);
|
|
float lightStepSize = lightDist / float(LIGHT_SAMPLES);
|
|
float opticalDepthLight = 0.0;
|
|
for (int j = 0; j < LIGHT_SAMPLES; j++) {
|
|
vec3 lp = p + normalize(u_SunPos) * (float(j) + 0.5) * lightStepSize;
|
|
float lh = length(lp) - PLANET_RADIUS;
|
|
opticalDepthLight += exp(-lh / RAYLEIGH_SCALE_HEIGHT) * lightStepSize;
|
|
}
|
|
vec3 transmittance = exp(-(opticalDepthLight * RAYLEIGH_SCATTERING_COEFF
|
|
+ opticalDepthLight * MIE_SCATTERING_COEFF));
|
|
totalRayleigh += rayleighDensity * stepSize * transmittance;
|
|
totalMie += mieDensity * stepSize * transmittance;
|
|
}
|
|
|
|
float mu = dot(dir, normalize(u_SunPos));
|
|
float rayleighPhase = 3.0 / (16.0 * PI) * (1.0 + mu * mu);
|
|
float miePhase = 3.0 / (8.0 * PI) * ((1.0 - MIE_G * MIE_G)
|
|
* (1.0 + mu * mu)) / ((2.0 + MIE_G * MIE_G) * pow(1.0 + MIE_G
|
|
* MIE_G - 2.0 * MIE_G * mu, 1.5));
|
|
return 20.0 * (totalRayleigh * RAYLEIGH_SCATTERING_COEFF * rayleighPhase
|
|
+ totalMie * MIE_SCATTERING_COEFF * miePhase);
|
|
}
|
|
|
|
void main() {
|
|
float u = atan(TexCoords.z, TexCoords.x) / (2.0 * PI) + 0.5;
|
|
float v = asin(TexCoords.y) / PI + 0.5;
|
|
float cloudAlpha = texture(u_CloudTexture, vec2(u,v)).r;
|
|
|
|
vec3 skyColor = get_sky_color(normalize(TexCoords));
|
|
vec3 cloudColor = mix(skyColor, vec3(1.0), smoothstep(0.5, 0.8, cloudAlpha));
|
|
|
|
float poleFade = 1.0 - abs(TexCoords.y);
|
|
float finalAlpha = smoothstep(0.0, 0.2, poleFade) * smoothstep(0.5, 0.8, cloudAlpha);
|
|
|
|
FragColor = vec4(pow(cloudColor, vec3(1.0/2.2)), finalAlpha);
|
|
}
|