diff --git a/common/bspfile.cc b/common/bspfile.cc index 4d3ea127..77a88a36 100644 --- a/common/bspfile.cc +++ b/common/bspfile.cc @@ -1782,21 +1782,19 @@ const bspversion_t bspver_qbism{Q2_QBISMIDENT, Q2_BSPVERSION, "qbism", "Quake II }, &gamedef_q2}; + bool surfflags_t::needs_write() const { - return no_dirt || no_shadow || no_bounce || no_minlight || no_expand || no_phong || light_ignore || - !surflight_rescale || phong_angle || phong_angle_concave || phong_group || minlight || - !qv::emptyExact(minlight_color) || light_alpha || maxlight || lightcolorscale != 1.0 || surflight_group || - world_units_per_luxel || object_channel_mask || surflight_minlight_scale; + return as_tuple(*this) != as_tuple(surfflags_t()); } static auto as_tuple(const surfflags_t &flags) { return std::tie(flags.native, flags.is_nodraw, flags.is_hintskip, flags.is_hint, flags.no_dirt, flags.no_shadow, flags.no_bounce, flags.no_minlight, flags.no_expand, flags.no_phong, flags.light_ignore, - flags.surflight_rescale, flags.phong_angle, flags.phong_angle_concave, flags.phong_group, flags.minlight, + flags.surflight_rescale, flags.surflight_color, flags.surflight_minlight_scale, flags.phong_angle, flags.phong_angle_concave, flags.phong_group, flags.minlight, flags.minlight_color, flags.light_alpha, flags.maxlight, flags.lightcolorscale, flags.surflight_group, - flags.world_units_per_luxel, flags.object_channel_mask, flags.surflight_minlight_scale); + flags.world_units_per_luxel, flags.object_channel_mask); } bool surfflags_t::operator<(const surfflags_t &other) const diff --git a/common/imglib.cc b/common/imglib.cc index 5688d9ac..5509dbb8 100644 --- a/common/imglib.cc +++ b/common/imglib.cc @@ -516,6 +516,14 @@ std::optional load_wal_json_meta( texture_meta meta{}; + { + fs::path wal = fs::path(name).replace_extension(".wal"); + + if (auto wal_file = fs::load(wal)) + if (auto wal_meta = load_wal_meta(wal.string(), wal_file, game)) + meta = *wal_meta; + } + if (json.contains("width") && json["width"].is_number_integer()) { meta.width = json["width"].get(); } diff --git a/include/common/bspfile.hh b/include/common/bspfile.hh index 06baf4d7..c008360b 100644 --- a/include/common/bspfile.hh +++ b/include/common/bspfile.hh @@ -192,6 +192,12 @@ struct surfflags_t // normal if false, use a more natural angle falloff of 0% at 90 degrees bool surflight_rescale = true; + // override the textures' surflight color + std::optional surflight_color; + + // surface light rescaling + std::optional surflight_minlight_scale; + // if non zero, enables phong shading and gives the angle threshold to use vec_t phong_angle; @@ -224,8 +230,6 @@ struct surfflags_t std::optional object_channel_mask; - std::optional surflight_minlight_scale; - bool needs_write() const; public: diff --git a/include/common/imglib.hh b/include/common/imglib.hh index 129679b7..3a8cf0fd 100644 --- a/include/common/imglib.hh +++ b/include/common/imglib.hh @@ -102,7 +102,11 @@ constexpr struct ext id; decltype(load_wal) *loader; } extension_list[] = { - {".tga", ext::TGA, load_tga}, {".wal", ext::WAL, load_wal}, {".mip", ext::MIP, load_mip}, {"", ext::MIP, load_mip}}; + {".tga", ext::TGA, load_tga}, + {".wal", ext::WAL, load_wal}, + {".mip", ext::MIP, load_mip}, + {"", ext::MIP, load_mip} +}; // Attempt to load a texture from the specified name. std::tuple, fs::resolve_result, fs::data> load_texture( @@ -127,7 +131,9 @@ constexpr struct meta_ext id; decltype(load_wal_meta) *loader; } meta_extension_list[] = { - {".wal", meta_ext::WAL, load_wal_meta}, {".wal_json", meta_ext::WAL_JSON, load_wal_json_meta}}; + {".wal_json", meta_ext::WAL_JSON, load_wal_json_meta}, + {".wal", meta_ext::WAL, load_wal_meta} +}; // Attempt to load a texture meta from the specified name. std::tuple, fs::resolve_result, fs::data> load_texture_meta( diff --git a/include/light/entities.hh b/include/light/entities.hh index 86b46a94..cbc65f69 100644 --- a/include/light/entities.hh +++ b/include/light/entities.hh @@ -100,7 +100,7 @@ public: settings::setting_string suntexture; settings::setting_bool nostaticlight; settings::setting_int32 surflight_group; - settings::setting_scalar surface_minlight_scale; + settings::setting_scalar surflight_minlight_scale; settings::setting_int32 light_channel_mask; settings::setting_int32 shadow_channel_mask; settings::setting_bool nonudge; diff --git a/include/light/light.hh b/include/light/light.hh index 4fb1570c..12e1813b 100644 --- a/include/light/light.hh +++ b/include/light/light.hh @@ -102,7 +102,7 @@ struct lightsurf_t const mface_t *face; /* these take precedence the values in modelinfo */ vec_t minlight, maxlight, lightcolorscale = 1.0; - vec_t surflight_minlight_scale; + vec_t surflight_minlight_scale = 1.0; qvec3d minlight_color; bool nodirt, minlightMottle; int32_t object_channel_mask; @@ -269,8 +269,8 @@ public: setting_scalar global_anglescale; setting_scalar lightmapgamma; setting_bool addminlight; - setting_scalar minlightMottle; setting_scalar minlight; + setting_scalar minlightMottle; setting_scalar maxlight; setting_color minlight_color; setting_bool spotlightautofalloff; diff --git a/include/light/surflight.hh b/include/light/surflight.hh index a4d35a8c..be6d7f3a 100644 --- a/include/light/surflight.hh +++ b/include/light/surflight.hh @@ -47,6 +47,7 @@ struct surfacelight_t // rescale faces to account for perpendicular lights bool rescale; + std::optional minlight_scale; }; class light_t; diff --git a/light/entities.cc b/light/entities.cc index 9046ba9b..59026cb3 100644 --- a/light/entities.cc +++ b/light/entities.cc @@ -112,7 +112,7 @@ light_t::light_t() suntexture{this, "suntexture", ""}, nostaticlight{this, "nostaticlight", false}, surflight_group{this, "surflight_group", 0}, - surface_minlight_scale{this, "surface_minlight_scale", 64.f}, + surflight_minlight_scale{this, "surflight_minlight_scale", 64.f}, light_channel_mask{this, "light_channel_mask", CHANNEL_MASK_DEFAULT}, shadow_channel_mask{this, "shadow_channel_mask", CHANNEL_MASK_DEFAULT}, nonudge{this, "nonudge", false} @@ -338,10 +338,10 @@ static void CheckEntityFields(const mbsp_t *bsp, const settings::worldspawn_keys entity->shadow_channel_mask.setValue(entity->light_channel_mask.value(), settings::source::DEFAULT); } - if (!entity->surface_minlight_scale.isChanged()) { + if (!entity->surflight_minlight_scale.isChanged()) { if (bsp->loadversion->game->id != GAME_QUAKE_II) { // TODO: also use 1.0 for Q2? - entity->surface_minlight_scale.setValue(1.0f, settings::source::DEFAULT); + entity->surflight_minlight_scale.setValue(1.0f, settings::source::DEFAULT); } } } diff --git a/light/light.cc b/light/light.cc index d608e60d..e50574a5 100644 --- a/light/light.cc +++ b/light/light.cc @@ -164,8 +164,8 @@ worldspawn_keys::worldspawn_keys() lightmapgamma{this, "gamma", 1.0, 0.0, 100.0, &worldspawn_group}, addminlight{this, "addmin", false, &worldspawn_group}, minlight{this, {"light", "minlight"}, 0, &worldspawn_group}, - maxlight{this, "maxlight", 0, &worldspawn_group}, minlightMottle{this, "minlightMottle", false}, + maxlight{this, "maxlight", 0, &worldspawn_group}, minlight_color{this, {"minlight_color", "mincolor"}, 255.0, 255.0, 255.0, &worldspawn_group}, spotlightautofalloff{this, "spotlightautofalloff", false, &worldspawn_group}, compilerstyle_start{this, "compilerstyle_start", 32, &worldspawn_group}, @@ -1119,6 +1119,12 @@ static void LoadExtendedTexinfoFlags(const fs::path &sourcefilename, const mbsp_ if (val.contains("surflight_rescale")) { flags.surflight_rescale = val.at("surflight_rescale").get(); } + if (val.contains("surflight_color")) { + flags.surflight_color = val.at("surflight_color").get(); + } + if (val.contains("surflight_minlight_scale")) { + flags.surflight_minlight_scale = val.at("surflight_minlight_scale").get(); + } if (val.contains("phong_angle")) { flags.phong_angle = val.at("phong_angle").get(); } diff --git a/light/ltface.cc b/light/ltface.cc index 95b8a619..ac43c73f 100644 --- a/light/ltface.cc +++ b/light/ltface.cc @@ -3239,7 +3239,7 @@ void DirectLightFace(const mbsp_t *bsp, lightsurf_t &lightsurf, const settings:: if (auto value = IsSurfaceLitFace(bsp, face)) { auto *entity = std::get<3>(value.value()); - float surface_minlight_scale = entity ? entity->surface_minlight_scale.value() : 64.f; + float surface_minlight_scale = entity ? entity->surflight_minlight_scale.value() : 64.f; surface_minlight_scale *= lightsurf.surflight_minlight_scale; minlight = std::get<0>(value.value()) * surface_minlight_scale; minlight_color = std::get<2>(value.value()); diff --git a/light/surflight.cc b/light/surflight.cc index 7a82d809..dc500483 100644 --- a/light/surflight.cc +++ b/light/surflight.cc @@ -83,15 +83,19 @@ static void MakeSurfaceLight(const mbsp_t *bsp, const settings::worldspawn_keys // Calculate emit color and intensity... - // Handle arghrad sky light settings http://www.bspquakeeditor.com/arghrad/sunlight.html#sky - if (!texture_color.has_value()) { - if (cfg.sky_surface.isChanged() && is_sky) { - // FIXME: this only handles the "_sky_surface" "red green blue" format. - // There are other more complex variants we could handle documented in the link above. - // FIXME: we require value to be nonzero, see the check above - not sure if this matches arghrad - texture_color = cfg.sky_surface.value() * 255.0; - } else { - texture_color = qvec3f(Face_LookupTextureColor(bsp, face)); + if (extended_flags.surflight_color.has_value()) { + texture_color = extended_flags.surflight_color.value(); + } else { + // Handle arghrad sky light settings http://www.bspquakeeditor.com/arghrad/sunlight.html#sky + if (!texture_color.has_value()) { + if (cfg.sky_surface.isChanged() && is_sky) { + // FIXME: this only handles the "_sky_surface" "red green blue" format. + // There are other more complex variants we could handle documented in the link above. + // FIXME: we require value to be nonzero, see the check above - not sure if this matches arghrad + texture_color = cfg.sky_surface.value() * 255.0; + } else { + texture_color = qvec3f(Face_LookupTextureColor(bsp, face)); + } } } @@ -118,6 +122,7 @@ static void MakeSurfaceLight(const mbsp_t *bsp, const settings::worldspawn_keys l.points = std::move(points); l.style = style; l.rescale = extended_flags.surflight_rescale; + l.minlight_scale = extended_flags.surflight_minlight_scale; // Init bbox... if (light_options.visapprox.value() == visapprox_t::RAYS) { diff --git a/qbsp/map.cc b/qbsp/map.cc index 526b0b94..d73accc0 100644 --- a/qbsp/map.cc +++ b/qbsp/map.cc @@ -619,6 +619,15 @@ static surfflags_t SurfFlagsForEntity( flags.light_ignore = true; if (entity.epairs.has("_surflight_rescale") && entity.epairs.get_int("_surflight_rescale") == 0) flags.surflight_rescale = false; + { + qvec3d color; + // FIXME: get_color, to match settings + if (entity.epairs.has("_surflight_color") && entity.epairs.get_vector("_surflight_color", color) == 3) { + flags.surflight_color = qvec3b{ (uint8_t) (color[0] * 255), (uint8_t) (color[1] * 255), (uint8_t) (color[2] * 255) }; + } + } + if (entity.epairs.has("_surflight_minlight_scale")) + flags.surflight_minlight_scale = entity.epairs.get_float("_surflight_minlight_scale"); // "_minlight_exclude", "_minlight_exclude2", "_minlight_exclude3"... for (int i = 0; i <= 9; i++) { @@ -715,10 +724,6 @@ static surfflags_t SurfFlagsForEntity( flags.object_channel_mask = entity.epairs.get_int("_object_channel_mask"); } - if (entity.epairs.has("_surflight_minlight_scale")) { - flags.surflight_minlight_scale = entity.epairs.get_float("_surflight_minlight_scale"); - } - // handle "_mincolor" { qvec3d mincolor{}; diff --git a/qbsp/writebsp.cc b/qbsp/writebsp.cc index 286286a2..5335771e 100644 --- a/qbsp/writebsp.cc +++ b/qbsp/writebsp.cc @@ -384,6 +384,12 @@ static void WriteExtendedTexinfoFlags(void) if (tx.flags.surflight_rescale == false) { t["surflight_rescale"] = tx.flags.surflight_rescale; } + if (tx.flags.surflight_color.has_value()) { + t["surflight_color"] = tx.flags.surflight_color.value(); + } + if (tx.flags.surflight_minlight_scale.has_value()) { + t["surflight_minlight_scale"] = tx.flags.surflight_minlight_scale.value(); + } if (tx.flags.phong_angle) { t["phong_angle"] = tx.flags.phong_angle; } @@ -417,9 +423,6 @@ static void WriteExtendedTexinfoFlags(void) if (tx.flags.object_channel_mask) { t["object_channel_mask"] = *tx.flags.object_channel_mask; } - if (tx.flags.surflight_minlight_scale) { - t["surflight_minlight_scale"] = *tx.flags.surflight_minlight_scale; - } texinfofile[std::to_string(*tx.outputnum)].swap(t); }