ponko 0.0.1

A fast 2D game engine for simulating millions of things: ECS on all cores, hot reload, an in-game inspector, AI-agent control, and a C++ API.
Documentation
// The built-in terrain material (Ctx::create_terrain_material): up to 8
// ground layers, blended by a weight map, their textures lined up with the
// world so neighbouring tiles match.
//
//   custom_array0: each layer's color         custom_array1: their normal maps
//   custom_array2: the weights, layer 0's RGBA for ground layers 0-3, layer
//                  1's for 4-7, stretched over the weight area
//   custom[0]: layers, normal strength, has normal maps (1/0)
//   custom[1], custom[2]: 1 / each layer's size in world units
//   custom[3]: the weight area's corner (x, z), then 1 / its size (x, z)

fn surface(s: Surface) -> Surface {
    var out = s;
    let count = i32(material.custom[0].x);
    // The weights, clamped half a texel in so the edges don't wrap around.
    let half = 0.5 / vec2<f32>(textureDimensions(custom_array2));
    let area = clamp((s.world.xz - material.custom[3].xy) * material.custom[3].zw, half, 1.0 - half);
    let last = i32(textureNumLayers(custom_array2)) - 1;
    let low = textureSample(custom_array2, material_sampler, area, 0);
    let high = textureSample(custom_array2, material_sampler, area, min(1, last));
    var weights = array<f32, 8>(low.x, low.y, low.z, low.w, high.x, high.y, high.z, high.w);
    let c1 = material.custom[1];
    let c2 = material.custom[2];
    let scales = array<f32, 8>(c1.x, c1.y, c1.z, c1.w, c2.x, c2.y, c2.z, c2.w);
    var total = 0.0;
    for (var i = 0; i < 8; i++) {
        if i >= count {
            weights[i] = 0.0;
        }
        total += weights[i];
    }
    if total <= 0.0 {
        weights[0] = 1.0; // nothing painted: the first layer
        total = 1.0;
    }
    let normals = material.custom[0].z > 0.5;
    // Triplanar: steep ground takes its textures from the sides (along X
    // and along Z) as well as from above, so cliffs don't stretch them.
    // Flat ground skips the side samples; the gradients are taken here,
    // outside the branches, so the skipped ones don't upset mip choice.
    let n = s.normal;
    var tri = pow(abs(n), vec3<f32>(4.0));
    tri /= tri.x + tri.y + tri.z;
    let dx = dpdx(s.world);
    let dy = dpdy(s.world);
    let flip = select(vec2<f32>(-1.0), vec2<f32>(1.0), n.xz >= vec2<f32>(0.0));
    var albedo = vec3<f32>(0.0);
    // The normal maps' tilt, in world space, added to the ground's normal.
    var tilt = vec3<f32>(0.0);
    var up = 0.0;
    for (var i = 0; i < count; i++) {
        let w = weights[i] / total;
        if w <= 0.0 {
            continue;
        }
        let k = scales[i];
        // From above: u along +X, the image's up along -Z.
        if tri.y > 0.02 {
            let uv = s.world.xz * k;
            albedo += textureSampleGrad(custom_array0, material_sampler, uv, i, dx.xz * k, dy.xz * k).rgb * (w * tri.y);
            if normals {
                let m = textureSampleGrad(custom_array1, material_sampler, uv, i, dx.xz * k, dy.xz * k).xyz * 2.0 - 1.0;
                tilt += vec3<f32>(m.x, 0.0, -m.y) * (w * tri.y);
                up += m.z * w * tri.y;
            }
        }
        // From the side facing X: u along Z (mirrored on the -X side), up along +Y.
        if tri.x > 0.02 {
            let uv = vec2<f32>(s.world.z * flip.x, -s.world.y) * k;
            let gx = vec2<f32>(dx.z * flip.x, -dx.y) * k;
            let gy = vec2<f32>(dy.z * flip.x, -dy.y) * k;
            albedo += textureSampleGrad(custom_array0, material_sampler, uv, i, gx, gy).rgb * (w * tri.x);
            if normals {
                let m = textureSampleGrad(custom_array1, material_sampler, uv, i, gx, gy).xyz * 2.0 - 1.0;
                tilt += vec3<f32>(0.0, m.y, m.x * flip.x) * (w * tri.x);
                up += m.z * w * tri.x;
            }
        }
        // From the side facing Z: u along X (mirrored on the +Z side), up along +Y.
        if tri.z > 0.02 {
            let uv = vec2<f32>(-s.world.x * flip.y, -s.world.y) * k;
            let gx = vec2<f32>(-dx.x * flip.y, -dx.y) * k;
            let gy = vec2<f32>(-dy.x * flip.y, -dy.y) * k;
            albedo += textureSampleGrad(custom_array0, material_sampler, uv, i, gx, gy).rgb * (w * tri.z);
            if normals {
                let m = textureSampleGrad(custom_array1, material_sampler, uv, i, gx, gy).xyz * 2.0 - 1.0;
                tilt += vec3<f32>(-m.x * flip.y, m.y, 0.0) * (w * tri.z);
                up += m.z * w * tri.z;
            }
        }
    }
    // The skipped samples' share, so the colors still add up.
    let kept = select(0.0, tri.y, tri.y > 0.02) + select(0.0, tri.x, tri.x > 0.02) + select(0.0, tri.z, tri.z > 0.02);
    out.albedo = s.albedo * albedo / max(kept, 1e-4);
    if normals {
        // The tilt along the surface only, scaled by the strength.
        let along = (tilt - n * dot(tilt, n)) / max(kept, 1e-4);
        out.normal = normalize(n * max(up / max(kept, 1e-4), 1e-3) + along * material.custom[0].y);
    }
    return out;
}