Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/commit-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ env:
# Keep the engine's shared File/FileSystem ABI locked to the companion
# revision that implements GAME_API 46, generated-animation cache v3, and
# the game-owned transient time-scale interface.
OPENQ4_GAMELIBS_SHA: 67fcd3e2142bc07c4871873ea1ec6fe592ac8a5a
OPENQ4_GAMELIBS_SHA: bfe7f45c1f7cf90ecf0ffd29b11e11b9265d860a

jobs:
script-smoke:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/push-verification.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ env:
# Keep the engine's shared File/FileSystem ABI locked to the companion
# revision that implements GAME_API 46, generated-animation cache v3, and
# the game-owned transient time-scale interface.
OPENQ4_GAMELIBS_SHA: 67fcd3e2142bc07c4871873ea1ec6fe592ac8a5a
OPENQ4_GAMELIBS_SHA: bfe7f45c1f7cf90ecf0ffd29b11e11b9265d860a

concurrency:
group: openq4-push-verification-${{ github.ref }}
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ Packaged support currently focuses on Windows, Linux x64, Steam Deck/SteamOS, pr
- [Competitive Matches](docs/user/competitive-matches.md) (experimental) - match framework, rules, and warmup behaviour
- [Demo Library and Multi-View Demos](docs/user/multiview-demos.md) - browse formats, use playback controls, and record or replay complete multiplayer matches
- [Liquids](docs/user/liquids.md) - water, slime, and lava behaviour, and how to author them
- [Classic Dynamic Lights](docs/user/classic-dynamic-lights.md) - Quake II/III style dynamic lights on muzzle flashes, bright projectiles, and explosions
- [Shadow Mapping](docs/user/shadow-mapping.md) - optional shadow-map settings and troubleshooting
- [Light Grids](docs/user/light-grids.md) - advanced lighting guide for players and testers
- [Advanced Screen-Space Lighting](docs/user/advanced-screen-space-lighting.md) (experimental) - bounded froxel volumetrics, SSR, SSGI, performance controls, and one-setting rollback
Expand Down
1 change: 1 addition & 0 deletions docs/dev/release-completion.md
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,7 @@ is `docs/dev/macos-moltenvk-decision.md`.
- [x] OpenGL depth-bounds submission now orders and clamps both values to the legal range before calling the driver, eliminating the two `GL_INVALID_VALUE` records that previously made `game/medlabs` the lone required-profile failure; its debug-context rerun is error-free.
- [x] Shadow-map caster coverage and contact quality are corrected across the classic OpenGL, direct Vulkan, and shared interaction paths. Automatic culling now stores the near shell for sealed geometry and renders open/uncertain stock geometry two-sided; large point-light bias is world-bounded, balanced filter footprints are tighter and cheaper, PCSS blocker search is bias-consistent, map/alpha/dynamic cache ownership fails closed, projected and point resources carry exact world/pass/storage provenance through bind time, partial mapped ownerships receive exact stencil supplements or return to full stencil, Modern OpenGL refuses resources it cannot consume completely, atlas placement follows physical limits, and nested OpenGL elapsed queries no longer generate validation errors. Final staged, windowed OpenGL `game/airdefense1` stencil/mapped qualification passed 2/2 with retained engine captures under `.tmp/shadowmap-review/final-ab-runtime-6/`; stencil measured 96.8 Hz at p95 14 ms and mapped measured 74.8 Hz at p95 16 ms, while the mapped capture keeps the start-area buggy, crates, arches, and rails grounded without the former light-corner gap. A matching direct-Vulkan mapped smoke passed at 83.7 Hz and p95 15 ms with a clean capture and no Vulkan validation/call failure under `.tmp/shadowmap-review/final-vk-runtime-5/`. The low-frequency telemetry rerun under `.tmp/shadowmap-review/final-telemetry-6/` recorded 22 lights with six supported point lights, four local and four global mapped ownerships, 212 admitted casters, two successful translucent receiver chains, three complete fail-closed stencil fallbacks, 48 rendered point faces, zero unshadowed/render/mask/receiver failures, and 43 completed plus 21 still-pending asynchronous elapsed-time queries with zero synchronous waits, slot exhaustion, drops, or query failures.
- [x] Known stock startup warnings are resolved without replacement content: the three brown-fluid images and large water splash omitted from the retail PK4s use fail-after-primary shipped-media fallbacks, generated TrueType atlas materials bind their already-uploaded intrinsic images on first parse and survive renderer restart, wide loading backgrounds retain atomic publication under long Windows save paths through a root-relative 128-bit CSPRNG staging identity, generated image caches fall back from the legacy qpath to a versioned SHA-256/128 compact identity without bypassing VFS or pure-server policy, and rigid-body states that are immediately clamped or forced to rest remain developer diagnostics while unrecovered physics faults keep warning severity. Every binary-image header, mip record, and payload write now rejects short output, and the renderer evidence tools fail closed on either cache-write or expanded-loadscreen-publication warnings. The final staged, windowed OpenGL `game/airdefense1` cold run and same-savepath warm reuse run passed with engine captures and no warning, error, fatal, or asset-load-failure records under `.tmp/unrelated-warning-fixes/airdefense1-compact-cache-cold-longpath-final-2/`: the fixture held the valid expanded TGA at 240 characters, reduced its formerly failing 263-character staging path to 222, forced nine overlong legacy cache identities onto compact paths, left no staging files behind, and preserved byte hashes plus modification times for all eight persistent stock/image-program compact caches on warm load. The generated loadscreen derivative alone refreshed as expected when its source TGA was atomically regenerated.
- [x] Muzzle flashes, bright projectiles, and explosions now light the world the way Quake II and Quake III did, through the new default-on `g_classicDynamicLights`. Firing raises a short, wide world flash at the barrel on top of the weapon's authored one; rockets, plasma bolts, dark matter spheres, and napalm carry their own light; and detonations flash the surrounding geometry, which no shipped Quake 4 explosion effect did at all. Colors are taken from the shipped assets rather than invented - muzzle flashes use each weapon def's own `flashColor`, and projectile and explosion colors come from the light segments Raven authored in `effects/weapons` and `effects/monsters` - so a classic light reads as part of the effect it belongs to. Projectiles whose def authors a light, and the single-player rocket and grenade whose shipped trail effects already carry a light segment, are left untouched; bullets, nails, debris, and glass are deliberately unlit. At most 24 one-shot flashes are alive at once, all unshadowed, distance-culled, and recycled oldest-first. `g_classicDynamicLightScale` scales their radius between 0.25 and 4, content can override or opt out per entity def with `classic_light`, `classic_light_color`, and `classic_light_radius`, and the cheat command `testClassicLight` raises them without firing a shot.
- [ ] Finish Milestone A release qualification by repeating and retaining the full job, renderer-budget, retail-baseline, and human-review evidence from clean committed source and a freshly staged final package, then recording the required release platform/driver coverage.

## macOS Evidence Gate
Expand Down
103 changes: 103 additions & 0 deletions docs/user/classic-dynamic-lights.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Classic Dynamic Lights

Quake II and Quake III lit the world from the action itself. Every muzzle flash threw a pool of light
across the room, every rocket and plasma ball carried its own glow down the corridor, and every
explosion flashed the walls for a tenth of a second. Quake 4 replaced that with authored BSE effects,
and most of the shipped effects carry no light at all: apart from the single-player rocket and
grenade trails, player projectiles are unlit, and **no explosion in the game flashes the room**.

openQ4 adds that classic layer back. It is on by default.

## Quick Reference

| Setting | Default | Scope | What it does |
|---|---:|---|---|
| `g_classicDynamicLights` | `1` | SP and MP game code | Quake II/III style dynamic lights on muzzle flashes, bright projectiles and explosions. |
| `g_classicDynamicLightScale` | `1` | SP and MP game code | Radius multiplier for those lights, `0.25` to `4`. |

Both are archived, so a change survives a restart.

## What it adds

**Muzzle flashes.** Firing raises a short, wide world light at the barrel — roughly 100 ms, and half
again the radius of the weapon's own authored flash. It is layered on top of the stock flash rather
than replacing it, so the shot reads as a punchier pop that briefly reaches further into the room.
Weapons that carry no flash light of their own get one from this.

**Bright projectiles.** A rocket, plasma bolt or dark matter sphere carries a light with it. This
only fills gaps: a projectile whose def authors its own light (`mtr_light_shader`) keeps that light
untouched, and the single-player rocket and grenade — whose shipped trail effects already contain a
light segment — are left alone so their glow is not doubled. Their multiplayer trails carry no light
segment, so those do take the classic light.

**Explosions.** A detonation flashes the surrounding geometry and fades over 120–400 ms depending on
what went off. This is entirely new: nothing in the shipped explosion effects lights the room.
Exploding barrels and damagables get it too.

Bullets, nails, debris and glass deliberately get nothing. They are not bright, there are far too
many of them in flight to afford lighting them, and Quake II and Quake III did not light them either.

## Colors

The colors are taken from the shipped Quake 4 assets rather than invented, so a classic light reads
as part of the effect it belongs to instead of a wash of arbitrary color over it.

Muzzle flashes use the firing weapon's own `flashColor`, whatever a mod sets it to. For stock
weapons that is:

| Weapon | `flashColor` | Reads as |
|---|---|---|
| Blaster, Hyperblaster, Gauntlet | `0.7 0.8 1` | blue-white |
| Machinegun, Shotgun, Nailgun | `1 0.8 0.4` | warm white |
| Rocket Launcher, Grenade Launcher, Napalm Gun, Dark Matter Gun | `0.99 0.84 0.31` | amber |
| Railgun | `0.72 1 0.9` | pale green-white |
| Lightning Gun | `0.5 0.8 1` | pale blue |

Projectile and explosion colors come from the light segments Raven did author elsewhere in the same
asset set:

| Class | Color | Source |
|---|---|---|
| Rocket | `0.906 0.518 0.161` | `effects/weapons/rocketlauncher/fly.fx` |
| Grenade | `0.973 0.286 0.086` | `effects/weapons/grenadelauncher/trail.fx` |
| Napalm | `0.922 0.545 0.322` | `effects/weapons/napalmgun/globburn.fx` |
| Dark matter | `0.502 0 1` | `effects/weapons/dmg/core.fx` |
| Energy bolts | `0.7 0.8 1` | the energy weapons' own `flashColor` |
| Explosions | `1 0.824 0.290` | `effects/monsters/strogg_flyer/bomb_burst.fx` |

## Content overrides

An entity def can override the class the table picks for it:

```
"classic_light" "0" // never give this one a classic light
"classic_light_color" "1 0.5 0.2" // use this color instead of the table's
"classic_light_radius" "180" // tracking light radius, in units
```

`classic_light_radius` also overrides the "the shipped effect already lights this" rule, so a mod
that replaces the single-player rocket trail with an unlit one can ask for the classic light back.

## Cost and tuning

Each of these is a real light in this renderer, not the cheap vertex tint it was in Quake II. They
are all unshadowed, at most 24 one-shot flashes are alive at a time, flashes more than about 3000
units from the viewer are skipped, and the oldest flash is recycled when the pool is full.

If the effect is too strong for your taste, lower `g_classicDynamicLightScale` before turning the
feature off — `0.5` keeps the character at half the reach. Setting `g_classicDynamicLights 0` retires
every live flash immediately and stops new ones; projectiles already in flight keep the light they
were launched with until they expire.

`g_projectileLights 0` still hides projectile lights, classic ones included, and `g_muzzleFlash 0`
still suppresses muzzle flashes.

## Looking at them

With cheats enabled, `testClassicLight` raises the flashes in front of you without firing a shot:

```
testClassicLight // one muzzle flash and one explosion
testClassicLight muzzle weapon_railgun // that weapon's flash color
testClassicLight explosion projectile_dmg // that projectile class's detonation flash
```
15 changes: 15 additions & 0 deletions docs/user/gameplay-settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ The auto-skip cinematics, corpse cleanup, and corpse sink controls are also avai
| `g_corpseRemoveDelaySP` | `0` | Single-player | Controls how long SP corpses remain before disappearing. `0` uses stock timing, `-1` disables corpse removal. |
| `g_corpseRemoveDelayMP` | `0` | Multiplayer | Controls how long MP corpses remain before disappearing. `0` uses stock timing, `-1` disables corpse removal. |
| `g_corpseSink` | `0` | SP and MP game code | Selects corpse sink mode instead of the normal dissolve or burn-away behavior. |
| `g_classicDynamicLights` | `1` | SP and MP game code | Quake II/III style dynamic lights on muzzle flashes, bright projectiles and explosions. On by default. |
| `g_classicDynamicLightScale` | `1` | SP and MP game code | Radius multiplier for the classic dynamic lights, `0.25` to `4`. |
| `s_musicVolume` | `0.5` | Client audio | Controls music volume independently of the main sound mix. |
| `hud_damageNumbers` | `0` | Multiplayer client | Floating damage numbers over the players you hit. `0` off, `1` opponents only, `2` all damage you deal. |
| `hud_damageNumberStyle` | `1` | Multiplayer client | How damage numbers are coloured. `1` white through red, `2` one colour per damage band, `3` one colour per weapon. |
Expand Down Expand Up @@ -202,6 +204,19 @@ seta hud_damageNumberStyle 2
seta hud_damageNumberScale 1.25
```

## Classic Dynamic Lights

`g_classicDynamicLights` restores the Quake II / Quake III habit of lighting the world from the
action: muzzle flashes throw a short, wide pool of light, bright projectiles carry their own glow,
and explosions flash the surrounding geometry. It is on by default, and the colors come from the
shipped Quake 4 assets.

`g_classicDynamicLightScale` scales the radius of all of them between `0.25` and `4`. Lower it
before turning the feature off if the effect is stronger than you want.

See [Classic Dynamic Lights](classic-dynamic-lights.md) for the per-weapon colors, the content
override keys, and the `testClassicLight` console command.

## Example Presets

### Fast Testing Setup
Expand Down
Loading