bettola/assets/shaders/sky.frag

81 lines
2.6 KiB
GLSL

#version 330 core
out vec4 FragColor;
in vec3 v_WorldPos;
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);
}
void main() {
vec3 dir = normalize(v_WorldPos);
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));
vec3 finalColor = 20.0 * (totalRayleigh * RAYLEIGH_SCATTERING_COEFF
* rayleighPhase + totalMie * MIE_SCATTERING_COEFF * miePhase);
FragColor = vec4(pow(finalColor, vec3(1.0/2.2)), 1.0);
}