Skip to main content

FILM

Constant FILM 

Source
pub const FILM: &str = "const FILM_SAMPLES: u32 = 24u;\nconst FILM_NU: f32 = 0.0013513514;\nconst FILM_STEP: f32 = 5.2728312e-05;\nconst FILM_WEIGHTS = array<vec3f, 24>(\n    vec3f(0.00049457996, 6.4814856e-05, 0.00010619715),\n    vec3f(0.002711246, -0.0001910701, -0.00037234355),\n    vec3f(0.01515967, 0.00028906547, 0.00012810956),\n    vec3f(0.06871473, -0.006184027, -0.00132862),\n    vec3f(0.19734336, -0.023679964, -0.0021775665),\n    vec3f(0.34738973, -0.02425651, -0.0060811765),\n    vec3f(0.3639468, 0.030559337, -0.014212847),\n    vec3f(0.23666404, 0.12368723, -0.022455476),\n    vec3f(0.08203017, 0.19909823, -0.027573477),\n    vec3f(-0.02977581, 0.22957213, -0.027457258),\n    vec3f(-0.091345824, 0.21851267, -0.020553917),\n    vec3f(-0.09862617, 0.16825487, -0.004000803),\n    vec3f(-0.071613036, 0.09727391, 0.021227753),\n    vec3f(-0.047891952, 0.05012592, 0.0553259),\n    vec3f(-0.024773184, 0.0206622, 0.112508),\n    vec3f(-0.01048964, -0.0007772626, 0.18015881),\n    vec3f(0.006274984, -0.01616651, 0.20803724),\n    vec3f(0.017522685, -0.023618592, 0.2038683),\n    vec3f(0.015057241, -0.021199455, 0.17673187),\n    vec3f(0.0156005435, -0.01456651, 0.10748986),\n    vec3f(0.0014033349, -0.00467564, 0.039753698),\n    vec3f(0.004500126, -0.0028086475, 0.014122494),\n    vec3f(-0.0012337026, 0.00018912496, 0.0036677718),\n    vec3f(0.00093538617, -0.00016521492, 0.0030877078),\n);\nconst FILM_EDGE: f32 = 0.46266436;\n\nstruct FilmStack {\n    lift: vec2f,\n    floor: vec2f,\n    cosine: vec2f,\n    sine: vec2f,\n}\n\nfn film_amplitudes(cos_i: f32, na: f32, nb: f32) -> vec3f {\n    let sin2 = (na / nb) * (na / nb) * (1.0 - cos_i * cos_i);\n    if (sin2 >= 1.0) {\n        return vec3f(1.0, 1.0, 0.0);\n    }\n    let cos_t = sqrt(1.0 - sin2);\n    let rs = (na * cos_i - nb * cos_t) / (na * cos_i + nb * cos_t);\n    let rp = (nb * cos_i - na * cos_t) / (nb * cos_i + na * cos_t);\n    return vec3f(rs, rp, cos_t);\n}\n\nfn film_stack(r12: vec2f, r23_re: vec2f, r23_im: vec2f) -> FilmStack {\n    let r23 = r23_re * r23_re + r23_im * r23_im;\n    let floor = vec2f(1.0) + r12 * r12 * r23;\n    return FilmStack(0.5 * (r12 * r12 + r23 - floor), floor, 2.0 * r12 * r23_re, -2.0 * r12 * r23_im);\n}\n\nfn film_pair(z: vec2f, stack: FilmStack) -> f32 {\n    return dot(stack.lift, vec2f(1.0) / (stack.floor + stack.cosine * z.x + stack.sine * z.y));\n}\n\nfn film_sum(path: f32, red: FilmStack, green: FilmStack, blue: FilmStack) -> vec3f {\n    let turn = vec2f(cos(path * FILM_STEP), sin(path * FILM_STEP));\n    var z = vec2f(cos(path * FILM_NU), sin(path * FILM_NU));\n    var weights = FILM_WEIGHTS;\n    var total = vec3f(1.0);\n    for (var k = 0u; k < FILM_SAMPLES; k++) {\n        total += weights[k] * vec3f(film_pair(z, red), film_pair(z, green), film_pair(z, blue));\n        z = vec2f(z.x * turn.x - z.y * turn.y, z.x * turn.y + z.y * turn.x);\n    }\n    return clamp(total, vec3f(0.0), vec3f(1.0));\n}\n\nfn film_sum_one(path: f32, stack: FilmStack) -> vec3f {\n    let turn = vec2f(cos(path * FILM_STEP), sin(path * FILM_STEP));\n    var z = vec2f(cos(path * FILM_NU), sin(path * FILM_NU));\n    var weights = FILM_WEIGHTS;\n    var total = vec3f(1.0);\n    for (var k = 0u; k < FILM_SAMPLES; k++) {\n        total += weights[k] * film_pair(z, stack);\n        z = vec2f(z.x * turn.x - z.y * turn.y, z.x * turn.y + z.y * turn.x);\n    }\n    return clamp(total, vec3f(0.0), vec3f(1.0));\n}\n\nfn film_dielectric(cosine: f32, thickness: f32, film_ior: f32, substrate_ior: f32) -> vec3f {\n    let nf = max(film_ior, 1.01);\n    let first = film_amplitudes(clamp(cosine, 0.0, 1.0), 1.0, nf);\n    let second = film_amplitudes(first.z, nf, max(substrate_ior, 1.0));\n    if (second.z <= 0.0) {\n        return vec3f(1.0);\n    }\n    let normal = cosine >= 1.0;\n    let stack = film_stack(select(first.xy, first.xx, normal), select(second.xy, second.xx, normal), vec2f(0.0));\n    return film_sum_one(12.566370614 * nf * thickness * first.z, stack);\n}\n\nfn film_conductor_ior(f0: f32) -> vec2f {\n    let r = clamp(f0, 0.0, 0.999);\n    let edge = mix(clamp(f0, 0.0, 1.0), 1.0, FILM_EDGE);\n    let root = sqrt(r);\n    let n = mix((1.0 + root) / (1.0 - root), (1.0 - r) / (1.0 + r), edge);\n    let k = sqrt(max((r * (n + 1.0) * (n + 1.0) - (n - 1.0) * (n - 1.0)) / (1.0 - r), 0.0));\n    return vec2f(n, k);\n}\n\nfn film_mul(a: vec2f, b: vec2f) -> vec2f {\n    return vec2f(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);\n}\n\nfn film_div(a: vec2f, b: vec2f) -> vec2f {\n    return vec2f(a.x * b.x + a.y * b.y, a.y * b.x - a.x * b.y) / dot(b, b);\n}\n\nfn film_root(a: vec2f) -> vec2f {\n    let size = length(a);\n    let re = sqrt(max(0.5 * (size + a.x), 0.0));\n    let im = sqrt(max(0.5 * (size - a.x), 0.0));\n    return vec2f(re, select(im, -im, a.y < 0.0));\n}\n\nfn film_metal_stack(r12: vec2f, cos_f: f32, nf: f32, f0: f32) -> FilmStack {\n    let metal = film_conductor_ior(f0);\n    let square = film_mul(metal, metal);\n    let u = film_root(square - vec2f(nf * nf * (1.0 - cos_f * cos_f), 0.0));\n    let across = vec2f(nf * cos_f, 0.0);\n    let rs = film_div(across - u, across + u);\n    if (cos_f >= 1.0) {\n        return film_stack(r12.xx, vec2f(rs.x), vec2f(rs.y));\n    }\n    let tilted = square * cos_f;\n    let rp = film_div(tilted - nf * u, tilted + nf * u);\n    return film_stack(r12, vec2f(rs.x, rp.x), vec2f(rs.y, rp.y));\n}\n\nfn film_conductor(cosine: f32, thickness: f32, film_ior: f32, f0: vec3f) -> vec3f {\n    let nf = max(film_ior, 1.01);\n    let first = film_amplitudes(clamp(cosine, 0.0, 1.0), 1.0, nf);\n    let red = film_metal_stack(first.xy, first.z, nf, f0.r);\n    let green = film_metal_stack(first.xy, first.z, nf, f0.g);\n    let blue = film_metal_stack(first.xy, first.z, nf, f0.b);\n    return film_sum(12.566370614 * nf * thickness * first.z, red, green, blue);\n}\n";