struct Material {
    vec3 albedo;
    float roughness;
    float metalness;
    vec3 emissivity;
};

struct SceneResult {
    float dist;
    float materialIndex;
};

Material mWhiteLight = Material(vec3(0), 1, 0, vec3(2));
Material mIron = Material(vec3(0.7686, 0.7804, 0.7804), 0.2, 1, vec3(0));
Material mPerfectMirror = Material(vec3(0), 0, 0, vec3(0));
Material mBlueishMirror = Material(vec3(0, 0, 0.5), 0.1, 1, vec3(0));
Material mSky(vec3 p) {
    Material m = Material(vec3(0), 1, 0, vec3(0.0003, 0.00001, 0.001));
    m.emissivity *= 0.1 * pow(abs(p.z) + 10 * cos(p.x * 0.5), 3);;
    return m;
}

Material mixMaterials(Material m1, Material m2, float k)
{
    return Material(mix(m1.albedo, m2.albedo, k),
                    mix(m1.roughness, m2.roughness, k),
                    mix(m1.metalness, m2.metalness, k),
                    mix(m1.emissivity, m2.emissivity, k));
}

SceneResult opU(SceneResult r1, SceneResult r2) {
    return r2.dist < r1.dist ? r2 : r1;
}

SceneResult opI(SceneResult r1, SceneResult r2) {
    return r2.dist > r1.dist ? r2 : r1;
}

SceneResult opS(SceneResult r1, SceneResult r2) {
    return r2.dist > -r1.dist ? r2 : SceneResult(-r1.dist, r1.materialIndex);
}
