             }
         }
 
+        scene_shadow_length = max(0.0, abs(s_out - s_in));
+
         vec3 sky_irradiance;
         vec3 sun_irradiance = GetSunAndSkyIrradiance( point.xyz - earth_center, normal, sun_direction, sky_irradiance);
         scene_radiance = kSphereAlbedo * (1.0 / PI) * (sun_irradiance + sky_irradiance);
 
-        float shadow_length = max(0.0, abs(s_in - s_out)) * 2.0;
-        scene_shadow_length = shadow_length;
-
         vec3 transmittance;
-        vec3 in_scatter = GetSkyRadianceToPoint(camera - earth_center, point.xyz - earth_center, shadow_length, sun_direction, transmittance);
+        vec3 in_scatter = GetSkyRadianceToPoint(camera - earth_center, point.xyz - earth_center, scene_shadow_length, sun_direction, transmittance);
         scene_radiance = scene_radiance * transmittance + in_scatter;
     }
 
+    // Sphere
+    if(render_sphere)
+    {
+        GetSphereShadowInOut(view_direction, sun_direction, sphere_shadow_in, sphere_shadow_out);
+
+        p = camera - kSphereCenter;
+        p_dot_v = dot(p, view_direction);
+        p_dot_p = dot(p, p);
+        squared_radius = kSphereRadius * kSphereRadius;
+
+        float ray_sphere_center_squared_distance = p_dot_p - p_dot_v * p_dot_v;
+        float distance_to_intersection = -p_dot_v - sqrt(kSphereRadius * kSphereRadius - ray_sphere_center_squared_distance);
+        float sphere_depth = distance_to_intersection * view_direction.z;
+
+        if (render_sphere && ray_sphere_center_squared_distance <= squared_radius && abs(sphere_depth) < abs(scene_point.z))
+        {
+            sphere_alpha = 1.0;
+            vec3 point = camera + view_direction * distance_to_intersection;
+            vec3 normal = normalize(point - kSphereCenter);
+
+            vec4 shadow_uv = SHADOW_MATRIX * vec4(point, 1.0);
+            shadow_uv.xyz /= shadow_uv.w;
+            shadow_uv.xyz = shadow_uv.xyz * 0.5 + 0.5;
+            float scene_shadow = texture(texture_shadow, shadow_uv.xy, 0).x < shadow_uv.z ? 0.0 : 1.0;
+
+            vec3 sky_irradiance;
+            vec3 sun_irradiance = GetSunAndSkyIrradiance( point - earth_center, normal, sun_direction, sky_irradiance);
+
+            sphere_radiance = kSphereAlbedo * (1.0 / PI) * (sun_irradiance + sky_irradiance) * scene_shadow;
+
+            float shadow_length = max(0.0, min(sphere_shadow_out, distance_to_intersection) - sphere_shadow_in);
+            shadow_length = max(scene_shadow_length, shadow_length) * lightshaft_fadein_hack;
+
+            vec3 transmittance;
+            vec3 in_scatter = GetSkyRadianceToPoint(
+                    camera - earth_center,point - earth_center, shadow_length, sun_direction, transmittance);
+            sphere_radiance = sphere_radiance * transmittance + in_scatter;
+        }
+    }
+
     // Ground
-    vec3 p = camera - earth_center;
-    float p_dot_v = dot(p, view_direction);
-    float p_dot_p = dot(p, p);
-    float squared_radius = earth_center.y * earth_center.y;
-    float ray_earth_center_squared_distance = p_dot_p - p_dot_v * p_dot_v;
-
-    float ground_alpha = 0.0;
-    vec3 ground_radiance = vec3(0.0);
-    if (p_dot_v <= 0.0 && ray_earth_center_squared_distance <= squared_radius)
-    {
-        float distance_to_intersection = -p_dot_v - sqrt(squared_radius - ray_earth_center_squared_distance);
-        vec3 point = camera + view_direction * distance_to_intersection;
-        vec3 normal = normalize(point - earth_center);
-
-        vec3 sky_irradiance;
-        vec3 sun_irradiance = GetSunAndSkyIrradiance(point - earth_center, normal, sun_direction, sky_irradiance);
-        ground_radiance = kGroundAlbedo * (1.0 / PI) * (
-            sun_irradiance * GetSunVisibility(point, sun_direction) +
-            sky_irradiance * GetSkyVisibility(point));
-
-        float shadow_length = max(scene_shadow_length, max(0.0, min(shadow_out, distance_to_intersection) - shadow_in)) * lightshaft_fadein_hack;
-        vec3 transmittance;
-        vec3 in_scatter = GetSkyRadianceToPoint(camera - earth_center, point - earth_center, shadow_length, sun_direction, transmittance);
-        ground_radiance = ground_radiance * transmittance + in_scatter;
-        ground_alpha = 1.0;
-
-        // shadow_result = max(0.0, min(shadow_out, distance_to_intersection) - shadow_in);
-    }
-
-    // Sphere
-    p = camera - kSphereCenter;
-    p_dot_v = dot(p, view_direction);
-    p_dot_p = dot(p, p);
-    squared_radius = kSphereRadius * kSphereRadius;
-    float ray_sphere_center_squared_distance = p_dot_p - p_dot_v * p_dot_v;
-    float distance_to_intersection = -p_dot_v - sqrt(kSphereRadius * kSphereRadius - ray_sphere_center_squared_distance);
-    float sphere_depth = distance_to_intersection * view_direction.z;
-
-    float sphere_alpha = 0.0;
-    vec3 sphere_radiance = vec3(0.0);
-    if (ray_sphere_center_squared_distance <= squared_radius && abs(sphere_depth) < abs(scene_point.z))
-    {
-        sphere_alpha = 1.0;
-        vec3 point = camera + view_direction * distance_to_intersection;
-        vec3 normal = normalize(point - kSphereCenter);
-
-        vec3 sky_irradiance;
-        vec3 sun_irradiance = GetSunAndSkyIrradiance( point - earth_center, normal, sun_direction, sky_irradiance);
-        sphere_radiance = kSphereAlbedo * (1.0 / PI) * (sun_irradiance + sky_irradiance);
-
-        float shadow_length = max(scene_shadow_length, max(0.0, min(shadow_out, distance_to_intersection) - shadow_in)) * lightshaft_fadein_hack;
-        vec3 transmittance;
-        vec3 in_scatter = GetSkyRadianceToPoint(camera - earth_center, point - earth_center, shadow_length, sun_direction, transmittance);
-        sphere_radiance = sphere_radiance * transmittance + in_scatter;
-
-        // shadow_result = max(0.0, min(shadow_out, distance_to_intersection) - shadow_in);
-    }
-
-
+    if(render_ground)
+    {
+        p = camera - earth_center;
+        p_dot_v = dot(p, view_direction);
+        p_dot_p = dot(p, p);
+        squared_radius = earth_radius * earth_radius;
+
+        float ray_earth_center_squared_distance = p_dot_p - p_dot_v * p_dot_v;
+        if (p_dot_v <= 0.0 && ray_earth_center_squared_distance <= squared_radius)
+        {
+            float distance_to_intersection = -p_dot_v - sqrt(squared_radius - ray_earth_center_squared_distance);
+            vec3 point = camera + view_direction * distance_to_intersection;
+            vec3 normal = normalize(point - earth_center);
+
+            vec4 shadow_uv = SHADOW_MATRIX * vec4(point, 1.0);
+            shadow_uv.xyz /= shadow_uv.w;
+            shadow_uv.xyz = shadow_uv.xyz * 0.5 + 0.5;
+            float scene_shadow = texture(texture_shadow, shadow_uv.xy, 0).x < shadow_uv.z ? 0.0 : 1.0;
+
+            vec3 sky_irradiance;
+            vec3 sun_irradiance = GetSunAndSkyIrradiance(point - earth_center, normal, sun_direction, sky_irradiance);
+
+            ground_radiance = kGroundAlbedo * (1.0 / PI) *
+                (sun_irradiance * GetSunVisibility(point, sun_direction) +
+                sky_irradiance * GetSkyVisibility(point)) * scene_shadow;
+
+            float shadow_length = max(0.0, min(sphere_shadow_out, distance_to_intersection) - sphere_shadow_in);
+            shadow_length = max(scene_shadow_length, shadow_length) * lightshaft_fadein_hack;
+
+            vec3 transmittance;
+            vec3 in_scatter = GetSkyRadianceToPoint(camera - earth_center, point - earth_center, shadow_length, sun_direction, transmittance);
+            ground_radiance = ground_radiance * transmittance + in_scatter;
+            ground_alpha = 1.0;
+        }
+    }
 
     // Sky
-    float shadow_length = max(scene_shadow_length, max(0.0, shadow_out - shadow_in)) * lightshaft_fadein_hack;
+    float shadow_length = max(scene_shadow_length, max(0.0, sphere_shadow_out - sphere_shadow_in)) * lightshaft_fadein_hack;
+
     vec3 transmittance;
-    vec3 radiance = GetSkyRadiance(camera - earth_center, view_direction, shadow_length, sun_direction, transmittance);
+    vec3 radiance = GetSkyRadiance(camera * ratio - earth_center, view_direction, shadow_length, sun_direction, transmittance);
 
     // Sun
     if (dot(view_direction, sun_direction) > sun_size.y)


            if(false == shadow_enter && s <= shadow_uv.z)
            {
                shadow_enter = true;
                s_in = world_pos.z;
                continue;

uniform vec3 SUN_RADIANCE_TO_LUMINANCE;


vec3 GetSolarRadiance()
{
    return ATMOSPHERE.solar_irradiance /
