From 462a152a66d26aac85370078d1992f0ee94d9a5f Mon Sep 17 00:00:00 2001 From: Aaron Kimbrell Date: Mon, 28 Sep 2026 12:07:58 -0500 Subject: [PATCH] feat(ugc): metal, brushed steel and glow shaders on by default Tested in game: shader_metal 88, shader_brushed 89 and shader_glow 46 are now the defaults, with brushed_colors defaulting to the drum lacquered 298,300,1002,1004 and transparent_colors to 129. Empty list settings take the default; none turns a list off. The three shader ids set to 0 still write live's all-plastic models byte for byte. Co-Authored-By: Claude Opus 5.5 --- dDashboardServer/routes/SettingsCatalog.cpp | 10 +++++----- dUgcServer/UgcServer.cpp | 14 +++++++++----- docs/UgcServer.md | 21 +++++++++++---------- resources/ugcconfig.ini | 21 +++++++++++---------- 4 files changed, 36 insertions(+), 30 deletions(-) diff --git a/dDashboardServer/routes/SettingsCatalog.cpp b/dDashboardServer/routes/SettingsCatalog.cpp index dc5fc4666..7b91c6edb 100644 --- a/dDashboardServer/routes/SettingsCatalog.cpp +++ b/dDashboardServer/routes/SettingsCatalog.cpp @@ -444,7 +444,7 @@ namespace { c.Add(Unit(Float(UGC, "color_variation", "Color variation", "Each brick's brightness is shifted by up to this much (the same every time the model is made). 0: none.", "5", 0, 100), "%")); c.Add(Unit(Float(UGC, "transparent_opacity", "Transparent opacity", "", "58.82", 0, 100), "%")); c.Add(Unit(Float(UGC, "color_brightness", "Model color brightness", "The models' vertex colors (not the icons'). 100: as the palette has them; lower is darker. Models already made keep theirs until they are made again.", "100", 0, 200), "%")); - c.Add(Text(UGC, "transparent_colors", "Always transparent colors", "LEGO color ids drawn transparent whatever Materials.xml says, comma separated (e.g. 129, the transparent glitter violet, which Materials.xml has opaque). Their opacity is Transparent opacity.", "")); + c.Add(Text(UGC, "transparent_colors", "Always transparent colors", "LEGO color ids drawn transparent whatever Materials.xml says, comma separated: by default 129, the transparent glitter violet, which Materials.xml has opaque (none: no colors). Their opacity is Transparent opacity.", "129")); c.Add(Text(UGC, "lods", "Levels of detail", "brickprimitives levels made, 0 (most detailed) to 2, e.g. 0,2.", "0,2")); c.Add(Float(UGC, "lod_distance_0", "LOD 0 distance", "", "0", 0, 100000)); c.Add(Float(UGC, "lod_distance_1", "LOD 1 distance", "", "50", 0, 100000)); @@ -455,13 +455,13 @@ namespace { c.Add(Bool(UGC, "combine_transparent", "One shape for all transparent bricks", "Off: each transparent brick is its own shape, so the client can sort them.", false)); // Metal and glow groups (UgcJobs::Shaders): off keeps the files exactly as before, as live made them const std::string notLive = " Not how live looked: live's models were all LEGO plastic (S01). Models already made keep their look until they are made again (Make everything again, or Reprocess)."; - c.Add(Int(UGC, "shader_metal", "Metal shader", "mapShaders id for metal colors (Materials.xml shinySteel and LU Toolbox's metallic ones), in a group S_Metal_Model: 88 is Polished Metal. 0: off, they stay LEGO plastic." + notLive, "0", 0, 9999)); - c.Add(Int(UGC, "shader_brushed", "Brushed steel shader", "mapShaders id for brushed steel colors (Materials.xml brushedSteel and matteSteel; the client's has none) in S_Brushed_Model: 89 is Brushed Steel. 0: off." + notLive, "0", 0, 9999)); - c.Add(Int(UGC, "shader_glow", "Glow shader", "mapShaders id for opaque glowing colors (LU Toolbox's glow colors) in S_Glow_Model, with their plain color and an emissive material: 46 is LEGO-Emissive. Transparent glow stays with the transparent bricks. 0: off." + notLive, "0", 0, 9999)); + c.Add(Int(UGC, "shader_metal", "Metal shader", "mapShaders id for metal colors (Materials.xml shinySteel and LU Toolbox's metallic ones), in a group S_Metal_Model: 88 is Polished Metal. 0: off, they stay LEGO plastic." + notLive, "88", 0, 9999)); + c.Add(Int(UGC, "shader_brushed", "Brushed steel shader", "mapShaders id for brushed steel colors (Materials.xml brushedSteel and matteSteel; the client's has none) in S_Brushed_Model: 89 is Brushed Steel. 0: off." + notLive, "89", 0, 9999)); + c.Add(Int(UGC, "shader_glow", "Glow shader", "mapShaders id for opaque glowing colors (LU Toolbox's glow colors) in S_Glow_Model, with their plain color and an emissive material: 46 is LEGO-Emissive. Transparent glow stays with the transparent bricks. 0: off." + notLive, "46", 0, 9999)); c.Add(Float(UGC, "glow_emissive", "Glow emissive strength", "With the glow shader on: the glow shapes' material emissive, how far the emissive shader goes from lit to the plain color (1: fully).", "1", 0, 10)); c.Add(Text(UGC, "metal_material_types", "Metal material types", "Materials.xml MaterialTypes drawn as metal, comma separated (none: only LU Toolbox's metallic colors).", "shinySteel")); c.Add(Text(UGC, "brushed_material_types", "Brushed steel material types", "Materials.xml MaterialTypes drawn as brushed steel, comma separated (none: no such colors).", "brushedSteel,matteSteel")); - c.Add(Text(UGC, "brushed_colors", "Brushed steel colors", "LEGO color ids drawn as brushed steel whatever their Materials.xml type, comma separated (e.g. the drum lacquered 298,300,1002,1004). Empty: none.", "")); + c.Add(Text(UGC, "brushed_colors", "Brushed steel colors", "LEGO color ids drawn as brushed steel whatever their Materials.xml type, comma separated: by default the drum lacquered 298,300,1002,1004 (none: no colors).", "298,300,1002,1004")); c.Add(Bool(UGC, "remove_hidden_faces", "Remove faces nobody can see", "", true)); c.Add(Bool(UGC, "hsr_ground_plane", "Nothing seen from below", "Also removes what can only be seen from under the model.", false)); c.Add(Unit(Int(UGC, "optimize_resolution", "Detail of the visibility renders", "", "1024", 64, 4096), "pixels")); diff --git a/dUgcServer/UgcServer.cpp b/dUgcServer/UgcServer.cpp index aceecd8d7..9d17976af 100644 --- a/dUgcServer/UgcServer.cpp +++ b/dUgcServer/UgcServer.cpp @@ -81,7 +81,9 @@ namespace { settings.build.transparentOpacity = std::clamp(Setting("transparent_opacity", 58.82f), 0.0f, 100.0f); settings.build.brightness = std::clamp(Setting("color_brightness", 100.0f), 0.0f, 200.0f); { - std::stringstream stream(Game::config->GetValue("transparent_colors")); + // Empty: the default (129); none: no colors + const auto value = Game::config->GetValue("transparent_colors"); + std::stringstream stream(value.empty() ? "129" : value); std::string id; while (std::getline(stream, id, ',')) { std::erase_if(id, [](unsigned char c) { return std::isspace(c); }); @@ -98,9 +100,9 @@ namespace { if (!Game::config->GetValue("shader_opaque").empty()) settings.shaderOpaque = Game::config->GetValue("shader_opaque"); settings.combineTransparent = Setting("combine_transparent", 0) != 0; // Metal and glow colors in NiLODNodes of their own, drawn with those shaders (off by default: not how live looked) - settings.shaders.metal = std::min(Setting("shader_metal", 0), 9999u); - settings.shaders.brushed = std::min(Setting("shader_brushed", 0), 9999u); - settings.shaders.glow = std::min(Setting("shader_glow", 0), 9999u); + settings.shaders.metal = std::min(Setting("shader_metal", 88), 9999u); + settings.shaders.brushed = std::min(Setting("shader_brushed", 89), 9999u); + settings.shaders.glow = std::min(Setting("shader_glow", 46), 9999u); settings.shaders.glowEmissive = std::clamp(Setting("glow_emissive", 1.0f), 0.0f, 10.0f); settings.icon.glowEmissive = settings.shaders.glowEmissive; // Which Materials.xml MaterialTypes are metal and brushed steel @@ -117,7 +119,9 @@ namespace { } // LEGO color ids drawn as brushed steel whatever their Materials.xml type { - std::stringstream stream(Game::config->GetValue("brushed_colors")); + // Empty: the default (the drum lacquered colors); none: no colors + const auto value = Game::config->GetValue("brushed_colors"); + std::stringstream stream(value.empty() ? "298,300,1002,1004" : value); std::string id; while (std::getline(stream, id, ',')) { std::erase_if(id, [](unsigned char c) { return std::isspace(c); }); diff --git a/docs/UgcServer.md b/docs/UgcServer.md index 57abc0c6d..9212c1ece 100644 --- a/docs/UgcServer.md +++ b/docs/UgcServer.md @@ -117,8 +117,9 @@ defaults. The table below goes through it step by step. `Materials.xml`): LU's colors, the LDD colors LU doesn't have mapped onto the nearest LU one, colors LU Toolbox doesn't know but the client's `Materials.xml` has (colors added to the brick database) from `Materials.xml`, unknown ones black. A brick is transparent only when all of its materials are; transparent bricks get `transparent_opacity` (58.82%). - `transparent_colors` names colors that are transparent whatever `Materials.xml` says (129, "Tr. Bright Bluish - Violet with Glitter", has alpha 255 there); an opaque-listed color named there gets `transparent_opacity`. + `transparent_colors` (default 129; `none`: no colors) names colors that are transparent whatever `Materials.xml` + says (129, "Tr. Bright Bluish Violet with Glitter", has alpha 255 there); a color named there gets + `transparent_opacity`. `color_brightness` (percent, default 100: unchanged) scales the models' colors after the variation below, not the icons'. 3. Color variation: each material of each brick has its brightness shifted like LU Toolbox's "Apply Color Variation": @@ -206,13 +207,13 @@ defaults. The table below goes through it step by step. | Icon scene BrickBuild / Car: 50 mm lens, camera 53.4 / 19.5 degrees, sun at 21 / 50.3, 128 px, framing 1.03, transparent film | Same framing (`icon_*`); the light is brighter, to match the game's icons | | Icon scene Rocket: 35 mm lens, other angles, two suns | Not built in; a preset for the rocket build type can be set in the icon editor | -### Metal and glow (opt in, not how live looked) +### Metal and glow (on by default, not how live looked) Live's models, LU Toolbox's exports and the client's own builder (`LUNifBuilder_BK`, which writes only `S01_Opaque` and `S01_Alpha`) all draw every brick with the LEGO shader, so metal colors look like grey plastic and glowing colors -like bright plastic. The UGC server can instead give them the client's metal and emissive shaders. Everything is off -by default, and off writes exactly the files it wrote before these settings existed (the same bytes, tested), so -nothing is made again needlessly. +like bright plastic. The UGC server gives them the client's metal and emissive shaders by default. Set the three +shader ids to 0 for live's look: off writes exactly the files it wrote before these settings existed (the same bytes, +tested). How the client picks the shader (checked in the 1.10.64 client; Ghidra bookmarks under "UGCShaders"): player models (LOT 14, and 6662) have RenderComponent shader 100, mapShaders "Multishader" (gameValue 9999). For a downloaded model @@ -224,13 +225,13 @@ all of its levels, so each look needs a group of its own. | Setting (`ugcconfig.ini`, dashboard: UGC models) | Default | What it writes | | --- | --- | --- | -| `shader_metal` | 0 (off) | `S_Metal_Model` for metal colors: 88 is Polished Metal (gameValue 98). The client loads `textures/metal/metal_reflection_polished.dds` itself and tints it by the vertex color (`Metallic.fx`, `Technique_Lighting_PolishedMetal_VertColor`). | -| `shader_brushed` | 0 (off) | `S_Brushed_Model` for brushed steel colors: 89 is Brushed Steel (gameValue 99; it loads `metal_reflection_brushed.dds` and `_noise.dds`, the noise in object space). The textures are registered by the client (`RegisterBrushedSteelTextures`, 0x00467090) as global shader textures 6 and 7, so the .nif needs none. The client's Materials.xml has no brushed types, so this needs `brushed_colors` or a Materials.xml that names them. | -| `shader_glow` | 0 (off) | `S_Glow_Model` for opaque glowing colors: 46 is LEGO-Emissive (gameValue 53), which draws `lerp(lit, vertex color, vertex alpha * material emissive red)`, opaque. | +| `shader_metal` | 88 | `S_Metal_Model` for metal colors: 88 is Polished Metal (gameValue 98). The client loads `textures/metal/metal_reflection_polished.dds` itself and tints it by the vertex color (`Metallic.fx`, `Technique_Lighting_PolishedMetal_VertColor`). | +| `shader_brushed` | 89 | `S_Brushed_Model` for brushed steel colors: 89 is Brushed Steel (gameValue 99; it loads `metal_reflection_brushed.dds` and `_noise.dds`, the noise in object space). The textures are registered by the client (`RegisterBrushedSteelTextures`, 0x00467090) as global shader textures 6 and 7, so the .nif needs none. The client's Materials.xml has no brushed types, so this needs `brushed_colors` or a Materials.xml that names them. | +| `shader_glow` | 46 | `S_Glow_Model` for opaque glowing colors: 46 is LEGO-Emissive (gameValue 53), which draws `lerp(lit, vertex color, vertex alpha * material emissive red)`, opaque. | | `glow_emissive` | 1 | The glow shapes' `NiMaterialProperty` emissive (grey): how far the shader goes from lit to the plain color. | | `metal_material_types` | `shinySteel` | Materials.xml `MaterialType`s that are metal (empty: the default; `none`: none). | | `brushed_material_types` | `brushedSteel,matteSteel` | Materials.xml `MaterialType`s that are brushed steel. | -| `brushed_colors` | empty | LEGO color ids that are brushed steel whatever their type (e.g. the drum lacquered 298, 300, 1002, 1004); they win over the metal and glow colors. | +| `brushed_colors` | 298,300,1002,1004 (the drum lacquered colors) | LEGO color ids that are brushed steel whatever their type; they win over the metal and glow colors. Empty: the default; `none`: no colors. | Which color has which look is data, not a list in the code (`UgcModel::LookOf`): glow is LU Toolbox's glow table (`UgcPalette::Glow`: 50, 294, 329, 9000-9027), metal is LU Toolbox's metallic table (`UgcPalette::IsMetallic`) plus diff --git a/resources/ugcconfig.ini b/resources/ugcconfig.ini index a396eeb51..260917e65 100644 --- a/resources/ugcconfig.ini +++ b/resources/ugcconfig.ini @@ -47,13 +47,13 @@ max_attempts=3 # color_variation: each brick's brightness is shifted by up to this percent (the same every time; 0: none). # transparent_opacity: transparent bricks' opacity in percent. # color_brightness: the models' colors in percent (not icons'; 100: as the palette has them, lower is darker). -# transparent_colors: color ids drawn transparent whatever Materials.xml says, comma separated (e.g. 129, the -# transparent glitter violet, which Materials.xml has opaque). Empty: none. +# transparent_colors: color ids drawn transparent whatever Materials.xml says, comma separated (empty: the default, 129, +# the transparent glitter violet, which Materials.xml has opaque; none: no colors). color_palette=lu_toolbox color_variation=5 transparent_opacity=58.82 color_brightness=100 -transparent_colors= +transparent_colors=129 # Levels of detail made, from the client's brickprimitives (0 most detailed, 2 least), and the distances they're # drawn at (LU Toolbox picks each level's range from these by which levels are made; lod_cull: drawn up to). @@ -69,8 +69,8 @@ lod_cull=10000 shader_opaque=01 combine_transparent=0 -# Metal and glow colors in NiLODNodes of their own, drawn with the client's metal and emissive shaders. Not how live -# looked: live's models were all LEGO plastic (S01), which is what 0 (off, the default) keeps, byte for byte. +# Metal and glow colors in NiLODNodes of their own, drawn with the client's metal and emissive shaders (the default). +# Not how live looked: live's models were all LEGO plastic (S01), which 0 (off) keeps, byte for byte. # shader_metal: mapShaders id for metal colors (Materials.xml types in metal_material_types and LU Toolbox's metallic # colors), S_Metal_Model: 88 is Polished Metal. # shader_brushed: for brushed steel colors (brushed_material_types; the client's Materials.xml has none): 89 is @@ -80,14 +80,15 @@ combine_transparent=0 # glow_emissive: the glow shapes' material emissive (how far the shader goes from lit to the plain color, 1 fully). # *_material_types: Materials.xml MaterialTypes, comma separated (empty: the default, none: no types). # Models already made keep their look until they're made again (the dashboard's Make everything again, or Reprocess). -shader_metal=0 -shader_brushed=0 -shader_glow=0 +shader_metal=88 +shader_brushed=89 +shader_glow=46 glow_emissive=1 metal_material_types=shinySteel brushed_material_types=brushedSteel,matteSteel -# brushed_colors: LEGO color ids drawn as brushed steel whatever their type (e.g. the drum lacquered 298,300,1002,1004) -brushed_colors= +# brushed_colors: LEGO color ids drawn as brushed steel whatever their type, comma separated (empty: the default, the +# drum lacquered 298,300,1002,1004; none: no colors) +brushed_colors=298,300,1002,1004 # Remove faces that can't be seen from anywhere (optimize_resolution: detail of the renders that decide it; # hsr_ground_plane: 1 also removes what can only be seen from below the model)