GfxSkyMaterial *gfx_sky_material_add_or_get (const std::string &name)
{
    GFX_MAT_SYNC;
    if (gfx_material_has_any(name)) {
        GfxSkyMaterial *mat = dynamic_cast<GfxSkyMaterial*>(material_db[name]);
        if (mat==NULL) GRIT_EXCEPT("Material already exists but is the wrong kind: \""+name+"\"");
        return mat;
    }
    return gfx_sky_material_add(name);
}
void gfx_sky_material_init (void)
{
    std::string vs = "out.position = transform_to_world(vert.position.xyz);\n";
    std::string fs = "var c = pma_decode(sample(mat.emissiveMap, vert.coord0.xy))\n"
                     "             * Float4(1, 1, 1, mat.alphaMask);\n"
                     "if (c.a <= mat.alphaRejectThreshold) discard;\n"
                     "out.colour = gamma_decode(c.rgb) * mat.emissiveMask;\n"
                     "out.alpha = c.a;\n";

    gfx_shader_make_or_reset("/system/SkyDefault", vs, "", fs, {
        { "alphaMask", GfxGslParam::float1(1.0f) },
        { "alphaRejectThreshold", GfxGslParam::float1(-1.0f) },
        { "emissiveMap", GfxGslParam(GFX_GSL_FLOAT_TEXTURE2, 1, 1, 1, 1) },
        { "emissiveMask", GfxGslParam::float3(1, 1, 1) },
    });

    gfx_sky_material_add("/system/SkyDefault");
}