/* * Render the aerial perspective LUT, similar to * "A Scalable and Production Ready Sky and Atmosphere Rendering Technique" * by Sébastien Hillaire (2020). * * Unlike the paper, we are using a tiled 2D texture instead of a true 3D * texture. For some reason the overhead of rendering to a texture many times * (the depth of the 3D texture) seems to be too high, probably because OSG is * not sharing state between those passes. */ #version 330 core layout(location = 0) out vec4 fragColor; in vec2 texcoord; uniform sampler2D transmittance_lut; uniform mat4 fg_ViewMatrixInverse; uniform vec3 fg_CameraPositionCart; uniform vec3 fg_SunDirectionWorld; const float AP_SLICE_COUNT = 32.0; const float AP_MAX_DEPTH = 128000.0; const int AERIAL_PERSPECTIVE_STEPS = 10; const float RADIUS_OFFSET = 10.0; // pos_from_depth.glsl vec3 get_view_space_from_depth(vec2 uv, float depth); // atmos.glsl float get_earth_radius(); float get_ray_end(vec3 ray_origin, vec3 ray_dir, float t_max); vec4 compute_inscattering(in vec3 ray_origin, in vec3 ray_dir, in float t_max, in vec3 sun_dir, in int steps, in sampler2D transmittance_lut, out vec4 transmittance); // atmos_spectral.glsl vec4 get_sun_spectral_irradiance(); vec3 linear_srgb_from_spectral_samples(vec4 L); void main() { // Account for the depth slice we are currently in. Depth goes from 0 to // DEPTH_RANGE in a squared distribution. The first slice is not 0 since // that would waste a slice. float x = texcoord.x * AP_SLICE_COUNT; float slice = ceil(x); float w = slice / AP_SLICE_COUNT; // [0,1] float depth = w*w * AP_MAX_DEPTH; vec2 coord = vec2(fract(x), texcoord.y); vec3 frag_pos = get_view_space_from_depth(coord, 1.0); vec3 ray_dir = vec4(fg_ViewMatrixInverse * vec4(normalize(frag_pos), 0.0)).xyz; vec3 ray_origin = fg_CameraPositionCart; vec3 ray_end = ray_origin + ray_dir * depth; float t_max = depth; if (length(ray_end) <= (get_earth_radius() + RADIUS_OFFSET)) { ray_end = normalize(ray_end) * (get_earth_radius() + RADIUS_OFFSET + 1.0); ray_dir = ray_end - ray_origin; t_max = length(ray_dir); ray_dir /= t_max; } vec4 transmittance; vec4 L = compute_inscattering(ray_origin, ray_dir, t_max, fg_SunDirectionWorld, AERIAL_PERSPECTIVE_STEPS, transmittance_lut, transmittance); // In-scattering fragColor.rgb = linear_srgb_from_spectral_samples( L * get_sun_spectral_irradiance()); // Transmittance fragColor.a = dot(transmittance, vec4(0.25)); }