diff --git a/dDashboardServer/routes/Scenery.cpp b/dDashboardServer/routes/Scenery.cpp index caacf3edd..df229c5bb 100644 --- a/dDashboardServer/routes/Scenery.cpp +++ b/dDashboardServer/routes/Scenery.cpp @@ -278,9 +278,10 @@ namespace { * which must follow this; SceneryCoreJs checks), so a manifest a browser kept for a day from an older server * isn't drawn with newer code. 2: meshes carry their multishader tag; conversions without it drew glom parts with * the LEGO shader. 3: dark textures and the UV set each texture names. 4: the game's shaders draw the models - * (manifest "techniques"), vertex colors go to them as stored. 5: an animated material alpha is its highest key. + * (manifest "techniques"), vertex colors go to them as stored. 5: an animated material alpha is its highest key. 6: flair tints are bytes over + * 255 (they were over 63). */ - constexpr uint32_t FORMAT_VERSION = 5; + constexpr uint32_t FORMAT_VERSION = 6; // A zone's lighting (WorldScene::Lighting) for the viewers' shaders nlohmann::json LightingJson(const WorldScene::Lighting& lighting) { @@ -442,7 +443,7 @@ namespace { /** * The flairs' manifest (as the scenery's, plus a tint per flair), from the zone's terrain file. A flair's color - * tints its model; 63 is full strength (the files use 0 to 63 for most flairs, a little more for brighter ones). + * tints its model as a byte over 255, times the model's own vertex colors (FlairAssets::AppendRenderBuffer). */ std::optional BuildFlairs(uint32_t zoneId, ZoneScenery& scenery) { const auto raw = ZoneRawShared(zoneId); @@ -477,7 +478,7 @@ namespace { assets = scenery.assets; } return nlohmann::json{ - {"zone", zoneId}, {"sky", -1}, {"assets", assets}, {"distance", FLAIR_DISTANCE}, {"colorScale", 1.0 / 63.0}, {"lighting", scenery.lighting}, {"format", FORMAT_VERSION}, + {"zone", zoneId}, {"sky", -1}, {"assets", assets}, {"distance", FLAIR_DISTANCE}, {"colorScale", 1.0 / 255.0}, {"lighting", scenery.lighting}, {"format", FORMAT_VERSION}, // Flair.fx for all of them: (0.85 * sun + ambient) * the flair's tint, whatever their facing {"technique", { {"family", "flair"}, {"look", 0}, {"alpha", "opacity"}, {"flags", 0} }}, {"objects", { {"asset", assetOf}, {"pos", positions}, {"rot", rotations}, {"scale", scales}, {"color", colors} }} @@ -488,7 +489,7 @@ namespace { /** * The flairs' manifest (as the scenery's, plus a tint per flair), from the zone's terrain file. A flair's color - * tints its model; 63 is full strength (the files use 0 to 63 for most flairs, a little more for brighter ones). + * tints its model as a byte over 255, times the model's own vertex colors (FlairAssets::AppendRenderBuffer). * Built when first asked for (any thread). */ const std::optional& Flairs(uint32_t zoneId, ZoneScenery& scenery) { diff --git a/dDashboardServer/static/js/game-shaders.js b/dDashboardServer/static/js/game-shaders.js index b20e7bd2c..b9d9f8346 100644 --- a/dDashboardServer/static/js/game-shaders.js +++ b/dDashboardServer/static/js/game-shaders.js @@ -32,6 +32,7 @@ varying vec2 vUvDark; varying vec2 vUv; varying vec4 vColor; varying vec3 vLight; // the lit color the technique's vertex shader outputs (clamped as a COLOR output is) +varying vec3 vLit; // ... times the vertex color, clamped once as the Basic, AlphaAsAlpha and Flair COLOR0 outputs are varying float vLdn; // N.L, clamped varying vec3 vNormal; // world space varying vec3 vWorld; @@ -92,11 +93,21 @@ void main() { // g_metalDiffuse * N.L^4 + g_metalAmbient vLight = clamp( vec3( 0.7 ) * pow( vLdn, 4.0 ) + vec3( 0.3 ), 0.0, 1.0 ); #elif defined( FAMILY_FLAIR ) + // Flair_VS: (0.85 * sun + ambient) * the flair's tint, clamped once as the COLOR0 output vLight = clamp( 0.85 * gameLightColor + gameAmbient, 0.0, 1.0 ); + vLit = clamp( ( 0.85 * gameLightColor + gameAmbient ) * vcol.rgb, 0.0, 1.0 ); #elif defined( UNLIT ) vLight = vec3( 1.0 ); + vLit = clamp( vcol.rgb, 0.0, 1.0 ); #else - vLight = clamp( max( vec3( 0.0 ), gameLightColor * ldn ) + gameAmbient, 0.0, 1.0 ); + // BasicShaders / AlphaAsAlpha *_Lighting_VertColor_VS: (sun * N.L + ambient) * the vertex color, then clamped as + // the COLOR0 output (not the light alone: a bright light still lifts a dark vertex color) + vec3 lit = max( vec3( 0.0 ), gameLightColor * ldn ) + gameAmbient; + vLight = clamp( lit, 0.0, 1.0 ); + vLit = clamp( lit * vcol.rgb, 0.0, 1.0 ); +#endif +#if !defined( FAMILY_FLAIR ) && !defined( FAMILY_BASIC ) + vLit = vLight * vcol.rgb; #endif gl_Position = projectionMatrix * viewMatrix * worldPosition; } @@ -128,6 +139,7 @@ varying vec2 vUvDark; #endif varying vec4 vColor; varying vec3 vLight; +varying vec3 vLit; varying float vLdn; varying vec3 vNormal; varying vec3 vWorld; @@ -309,7 +321,7 @@ void main() { #else // Basic, AlphaAsAlpha, fixed function, flairs, the sky: texture times the lit (or unlit) vertex color - vec4 light = vec4( vLight * vc.rgb, vc.a ); + vec4 light = vec4( vLit, vc.a ); #ifdef LAYERS_BLENDED result = vec4( mix( tex( darkMap, vUvDark ).rgb, tex( map, vUv ).rgb, vc.a ) * light.rgb, 1.0 ); #elif defined( LAYERS_ADDED ) diff --git a/dDashboardServer/static/js/scenery-core.js b/dDashboardServer/static/js/scenery-core.js index 2350ae8ae..a401429c7 100644 --- a/dDashboardServer/static/js/scenery-core.js +++ b/dDashboardServer/static/js/scenery-core.js @@ -111,7 +111,7 @@ export const TECHNIQUE = { * The conversion format (Scenery.cpp FORMAT_VERSION) these views are written for. Manifest URLs carry it, so a * browser never draws with a manifest it kept from an older server (they are cached for up to a day). */ -export const SCENERY_FORMAT = 5; +export const SCENERY_FORMAT = 6; /** A manifest URL asking for SCENERY_FORMAT's manifest (the server ignores the parameter; browsers cache by it). */ export function manifestUrl(url) { diff --git a/docs/Dashboard.md b/docs/Dashboard.md index 654199984..6c81705ea 100644 --- a/docs/Dashboard.md +++ b/docs/Dashboard.md @@ -1096,7 +1096,7 @@ scenes. | Family | gameValues | Drawn as | | --- | --- | --- | | LEGO (LEGOPPLighting) | 4, 5, 12, 14, 19, 20, 22, 25-31, 48, 50, 53, 72, 88, 92 | hemisphere lit sun + ambient, fresnel rim, N.H^320 specular, default reflection cube x0.05; texture over vertex colors by its alpha (decal) or times them (Item, Masked NonDecal, FaceCreate); Emissive/SuperEmissive (vertex alpha x emissive red), Glow, Grayscale, NoAmbient, AnimUV | -| Basic (BasicShaders, AlphaAsAlpha) | 7-11, 13, 15-18, 23, 24, 32-39, 49, 52, 54-65, 68, 70, 73, 80-87, 91, 93, 94, 105-108 | sun x N.L + ambient per vertex (or unlit) x vertex color x texture; AlphaAsAlpha both sides; AlphaBlend without depth writes, AlphaTest cut out, Additive; material alpha for the AnimAlpha ones; two layer blends and adds | +| Basic (BasicShaders, AlphaAsAlpha) | 7-11, 13, 15-18, 23, 24, 32-39, 49, 52, 54-65, 68, 70, 73, 80-87, 91, 93, 94, 105-108 | (sun x N.L + ambient) x vertex color per vertex, clamped once as the COLOR0 output (or unlit), x texture; AlphaAsAlpha both sides (its techniques set Cullmode none, so cards made to be seen from one side show their backs from outside a playable area); AlphaBlend without depth writes, AlphaTest cut out, Additive; material alpha for the AnimAlpha ones; two layer blends and adds | | Metal (Metallic.fx) | 98, 99, 100 | 0.7 N.L^4 + 0.3, plus the client's metal cube (polished or brushed, with the brushed noise in object space) tinted by the vertex color, specular | | Clear Plastic | 6 | default reflection cube, fresnel of the lit grey, tight highlight; see-through facing the eye | | Ocean (Distortion) | 69, 89, 90, 95, 101 | three texture layers, each warped by the one before, lit (or unlit x2, or FX with the emissive alpha window) | @@ -1104,7 +1104,7 @@ scenes. | BrickWater | 51 | hemisphere lit vertex color, fresnel, specular | | Darkling | 75-77, 102-104 | dark texture on the second UV set over the base look by a window of vertex alphas (material emissive r/g/b); Specular uses LEGO lighting, Structure multiplies | | Terrain meshes | 2, 3, 97 | texture x vertex color x (sun x N.L + ambient); Rim Light adds a rim; Diffuse Map Only doubles the texture | -| Flairs (Flair.fx) | the flair manifest | (0.85 sun + ambient) x tint | +| Flairs (Flair.fx) | the flair manifest | (0.85 sun + ambient) x tint, clamped once; the tint is the terrain file's color byte / 255 times the flair model's own vertex colors | | Sky (Skydome.fx) | the scene's sky | texture x vertex color, unlit, moving by its texture transform | | Not drawn | 21, 71, 74, 79, 96 | model footprints, post-processing, drop shadows, Undefined | | Fixed function | -1 | sun x N.L + ambient with the material color and NiVertexColorProperty | @@ -1118,7 +1118,7 @@ Powerups, Orb, TV Screen and Head Icon effects (drawn as LEGO or unlit), Flair's client's environment textures come from `/api/scenery/env/:name` (`reflection`, `polished`, `brushed`, `brushedNoise`). Placed player models are drawn by the viewer's own lighting. -The views ask for a zone's manifest with the conversion format they're written for (`?format=5`, +The views ask for a zone's manifest with the conversion format they're written for (`?format=6`, `scenery-core.js` `SCENERY_FORMAT`, which follows `Scenery.cpp` `FORMAT_VERSION`), since browsers keep manifests for up to a day. A manifest without `techniques` (an older server's) is drawn with the viewer's own lights and its `textureAlpha` table instead of guessing every shader as LEGO, which laid see-through textures over white vertex