codecraft 0.1.2

A minimalist 3D game engine built on parts of Bevy (ECS, color) with wgpu and winit: OpenPBR materials, clustered lighting, a yakui-drawn UI, audio and gamepad haptics; its binary maps any folder, and the symbols of its Rust files, as a 3D wall of boxes
Documentation
// Port of glsl/pathtracing/coat_brdf.glsl

struct Alphas {
    x: f32,
    y: f32,
};

fn coat_ndf_roughnesses() -> Alphas {
    let rsqr = sqr(coat_roughness);
    var a: Alphas;
    a.x = rsqr * sqrt(2.0 / (1.0 + sqr(1.0 - coat_anisotropy)));
    a.y = (1.0 - coat_anisotropy) * a.x;
    let min_alpha = 1.0e-4;
    a.x = max(min_alpha, a.x);
    a.y = max(min_alpha, a.y);
    return a;
}

fn coat_brdf_evaluate(winputL: vec3<f32>, woutputL: vec3<f32>) -> BsdfEval {
    var out: BsdfEval;
    out.f = vec3<f32>(0.0);
    out.pdf = 0.0;
    let transmitted = woutputL.z * winputL.z < 0.0;
    if (transmitted) { return out; }

    let external_reflection = winputL.z > 0.0;
    let n_exterior = 1.0;
    let n_interior = coat_ior;
    let eta_ti_refl = select(n_exterior / n_interior, n_interior / n_exterior, external_reflection);
    if (abs(eta_ti_refl - 1.0) < IOR_EPSILON) { return out; }

    let a = coat_ndf_roughnesses();
    let mR = normalize(woutputL + winputL);

    let D = ggx_ndf_eval(mR, a.x, a.y);
    let DV = D * ggx_G1(winputL, a.x, a.y) * abs(dot(winputL, mR)) / max(DENOM_TOLERANCE, abs(winputL.z));
    let F = FresnelDielectricReflectance(abs(dot(winputL, mR)), eta_ti_refl);
    let dwh_dwo = 1.0 / max(abs(4.0 * dot(winputL, mR)), DENOM_TOLERANCE);
    out.pdf = DV * dwh_dwo;
    out.f = vec3<f32>(F) * D * ggx_G2(winputL, woutputL, a.x, a.y) / max(4.0 * abs(woutputL.z) * abs(winputL.z), DENOM_TOLERANCE);
    return out;
}

fn coat_brdf_sample(winputL: vec3<f32>) -> BsdfSample {
    var out: BsdfSample;
    out.f = vec3<f32>(0.0);
    out.woutputL = vec3<f32>(0.0, 0.0, 1.0);
    out.pdf = 0.0;
    let external_reflection = winputL.z > 0.0;
    let n_exterior = 1.0;
    let n_interior = coat_ior;
    let eta_ti_refl = select(n_exterior / n_interior, n_interior / n_exterior, external_reflection);
    if (abs(eta_ti_refl - 1.0) < IOR_EPSILON) { return out; }

    let a = coat_ndf_roughnesses();
    if (winputL.z <= 0.0) { return out; }
    let mR = ggx_ndf_sample(winputL, a.x, a.y);

    let woutputL = -winputL + 2.0 * dot(winputL, mR) * mR;
    out.woutputL = woutputL;
    if (winputL.z * woutputL.z < FLT_EPSILON) { return out; }

    let D = ggx_ndf_eval(mR, a.x, a.y);
    let DV = D * ggx_G1(winputL, a.x, a.y) * abs(dot(winputL, mR)) / max(DENOM_TOLERANCE, abs(winputL.z));
    let G2 = ggx_G2(winputL, woutputL, a.x, a.y);
    let dwh_dwo = 1.0 / max(abs(4.0 * dot(winputL, mR)), DENOM_TOLERANCE);
    out.pdf = DV * dwh_dwo;
    let F = FresnelDielectricReflectance(abs(dot(winputL, mR)), eta_ti_refl);
    out.f = vec3<f32>(F) * D * G2 / max(4.0 * abs(woutputL.z) * abs(winputL.z), DENOM_TOLERANCE);
    return out;
}

// Directional albedo of the coat's reflection lobe.
//
// Tabulated on the CPU (`energy.rs`, table `ENERGY_COAT_R`) rather than
// estimated with the viewer's one-sample Monte-Carlo draw. The estimate was
// wrong in a way that does not look like noise in the image: this albedo sets
// the coat layering weight, the lobe sampling probabilities *and* -- at the
// visible surface -- the denoiser's specular and diffuse demodulation guides.
// A guide that flickers frame to frame makes a denoiser dividing by it shake
// the whole image, which is exactly the failure 5fb5428 chased down for the
// props' wireframe. It also cost a GGX sample and two `rand()` draws at every
// vertex of every path.
//
// `coat_brdf_sample` returns nothing for a direction below the surface, so the
// albedo seen from inside is zero and only the outside table is needed.
fn coat_brdf_albedo(winputL: vec3<f32>) -> vec3<f32> {
    if (abs(coat_ior - 1.0) < IOR_EPSILON) { return vec3<f32>(0.0); }
    if (winputL.z <= 0.0) { return vec3<f32>(0.0); }
    return vec3<f32>(energy_table_lookup(ENERGY_COAT_R, winputL.z));
}