MONKEY (wet): wet hooks in terrain/static_gx/wow_model, rain rings on water, rainSurfaces cvar + row, wet- scenarios
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
88ad3cdad5
commit
5b8306dd6f
@@ -25,6 +25,7 @@ behind each constant.
|
||||
| Ground-effect spells | Flamestrike, Rain of Fire, Consecration, Flare and fire traps light the ground for their duration; frost and nature areas stay dark | `spellLightGain` |
|
||||
| Volumetric fog | near-field haze that converges on the zone fog colour (clear within 10 yd, full by 150 yd; mistier at dawn and in bad weather, faint indoors) and sun/moon light shafts through gaps, sampled from the shadow map; own fullscreen pass after the main pass (`benilla-app/src/volumetric_fog.rs`) | Advanced Graphics → Volumetric Fog (Off/Low/High), cvar `volumetricFog`, env `WOW_VOLFOG=0\|1\|2` |
|
||||
| Sky dithering | a faint screen-space dither in the FFXGlow combine so smooth sky and fog gradients do not band (MONKEY p0; was env-only) | Advanced Graphics → Sky Dithering, cvar `skyDither` 0/1 (default 0, Graphics preset High = 1), env `WOW_DITHER=1` still forces it on; bridge in `benilla-app/src/monkey_gfx.rs` |
|
||||
| Rain on surfaces | MONKEY (wet): while it rains, sky-exposed ground, stone and wood soak (dry→soaked in ~90 s, dry again over ~4 min): darker, slightly more saturated albedo, puddles on flat terrain, a sun highlight + sky Fresnel sheen on up-facing faces; rain rings on exterior Enhanced water. Wetness lives in `benilla-world/src/weather/wetness.rs` → MonkeyFrame `wet_a`; the look is `benilla-assets/src/shaders/wet_hook.wgsl` (one-line hooks in terrain/static_gx/wow_model), rings are `rain_ripple_normal` in `enhanced_water.wgsl`. Phase 1 sky exposure = not interior/unlit/emissive and not downward-facing; no rain-occlusion map yet, so porches and bridges still wet what is under them | Advanced Graphics → Wet Surfaces in Rain, cvar `rainSurfaces` 0/1 (default 1, Graphics preset High = 1); env `WOW_RAIN_SURFACES=0\|1`, `WOW_WETNESS=<0..1>` (pin wetness), `WOW_WET_T=<s>` (pin ripple clock) |
|
||||
| Night and interior level | global dimming of the night sky term and of interior ambient | `nightGain`, `interiorGain`, `interiorBakeFloor` |
|
||||
|
||||
Players reach all of it from **Options -> Advanced Graphics** (a Lighting Quality preset Off / Low / Medium / High plus the individual rows; Off is the original client look). The dev build has a panel for all of it: **Ctrl+Shift+D → Lighting & shadows**, with Dim / Default /
|
||||
|
||||
@@ -521,6 +521,8 @@
|
||||
interiorDarkness = "Interior Darkness",
|
||||
-- MONKEY (p0 skyDither)
|
||||
skyDither = "Sky Dithering",
|
||||
-- MONKEY (wet)
|
||||
rainSurfaces = "Wet Surfaces in Rain",
|
||||
yards = "%d yd",
|
||||
tips = {
|
||||
LIGHTING_QUALITY =
|
||||
@@ -617,6 +619,12 @@
|
||||
SKY_DITHER =
|
||||
"Adds a faint noise to the final image so smooth sky and fog gradients do not "
|
||||
.. "break into visible bands. Off is the original client's look. Practically free.",
|
||||
-- MONKEY (wet)
|
||||
RAIN_SURFACES =
|
||||
"Rain slowly soaks the ground, stone and wood under the open sky: they darken, "
|
||||
.. "puddles gather on flat ground and wet tops catch the light; rain drops ring "
|
||||
.. "the water. It dries over a few minutes after the rain stops. Off is the "
|
||||
.. "original client's look. Nearly free, and only active while things are wet.",
|
||||
},
|
||||
},
|
||||
ruRU = {
|
||||
@@ -651,6 +659,8 @@
|
||||
interiorDarkness = "Темнота помещений",
|
||||
-- MONKEY (p0 skyDither)
|
||||
skyDither = "Дизеринг неба",
|
||||
-- MONKEY (wet)
|
||||
rainSurfaces = "Мокрые поверхности в дождь",
|
||||
yards = "%d ярд.",
|
||||
tips = {
|
||||
LIGHTING_QUALITY =
|
||||
@@ -756,6 +766,12 @@
|
||||
"Добавляет едва заметный шум в итоговое изображение, чтобы плавные переходы цвета "
|
||||
.. "неба и тумана не распадались на полосы. Выключено — вид оригинального клиента. "
|
||||
.. "Почти ничего не стоит.",
|
||||
-- MONKEY (wet)
|
||||
RAIN_SURFACES =
|
||||
"Дождь постепенно намачивает землю, камень и дерево под открытым небом: они темнеют, "
|
||||
.. "на ровной земле собираются лужи, мокрые поверхности блестят, а капли расходятся "
|
||||
.. "кругами по воде. После дождя всё высыхает за несколько минут. Выключено — вид "
|
||||
.. "оригинального клиента. Почти ничего не стоит и работает, только пока всё мокрое.",
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -816,6 +832,8 @@
|
||||
"RowNightDarkness", "RowInteriorDarkness",
|
||||
-- MONKEY (p0 skyDither)
|
||||
"RowSkyDither",
|
||||
-- MONKEY (wet)
|
||||
"RowRainSurfaces",
|
||||
},
|
||||
-- Player Guild Names is a child of Player Names, as in 1.12 (l.702-708).
|
||||
Nameplates = {
|
||||
@@ -2854,6 +2872,18 @@
|
||||
"BENILLA_TOOLTIP_SKY_DITHER")
|
||||
</OnLoad></Scripts>
|
||||
</Frame>
|
||||
<!-- MONKEY (wet): wet surfaces + rain ripples. -->
|
||||
<Frame name="$parentRowRainSurfaces" inherits="OptionsCheckboxRowTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$parentRowSkyDither" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||||
<Anchor point="TOPRIGHT" relativeTo="$parentRowSkyDither" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||||
</Anchors>
|
||||
<Scripts><OnLoad>
|
||||
OptionsRow_OnLoad(self, "rainSurfaces",
|
||||
BENILLA_ADVGFX.rainSurfaces,
|
||||
"BENILLA_TOOLTIP_RAIN_SURFACES")
|
||||
</OnLoad></Scripts>
|
||||
</Frame>
|
||||
</Frames>
|
||||
<!-- The poll (see AdvGfx_OnUpdate): this is the one page whose
|
||||
settings move from outside it — the Lighting Quality row
|
||||
|
||||
@@ -1379,6 +1379,23 @@ pub(super) const ON_DEMAND: &[Scenario] = &[
|
||||
minute: 0,
|
||||
ui: None,
|
||||
},
|
||||
// MONKEY (wet): rain on surfaces. Run with rain forced and the ground pre-soaked, e.g.
|
||||
// `WOW_WEATHER=1,0.8 WOW_WETNESS=1 WOW_WET_T=3`, and A/B with `WOW_RAIN_SURFACES=0|1`.
|
||||
// Goldshire's square: the road, the grass, the inn's roofs and walls.
|
||||
Scenario {
|
||||
name: "wet-goldshire", map: Some(MAP_AZEROTH),
|
||||
eye: [-9460.0, 70.0, 59.5], look: [-9452.0, 30.0, 55.0], minute: 720, ui: None,
|
||||
},
|
||||
// The Elwynn river bank, close enough (< 25 yd) for the rain rings.
|
||||
Scenario {
|
||||
name: "wet-river", map: Some(MAP_AZEROTH),
|
||||
eye: [-9514.0, -330.0, 64.0], look: [-9500.0, -352.0, 61.4], minute: 720, ui: None,
|
||||
},
|
||||
// A Stormwind Trade District street: exterior WMO paving, walls, eaves.
|
||||
Scenario {
|
||||
name: "wet-stormwind", map: Some(MAP_AZEROTH),
|
||||
eye: [-8833.38, 628.63, 98.5], look: [-8815.0, 662.0, 93.5], minute: 720, ui: None,
|
||||
},
|
||||
];
|
||||
|
||||
/// The owner's reported vantage for the lava-glow report: `(-7048.8, -1000.6, 242.0)` facing
|
||||
|
||||
@@ -928,6 +928,13 @@ pub(crate) const REGISTERED: &[Registered] = &[
|
||||
"0",
|
||||
"benilla's own: faint screen dither against sky and fog banding, 0 Off / 1 On",
|
||||
),
|
||||
// MONKEY (wet): rain darkens and glosses sky-exposed surfaces and rings the water. Default 1
|
||||
// (only visible while it rains or the ground dries); the Graphics preset's High sets 1.
|
||||
ours(
|
||||
"rainSurfaces",
|
||||
"1",
|
||||
"benilla's own: rain wets sky-exposed surfaces and rings the water, 0 Off / 1 On",
|
||||
),
|
||||
ours(
|
||||
"waterQuality",
|
||||
"1",
|
||||
|
||||
@@ -5,17 +5,33 @@
|
||||
//! | cvar | values | default | Graphics preset High | resource |
|
||||
//! |---|---|---|---|---|
|
||||
//! | `skyDither` | 0 Off / 1 On | 0 | 1 | `benilla_world::ffx_glow::SkyDither` |
|
||||
//! | `rainSurfaces` | 0 Off / 1 On | 1 | 1 | `benilla_world::weather::RainSurfaces` |
|
||||
|
||||
use bevy::prelude::*;
|
||||
use benilla_world::ffx_glow::SkyDither;
|
||||
use benilla_world::weather::RainSurfaces; // MONKEY (wet)
|
||||
|
||||
/// The programme's cvar observer (registered by [`MonkeyGfxPlugin`]).
|
||||
pub(crate) fn on_cvar(ev: On<crate::cvars::CvarChanged>, mut dither: ResMut<SkyDither>) {
|
||||
if ev.key().as_str() == "skydither" {
|
||||
let want = ev.num() >= 0.5;
|
||||
if dither.0 != want {
|
||||
dither.0 = want;
|
||||
pub(crate) fn on_cvar(
|
||||
ev: On<crate::cvars::CvarChanged>,
|
||||
mut dither: ResMut<SkyDither>,
|
||||
mut rain: ResMut<RainSurfaces>, // MONKEY (wet)
|
||||
) {
|
||||
match ev.key().as_str() {
|
||||
"skydither" => {
|
||||
let want = ev.num() >= 0.5;
|
||||
if dither.0 != want {
|
||||
dither.0 = want;
|
||||
}
|
||||
}
|
||||
// MONKEY (wet): wet surfaces + rain ripples.
|
||||
"rainsurfaces" => {
|
||||
let want = ev.num() >= 0.5;
|
||||
if rain.0 != want {
|
||||
rain.0 = want;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +41,8 @@ pub(crate) struct MonkeyGfxPlugin;
|
||||
|
||||
impl Plugin for MonkeyGfxPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.init_resource::<SkyDither>().add_observer(on_cvar);
|
||||
app.init_resource::<SkyDither>()
|
||||
.init_resource::<RainSurfaces>() // MONKEY (wet)
|
||||
.add_observer(on_cvar);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,8 +245,58 @@ fn water_gerstner(p: vec2<f32>, t: f32, shore: f32) -> vec4<f32> {
|
||||
|
||||
// MONKEY (water): seam for the later wet-weather lane. Its result is a height-gradient
|
||||
// perturbation in world XZ; zero preserves today's image until that lane supplies rain data.
|
||||
fn rain_ripple_normal(world_xz: vec2<f32>, time: f32) -> vec2<f32> {
|
||||
return vec2<f32>(0.0);
|
||||
// MONKEY (wet): rain rings. Each layer is a grid of cells, one drop per cell at a hashed spot and
|
||||
// phase; a drop lands when its cell hash is under the rain rate, and its ring expands and fades
|
||||
// over one period. The ring's slope profile is a Gaussian-windowed cosine across the front. The
|
||||
// clock is MonkeyFrame `wet_a.z` (wraps at 1000 s; the rates are multiples of 1/1000, so the wrap is
|
||||
// seamless). Dry (`wet0.x == 0`), WMO interior pools, interior-fog rooms, and pixels too far or too
|
||||
// coarse to hold a ring return zero.
|
||||
fn ripple_hash2(p: vec2<f32>) -> vec2<f32> {
|
||||
var q = fract(vec3<f32>(p.xyx) * vec3<f32>(0.1031, 0.1030, 0.0973));
|
||||
q += dot(q, q.yzx + 33.33);
|
||||
return fract((q.xx + q.yz) * q.zy);
|
||||
}
|
||||
fn rain_ripple_normal(world_xz: vec2<f32>, footprint: f32, distance: f32, room: bool) -> vec2<f32> {
|
||||
let wet0 = water_monkey().wet_a;
|
||||
let rain = clamp(wet0.x, 0.0, 1.0);
|
||||
if rain <= 0.0 || water.lane.x > 1.5 || room {
|
||||
return vec2<f32>(0.0);
|
||||
}
|
||||
let reach = (1.0 - smoothstep(35.0, 60.0, distance)) * (1.0 - smoothstep(0.05, 0.14, footprint));
|
||||
if reach <= 0.0 {
|
||||
return vec2<f32>(0.0);
|
||||
}
|
||||
var grad = vec2<f32>(0.0);
|
||||
for (var layer = 0; layer < 2; layer += 1) {
|
||||
let c = select(0.9, 1.45, layer == 1);
|
||||
let rate = select(0.8, 0.65, layer == 1);
|
||||
let base = floor(world_xz / c);
|
||||
for (var j = -1; j <= 1; j += 1) {
|
||||
for (var i = -1; i <= 1; i += 1) {
|
||||
let cell = base + vec2<f32>(f32(i), f32(j));
|
||||
let seed = cell + vec2<f32>(f32(layer) * 57.0, f32(layer) * 113.0);
|
||||
let h = ripple_hash2(seed);
|
||||
let h2 = ripple_hash2(seed + 19.19);
|
||||
// Each period re-rolls whether this cell rains, so the pattern does not repeat.
|
||||
let cycle = wet0.z * rate + h.x;
|
||||
let roll = ripple_hash2(seed + floor(cycle) * 7.31).x;
|
||||
if roll > rain * 0.85 {
|
||||
continue;
|
||||
}
|
||||
let phase = fract(cycle);
|
||||
let centre = (cell + 0.5 + (h2 - 0.5) * 0.6) * c;
|
||||
let to_p = world_xz - centre;
|
||||
let d = length(to_p);
|
||||
let radius = phase * 0.6 * c;
|
||||
let x = d - radius;
|
||||
let width = 0.05 + 0.07 * phase;
|
||||
let fade = (1.0 - phase) * (1.0 - phase) * smoothstep(0.0, 0.08, phase);
|
||||
let slope = fade * exp(-(x * x) / (width * width)) * cos(x * 3.1415927 / width);
|
||||
grad += to_p / max(d, 1e-4) * slope;
|
||||
}
|
||||
}
|
||||
}
|
||||
return grad * (0.7 + 0.5 * rain) * reach;
|
||||
}
|
||||
|
||||
fn foam_hash(p_in: vec2<f32>) -> f32 {
|
||||
@@ -538,7 +588,8 @@ fn enhanced_water(in: WaterFragment, shallow: vec4<f32>, deep: vec4<f32>) -> vec
|
||||
open_sea_fold = water_gerstner(p, t, shore).w;
|
||||
}
|
||||
// One surface gradient: the procedural bands and the shore break.
|
||||
let surf_grad = wave.yz + shore_grad + rain_ripple_normal(in.world_position.xz, t);
|
||||
let surf_grad = wave.yz + shore_grad + rain_ripple_normal(in.world_position.xz, footprint,
|
||||
length(eye_pos), in.room_fog != 0u && water.lane.w > 0.5);
|
||||
var n = normalize(vec3<f32>(-surf_grad.x, 1.0, -surf_grad.y));
|
||||
if dot(n, to_view) < 0.0 { n = -n; }
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#import benilla::monkey_frame
|
||||
// MONKEY (p0 fog hook): the one distance-fog law every receiver calls.
|
||||
#import benilla::fog_hook
|
||||
// MONKEY (wet): rain on surfaces (wet_hook.wgsl).
|
||||
#import benilla::wet_hook
|
||||
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(100) var layer_array: texture_2d_array<f32>;
|
||||
@group(#{MATERIAL_BIND_GROUP}) @binding(104) var alpha_array: texture_2d_array<f32>;
|
||||
@@ -755,9 +757,19 @@ fn fragment(in: TerrainVsOut) -> @location(0) vec4<f32> {
|
||||
// specular = per-vertex sheen · gloss_mask · shadow → gated to ZERO in shadow (no sheen in shade)
|
||||
// (`tex·primary` is the MODULATE-1× diffuse; the sheen is added after, separate-specular.) Then
|
||||
// LDR-clamp; gamma/byte throughout; raw gamma out (GAMMA LANE, 0161).
|
||||
// MONKEY (wet): rain-darkened ground + puddles (wet_hook.wgsl); a dry frame returns `color`.
|
||||
let wet = wet_hook::wet_puddles(wet_hook::wet_surface(color, n_lit, in.world_position.xyz, 1.0,
|
||||
wow_light.monkey), n_lit, in.world_position.xyz, wow_light.monkey);
|
||||
color = wet.albedo;
|
||||
let diffuse_term = color * primary * (0.3 * shadow_lit_eff + 0.7) * character_shadow_term;
|
||||
let spec_term = in.specular * specmask * spec_gate;
|
||||
var tuned = clamp(diffuse_term + spec_term, vec3<f32>(0.0), vec3<f32>(1.0));
|
||||
// MONKEY (wet): the wet sheen, and the authored `_s` sheen brightens with it.
|
||||
if (wet.boost > 0.0) {
|
||||
tuned = clamp(tuned + spec_term * wet.boost + wet_hook::wet_sheen(wet.boost, n_lit,
|
||||
normalize(view.world_position - in.world_position.xyz), -normalize(wow_light.light_sun.xyz),
|
||||
wow_light.light_diffuse.rgb, wow_light.fog_color.rgb, spec_gate), vec3<f32>(0.0), vec3<f32>(1.0));
|
||||
}
|
||||
|
||||
// MONKEY (torch debug, interiorDebug 2 on TERRAIN): the ground's OWN cube-map sampling as
|
||||
// greyscale, the same instrument static_gx and wow_model already paint on walls and bodies. The
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
|
||||
struct WetSurface {
|
||||
albedo: vec3<f32>,
|
||||
// Gloss weight for `wet_sheen`: 0 dry, ~1 a soaked top face, up to ~1.6 in a terrain puddle.
|
||||
// Gloss weight for `wet_sheen`: 0 dry, ~1 a soaked top face, up to 2 in a terrain puddle (the
|
||||
// part above 1 is standing water: a flat mirror of the sky).
|
||||
boost: f32,
|
||||
}
|
||||
|
||||
@@ -68,13 +69,13 @@ fn wet_puddles(s: WetSurface, n: vec3<f32>, world_pos: vec3<f32>, mf: MonkeyFram
|
||||
return o;
|
||||
}
|
||||
let xz = world_pos.xz;
|
||||
let field = 0.65 * wet_noise(xz * 0.11) + 0.35 * wet_noise(xz * 0.43 + 17.0);
|
||||
let field = 0.65 * wet_noise(xz * 0.17) + 0.35 * wet_noise(xz * 0.53 + 17.0);
|
||||
let level = smoothstep(0.94, 0.99, n.y);
|
||||
// Puddles grow with the wetness: the threshold falls as the ground soaks.
|
||||
let edge = mix(0.8, 0.6, smoothstep(0.4, 1.0, wet0.y));
|
||||
let puddle = smoothstep(edge, edge + 0.06, field) * level * smoothstep(0.35, 0.8, wet0.y);
|
||||
o.albedo = o.albedo * (1.0 - 0.4 * puddle);
|
||||
o.boost = max(o.boost, 1.6 * puddle);
|
||||
o.albedo = o.albedo * (1.0 - 0.45 * puddle);
|
||||
o.boost = max(o.boost, 2.0 * puddle);
|
||||
return o;
|
||||
}
|
||||
|
||||
@@ -89,5 +90,8 @@ fn wet_sheen(boost: f32, n: vec3<f32>, to_view: vec3<f32>, to_light: vec3<f32>,
|
||||
let nl = max(dot(n, to_light), 0.0);
|
||||
let spec = pow(max(dot(n, h), 0.0), 80.0) * smoothstep(0.0, 0.15, nl);
|
||||
let fres = 0.03 + 0.97 * pow(1.0 - clamp(dot(n, to_view), 0.0, 1.0), 5.0);
|
||||
return boost * (sun_rgb * (0.9 * spec * shadow) + sky_rgb * (0.28 * fres));
|
||||
let gloss = min(boost, 1.0);
|
||||
let mirror = max(boost - 1.0, 0.0);
|
||||
return sun_rgb * ((0.9 * gloss + 1.2 * mirror) * spec * shadow)
|
||||
+ sky_rgb * (gloss * min(0.25 * fres, 0.2) + mirror * (0.22 + 0.3 * fres));
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#import benilla::shadow_hook
|
||||
// MONKEY (p0 MonkeyFrame): the programme block's struct, mirrored after the point table.
|
||||
#import benilla::monkey_frame
|
||||
// MONKEY (wet): rain on surfaces (wet_hook.wgsl).
|
||||
#import benilla::wet_hook
|
||||
// MONKEY (p0 fog hook): the one distance-fog law every receiver calls.
|
||||
#import benilla::fog_hook
|
||||
|
||||
@@ -1708,6 +1710,18 @@ fn fragment(in: WowVsOut, @builtin(front_facing) is_front: bool) -> WowFragOut {
|
||||
rgb = base.rgb;
|
||||
}
|
||||
|
||||
// MONKEY (wet): rain on sky-exposed WMO/M2 surfaces (wet_hook.wgsl); interior, glue booth, unlit,
|
||||
// Mod/Mod2x, additive and dry = untouched.
|
||||
let wet_dry = is_interior || interior_fogged || is_rig || is_emissive || is_mod || is_mod2x
|
||||
|| (u32(m.clutter_fade.z) & 4u) != 0u;
|
||||
let wet = wet_hook::wet_surface(rgb, n_lit, in.world_position.xyz, select(1.0, 0.0, wet_dry),
|
||||
wow_light.monkey);
|
||||
rgb = wet.albedo;
|
||||
if (wet.boost > 0.0) {
|
||||
rgb = min(rgb + wet_hook::wet_sheen(wet.boost, n_lit, normalize(view.world_position - in.world_position.xyz),
|
||||
L, wow_light.light_diffuse.rgb, wow_light.fog_color.rgb, player_shadow), vec3<f32>(1.0));
|
||||
}
|
||||
|
||||
// Linear fog by planar eye depth, as in terrain.wgsl. Per-batch colour policy (`clutter_fade.z`
|
||||
// bits 4-6, the M2 state setter `0x70baf0`): 0 scene, 1 black (additive), 2 white (Mod),
|
||||
// 3 grey (Mod2x), 4 unfogged (render flag 0x02). Tag bit 30, not the static `model_flags.z`,
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#import benilla::monkey_frame
|
||||
// MONKEY (p0 fog hook): the one distance-fog law every receiver calls.
|
||||
#import benilla::fog_hook
|
||||
// MONKEY (wet): rain on surfaces (wet_hook.wgsl).
|
||||
#import benilla::wet_hook
|
||||
|
||||
// Group 0 is Bevy's standard mesh-view bind group (view matrices, directional-light records and
|
||||
// the shadow textures the retained pass reads).
|
||||
@@ -1972,6 +1974,14 @@ fn fragment(in: GxVsOut) -> @location(0) vec4<f32> {
|
||||
if ((in.word & WORD_UNLIT) != 0u) {
|
||||
rgb = folded;
|
||||
}
|
||||
// MONKEY (wet): rain on sky-exposed surfaces (wet_hook.wgsl); interior, unlit and dry = untouched.
|
||||
let wet = wet_hook::wet_surface(rgb, n_lit, in.world_position.xyz,
|
||||
select(1.0, 0.0, (in.word & (WORD_INTERIOR | WORD_UNLIT)) != 0u), wow_light.monkey);
|
||||
rgb = wet.albedo;
|
||||
if (wet.boost > 0.0) {
|
||||
rgb = min(rgb + wet_hook::wet_sheen(wet.boost, n_lit, normalize(view.world_position - in.world_position.xyz),
|
||||
L, wow_light.light_diffuse.rgb, wow_light.fog_color.rgb, world_shadow), vec3<f32>(1.0));
|
||||
}
|
||||
// Planar eye-Z fog; other fog modes belong to blends never admitted here. The interior triple
|
||||
// keys on the per-frame record bit, not `WORD_INTERIOR`: the client sets it per group under
|
||||
// `[0xca7f00]` (`0x6b5190` for surfaces, `0x6b62e0` for the group's doodads).
|
||||
|
||||
Reference in New Issue
Block a user