|
| 1 | +#feature OUTLINE_PASS |
| 2 | +#feature PICKING_PASS |
| 3 | +#feature DYNAMIC_SUN_POSITION |
| 4 | + |
| 5 | +#shader vertex |
| 6 | +#version 450 core |
| 7 | + |
| 8 | +#include ":Shaders/Common/Buffers/EngineUBO.ovfxh" |
| 9 | +#include ":Shaders/Common/Utils.ovfxh" |
| 10 | +#include ":Shaders/Common/Buffers/LightsSSBO.ovfxh" |
| 11 | + |
| 12 | +layout (location = 0) in vec3 geo_Pos; |
| 13 | +layout (location = 1) in vec2 geo_TexCoords; |
| 14 | + |
| 15 | +out VS_OUT |
| 16 | +{ |
| 17 | + vec3 FragPos; |
| 18 | + flat vec3 SunPosition; |
| 19 | +} vs_out; |
| 20 | + |
| 21 | +uniform vec3 u_SunPosition = vec3(0.0, 0.1, -1.0); // Default sun position |
| 22 | + |
| 23 | +// Calculate the sun position based on the first directional light in the scene |
| 24 | +vec3 calculateSunPositionFromDirectionalLight() |
| 25 | +{ |
| 26 | + for (int i = 0; i < ssbo_Lights.length(); ++i) |
| 27 | + { |
| 28 | + const mat4 light = ssbo_Lights[i]; |
| 29 | + const int lightType = int(light[3][0]); |
| 30 | + |
| 31 | + if (lightType == 1) |
| 32 | + { |
| 33 | + vec3 lightDirection = -light[1].xyz; |
| 34 | + return normalize(lightDirection); |
| 35 | + } |
| 36 | + } |
| 37 | + |
| 38 | + // If no directional light is found, use the sun position uniform |
| 39 | + return u_SunPosition; |
| 40 | +} |
| 41 | + |
| 42 | +void main() |
| 43 | +{ |
| 44 | + vs_out.FragPos = geo_Pos; |
| 45 | + |
| 46 | +#if defined(DYNAMIC_SUN_POSITION) |
| 47 | + vs_out.SunPosition = calculateSunPositionFromDirectionalLight(); |
| 48 | +#else |
| 49 | + vs_out.SunPosition = u_SunPosition; |
| 50 | +#endif |
| 51 | + |
| 52 | + gl_Position = ubo_Projection * ubo_View * vec4(ubo_ViewPos + vs_out.FragPos, 1.0); |
| 53 | +} |
| 54 | + |
| 55 | +#shader fragment |
| 56 | +#version 450 core |
| 57 | + |
| 58 | +#include ":Shaders/Common/Buffers/EngineUBO.ovfxh" |
| 59 | +#include ":Shaders/Common/Utils.ovfxh" |
| 60 | + |
| 61 | +in VS_OUT |
| 62 | +{ |
| 63 | + vec3 FragPos; |
| 64 | + flat vec3 SunPosition; |
| 65 | +} fs_in; |
| 66 | + |
| 67 | +#if defined(PICKING_PASS) |
| 68 | +uniform vec4 _PickingColor; |
| 69 | +#endif |
| 70 | + |
| 71 | +#if defined(OUTLINE_PASS) |
| 72 | +uniform vec4 _OutlineColor; |
| 73 | +#endif |
| 74 | + |
| 75 | +uniform float u_SunIntensity = 22.0; // Sun intensity |
| 76 | +uniform float u_MiePreferredScatteringDirection = 0.758; // Mie preferred scattering direction |
| 77 | + |
| 78 | +const vec3 kRayOrigin = vec3(0.0, 6372e3, 0.0); // Ray origin |
| 79 | +const float kPlanetRadius = 6371e3; // Radius of the planet in meters |
| 80 | +const float kAtmosphereRadius = 6471e3; // Radius of the atmosphere in meters |
| 81 | +const vec3 kRayleighScattering = vec3(5.5e-6, 13.0e-6, 22.4e-6); // Rayleigh scattering coefficient |
| 82 | +const float kMieScattering = 21e-6; // Mie scattering coefficient |
| 83 | +const float kRayleighScaleHeight = 8e3; // Rayleigh scale height |
| 84 | +const float kMieScaleHeight = 1.2e3; // Mie scale height |
| 85 | + |
| 86 | +out vec4 FRAGMENT_COLOR; |
| 87 | + |
| 88 | +// [ATMOSHPERIC SCATTERING] Section Start |
| 89 | +// From https://github.com/wwwtyro/glsl-atmosphere/blob/master/index.glsl |
| 90 | +#define PI 3.141592 |
| 91 | +#define iSteps 16 |
| 92 | +#define jSteps 8 |
| 93 | + |
| 94 | +vec2 rsi(vec3 r0, vec3 rd, float sr) { |
| 95 | + // ray-sphere intersection that assumes |
| 96 | + // the sphere is centered at the origin. |
| 97 | + // No intersection when result.x > result.y |
| 98 | + float a = dot(rd, rd); |
| 99 | + float b = 2.0 * dot(rd, r0); |
| 100 | + float c = dot(r0, r0) - (sr * sr); |
| 101 | + float d = (b*b) - 4.0*a*c; |
| 102 | + if (d < 0.0) return vec2(1e5,-1e5); |
| 103 | + return vec2( |
| 104 | + (-b - sqrt(d))/(2.0*a), |
| 105 | + (-b + sqrt(d))/(2.0*a) |
| 106 | + ); |
| 107 | +} |
| 108 | + |
| 109 | +vec3 atmosphere(vec3 r, vec3 r0, vec3 pSun, float iSun, float rPlanet, float rAtmos, vec3 kRlh, float kMie, float shRlh, float shMie, float g) { |
| 110 | + // Normalize the sun and view directions. |
| 111 | + pSun = normalize(pSun); |
| 112 | + r = normalize(r); |
| 113 | + |
| 114 | + // Calculate the step size of the primary ray. |
| 115 | + vec2 p = rsi(r0, r, rAtmos); |
| 116 | + if (p.x > p.y) return vec3(0,0,0); |
| 117 | + p.y = min(p.y, rsi(r0, r, rPlanet).x); |
| 118 | + float iStepSize = (p.y - p.x) / float(iSteps); |
| 119 | + |
| 120 | + // Initialize the primary ray time. |
| 121 | + float iTime = 0.0; |
| 122 | + |
| 123 | + // Initialize accumulators for Rayleigh and Mie scattering. |
| 124 | + vec3 totalRlh = vec3(0,0,0); |
| 125 | + vec3 totalMie = vec3(0,0,0); |
| 126 | + |
| 127 | + // Initialize optical depth accumulators for the primary ray. |
| 128 | + float iOdRlh = 0.0; |
| 129 | + float iOdMie = 0.0; |
| 130 | + |
| 131 | + // Calculate the Rayleigh and Mie phases. |
| 132 | + float mu = dot(r, pSun); |
| 133 | + float mumu = mu * mu; |
| 134 | + float gg = g * g; |
| 135 | + float pRlh = 3.0 / (16.0 * PI) * (1.0 + mumu); |
| 136 | + float pMie = 3.0 / (8.0 * PI) * ((1.0 - gg) * (mumu + 1.0)) / (pow(1.0 + gg - 2.0 * mu * g, 1.5) * (2.0 + gg)); |
| 137 | + |
| 138 | + // Sample the primary ray. |
| 139 | + for (int i = 0; i < iSteps; i++) { |
| 140 | + |
| 141 | + // Calculate the primary ray sample position. |
| 142 | + vec3 iPos = r0 + r * (iTime + iStepSize * 0.5); |
| 143 | + |
| 144 | + // Calculate the height of the sample. |
| 145 | + float iHeight = length(iPos) - rPlanet; |
| 146 | + |
| 147 | + // Calculate the optical depth of the Rayleigh and Mie scattering for this step. |
| 148 | + float odStepRlh = exp(-iHeight / shRlh) * iStepSize; |
| 149 | + float odStepMie = exp(-iHeight / shMie) * iStepSize; |
| 150 | + |
| 151 | + // Accumulate optical depth. |
| 152 | + iOdRlh += odStepRlh; |
| 153 | + iOdMie += odStepMie; |
| 154 | + |
| 155 | + // Calculate the step size of the secondary ray. |
| 156 | + float jStepSize = rsi(iPos, pSun, rAtmos).y / float(jSteps); |
| 157 | + |
| 158 | + // Initialize the secondary ray time. |
| 159 | + float jTime = 0.0; |
| 160 | + |
| 161 | + // Initialize optical depth accumulators for the secondary ray. |
| 162 | + float jOdRlh = 0.0; |
| 163 | + float jOdMie = 0.0; |
| 164 | + |
| 165 | + // Sample the secondary ray. |
| 166 | + for (int j = 0; j < jSteps; j++) { |
| 167 | + |
| 168 | + // Calculate the secondary ray sample position. |
| 169 | + vec3 jPos = iPos + pSun * (jTime + jStepSize * 0.5); |
| 170 | + |
| 171 | + // Calculate the height of the sample. |
| 172 | + float jHeight = length(jPos) - rPlanet; |
| 173 | + |
| 174 | + // Accumulate the optical depth. |
| 175 | + jOdRlh += exp(-jHeight / shRlh) * jStepSize; |
| 176 | + jOdMie += exp(-jHeight / shMie) * jStepSize; |
| 177 | + |
| 178 | + // Increment the secondary ray time. |
| 179 | + jTime += jStepSize; |
| 180 | + } |
| 181 | + |
| 182 | + // Calculate attenuation. |
| 183 | + vec3 attn = exp(-(kMie * (iOdMie + jOdMie) + kRlh * (iOdRlh + jOdRlh))); |
| 184 | + |
| 185 | + // Accumulate scattering. |
| 186 | + totalRlh += odStepRlh * attn; |
| 187 | + totalMie += odStepMie * attn; |
| 188 | + |
| 189 | + // Increment the primary ray time. |
| 190 | + iTime += iStepSize; |
| 191 | + |
| 192 | + } |
| 193 | + |
| 194 | + // Calculate and return the final color. |
| 195 | + return iSun * (pRlh * kRlh * totalRlh + pMie * kMie * totalMie); |
| 196 | +} |
| 197 | +// [ATMOSHPERIC SCATTERING] Section End |
| 198 | + |
| 199 | +void main() |
| 200 | +{ |
| 201 | +#if defined(PICKING_PASS) |
| 202 | + // The atmosphere cannot be picked. |
| 203 | + discard; |
| 204 | +#elif defined(OUTLINE_PASS) |
| 205 | + // The atmosphere cannot be outlined. |
| 206 | + discard; |
| 207 | +#else |
| 208 | + |
| 209 | + vec3 color = atmosphere( |
| 210 | + normalize(fs_in.FragPos), // normalized ray direction |
| 211 | + kRayOrigin, // ray origin |
| 212 | + fs_in.SunPosition, // position of the sun |
| 213 | + u_SunIntensity, // intensity of the sun |
| 214 | + kPlanetRadius, // radius of the planet in meters |
| 215 | + kAtmosphereRadius, // radius of the atmosphere in meters |
| 216 | + kRayleighScattering, // Rayleigh scattering coefficient |
| 217 | + kMieScattering, // Mie scattering coefficient |
| 218 | + kRayleighScaleHeight, // Rayleigh scale height |
| 219 | + kMieScaleHeight, // Mie scale height |
| 220 | + u_MiePreferredScatteringDirection // Mie preferred scattering direction |
| 221 | + ); |
| 222 | + |
| 223 | + FRAGMENT_COLOR = vec4(color, 1.0); |
| 224 | +#endif |
| 225 | +} |
0 commit comments