myth_render 0.3.0

Core rendering system for the Myth engine (render graph, pipeline, GPU management).
Documentation
// ============================================================================
// Hillaire 2020 Atmosphere — Pure Math Helpers
// ============================================================================

const PI: f32 = 3.14159265358979323846;
const TAU: f32 = 6.28318530717958647692;
const INV_ATAN: vec2<f32> = vec2<f32>(0.15915494, 0.31830989);

{$ include "entry/utility/atmosphere/transmittance_math" $}

fn direction_to_sky_view_uv(dir: vec3<f32>) -> vec2<f32> {
    let theta = asin(clamp(dir.y, -1.0, 1.0));

    var v: f32;
    if theta < 0.0 {
        let coord = sqrt(-theta / (PI * 0.5));
        v = 0.5 - 0.5 * coord;
    } else {
        let coord = sqrt(theta / (PI * 0.5));
        v = 0.5 + 0.5 * coord;
    }

    let phi = atan2(dir.x, dir.z);
    let u = (phi + PI) / TAU;
    return vec2<f32>(u, v);
}

fn sky_view_uv_to_direction(uv: vec2<f32>) -> vec3<f32> {
    let phi = uv.x * TAU - PI;

    let v = uv.y;
    var theta: f32;
    if v < 0.5 {
        let coord = 1.0 - 2.0 * v;
        theta = -(PI * 0.5) * coord * coord;
    } else {
        let coord = 2.0 * v - 1.0;
        theta = (PI * 0.5) * coord * coord;
    }

    let cos_theta = cos(theta);
    let sin_theta = sin(theta);

    return vec3<f32>(
        cos_theta * sin(phi),
        sin_theta,
        cos_theta * cos(phi)
    );
}

fn transmittance_lut_inv(
    uv: vec2<f32>,
    planet_radius: f32,
    atmosphere_radius: f32,
) -> vec2<f32> {
    let H = sqrt(max(
        0.0,
        atmosphere_radius * atmosphere_radius - planet_radius * planet_radius
    ));
    let rho = H * uv.y;
    let r = sqrt(rho * rho + planet_radius * planet_radius);
    let altitude = r - planet_radius;

    let d_min = atmosphere_radius - r;
    let d_max = rho + H;
    let d = d_min + uv.x * (d_max - d_min);

    let cos_zenith = clamp((H * H - rho * rho - d * d) / (2.0 * r * max(d, 1e-6)), -1.0, 1.0);
    return vec2<f32>(altitude, cos_zenith);
}

fn equirectangular_uv(dir: vec3<f32>) -> vec2<f32> {
    let eq_uv = vec2<f32>(
        atan2(dir.z, dir.x),
        acos(clamp(dir.y, -1.0, 1.0))
    );

    return vec2<f32>(
        eq_uv.x * INV_ATAN.x + 0.5,
        eq_uv.y * INV_ATAN.y
    );
}

fn rotate_about_axis(v: vec3<f32>, axis: vec3<f32>, angle: f32) -> vec3<f32> {
    let axis_length_sq = dot(axis, axis);
    if axis_length_sq <= 1e-8 {
        return v;
    }

    let n = axis * inverseSqrt(axis_length_sq);
    let s = sin(angle);
    let c = cos(angle);
    return v * c + cross(n, v) * s + n * dot(n, v) * (1.0 - c);
}