Light walls with the warm colour of muzzle flashes and explosions

Muzzle flashes, bullet impacts and explosions lit walls and snow blue or
cyan while their own flash and fireball sprites stayed orange. The effect
colour is stored B,G,R,A. render_fx swaps it once to R,G,B,A for every
sprite, trail and spark, and the light path then passed that value to a
helper that swapped red and blue a second time. GfxLightPack.color is
R,G,B like a map primary light, so every effect omni and spot light came
out with red and blue reversed.

The helper is now elem_light_color_rgb and keeps the order. The light
instance field and the omni and spot pack parameters are renamed
color_rgb so the names say what the value holds. Read in the same order
the sprites use, the light elements of these effects are amber and
orange, matching their flash and fireball sprites.

Measured on the Mac on mp_subbase, facing the concrete wall above the
snow bank: the light an RPG blast adds to wall and snow went from linear
R:G:B 0.28:0.81:1.00 (cyan) to 1.00:0.82:0.33 (amber), and an M4 burst
from 0.34:0.48:1.00 (blue) to 1.00:0.60:0.55 (warm). Wall and snow
before the shots are unchanged, since map lights take another path. On
an iPhone build on mp_subbase, a long burst at a concrete wall lit it
warm instead of blue.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
JohnM
2026-10-13 20:24:01 +10:00
parent f46d5aadcd
commit 679118da0b
6 changed files with 15 additions and 18 deletions
+1 -1
View File
@@ -205,7 +205,7 @@ pub struct FxElemLightInstance {
pub is_spot: bool,
pub origin: [f32; 3],
pub radius: f32,
pub color_bgr: [f32; 3],
pub color_rgb: [f32; 3],
pub axis: [[f32; 3]; 3],
}
+3 -6
View File
@@ -94,11 +94,8 @@ pub fn cull_elem_light(
}
#[inline]
pub fn elem_light_color_bgr(color_rgba: [u8; 4], scale: f32) -> [f32; 3] {
pub fn elem_light_color_rgb(color_rgba: [u8; 4], scale: f32) -> [f32; 3] {
let s = scale * (crate::FX_RECIP_255 as f32);
[
color_rgba[2] as f32 * s,
color_rgba[1] as f32 * s,
color_rgba[0] as f32 * s,
]
let [r, g, b, _a] = color_rgba;
[r as f32 * s, g as f32 * s, b as f32 * s]
}
+1 -1
View File
@@ -95,7 +95,7 @@ pub use collide::{
};
pub use cull::{
FX_ELEM_FLAG_CULL_DRAW_5_PLANES, cull_cloud, cull_cloud_plane_count, cull_cloud_radius,
cull_elem_for_spawn_allows, cull_elem_light, cull_sphere, elem_light_color_bgr,
cull_elem_for_spawn_allows, cull_elem_light, cull_sphere, elem_light_color_rgb,
};
pub use draw::{FX_DRAW_ELEM_HANDLER_PRESENT, FxElemType, draw_elem_handler_present};
pub use effect_def::FxEffectDef;
+6 -6
View File
@@ -212,10 +212,10 @@ pub fn add_omni_light_to_scene_allows(
Ok(())
}
pub fn omni_light_pack(origin: [f32; 3], radius: f32, color_bgr: [f32; 3]) -> GfxLightPack {
pub fn omni_light_pack(origin: [f32; 3], radius: f32, color_rgb: [f32; 3]) -> GfxLightPack {
GfxLightPack {
light_type: GFX_LIGHT_TYPE_OMNI,
color: color_bgr,
color: color_rgb,
direction: [0.0; 3],
origin,
radius,
@@ -281,7 +281,7 @@ pub fn spot_light_pack(
origin: [f32; 3],
forward: [f32; 3],
radius: f32,
color_bgr: [f32; 3],
color_rgb: [f32; 3],
cone: SpotLightConeDvars,
) -> GfxLightPack {
let end = spot_light_clamp_end(cone.start_radius, cone.end_radius, radius);
@@ -301,9 +301,9 @@ pub fn spot_light_pack(
GfxLightPack {
light_type: GFX_LIGHT_TYPE_SPOT,
color: [
color_bgr[0] * cone.brightness,
color_bgr[1] * cone.brightness,
color_bgr[2] * cone.brightness,
color_rgb[0] * cone.brightness,
color_rgb[1] * cone.brightness,
color_rgb[2] * cone.brightness,
],
direction: dir,
origin,
@@ -707,7 +707,7 @@ fn commit_fx_transaction(
light.origin,
light.axis[0],
light.radius,
light.color_bgr,
light.color_rgb,
spot_cone,
)),
Err(lighting_iw4::AddOmniLightRefuse::Cap) => {
@@ -725,7 +725,7 @@ fn commit_fx_transaction(
Ok(()) => env.dlights.scene.push(lighting_iw4::omni_light_pack(
light.origin,
light.radius,
light.color_bgr,
light.color_rgb,
)),
Err(lighting_iw4::AddOmniLightRefuse::Cap) => {
env.dlights.cap_full = env.dlights.cap_full.saturating_add(1);
+2 -2
View File
@@ -19,7 +19,7 @@ use fx::{
use fx_iw4::{
FX_ELEM_ATLAS_OFF, FX_ELEM_ATLAS_SIZE, FxElemType, FxRandomChannel, apply_lighting_frac_bgra,
build_cloud, clamp_elem_rotation_time, cull_cloud, cull_elem_light,
effect_def_needs_lighting_sample, elem_light_color_bgr, elem_uses_lighting_frac,
effect_def_needs_lighting_sample, elem_light_color_rgb, elem_uses_lighting_frac,
evaluate_rotation_total, evaluate_scale, evaluate_size0, evaluate_size1, get_elem_angles_axis,
get_velocity_at_time, sample_f32, sprite_atlas_uv, vec3_normalize, vis_blocker_add_prepared,
};
@@ -1467,7 +1467,7 @@ pub fn build_fx_verts(
is_spot: ctx.elem_type == FxElemType::SpotLight as u8,
origin: ctx.origin,
radius: size0,
color_bgr: elem_light_color_bgr(color, scale),
color_rgb: elem_light_color_rgb(color, scale),
axis,
})
};