diff --git a/include/light/entities.hh b/include/light/entities.hh index 27c5835e..b27995f6 100644 --- a/include/light/entities.hh +++ b/include/light/entities.hh @@ -72,6 +72,7 @@ public: public: lockable_vec_t light, atten, formula, spotangle, spotangle2, style, anglescale; lockable_vec_t dirtscale, dirtgain, dirt, deviance, samples, projfov; + lockable_vec_t dirt_off_radius, dirt_on_radius; lockable_bool_t bleed; lockable_vec3_t origin, color, mangle, projangle; lockable_string_t project_texture; @@ -105,6 +106,8 @@ public: deviance { "deviance", 0 }, samples { "samples", 16 }, projfov { "project_fov", 90 }, + dirt_off_radius { "dirt_off_radius", 0.0f }, + dirt_on_radius { "dirt_on_radius", 0.0f }, bleed { "bleed", false }, origin { "origin", 0, 0, 0 }, color { "color", 255.0f, 255.0f, 255.0f, vec3_transformer_t::NORMALIZE_COLOR_TO_255 }, @@ -123,6 +126,7 @@ public: return {{ &light, &atten, &formula, &spotangle, &spotangle2, &style, &bleed, &anglescale, &dirtscale, &dirtgain, &dirt, &deviance, &samples, &projfov, + &dirt_off_radius, &dirt_on_radius, &origin, &color, &mangle, &projangle, &project_texture }}; } diff --git a/light/ltface.cc b/light/ltface.cc index 29be10c3..38285709 100644 --- a/light/ltface.cc +++ b/light/ltface.cc @@ -1081,6 +1081,13 @@ Light_ClampMin(lightsample_t *sample, const vec_t light, const vec3_t color) } } +static float fraction(float min, float val, float max) { + if (val >= max) return 1.0; + if (val <= min) return 0.0; + + return (val - min) / (max - min); +} + /* * ============ * Dirt_GetScaleFactor @@ -1089,7 +1096,7 @@ Light_ClampMin(lightsample_t *sample, const vec_t light, const vec3_t color) * ============ */ static inline vec_t -Dirt_GetScaleFactor(const globalconfig_t &cfg, vec_t occlusion, const light_t *entity, const lightsurf_t *surf) +Dirt_GetScaleFactor(const globalconfig_t &cfg, vec_t occlusion, const light_t *entity, const vec_t entitydist, const lightsurf_t *surf) { vec_t light_dirtgain = cfg.dirtGain.floatValue(); vec_t light_dirtscale = cfg.dirtScale.floatValue(); @@ -1145,6 +1152,26 @@ Dirt_GetScaleFactor(const globalconfig_t &cfg, vec_t occlusion, const light_t *e outDirt = 1.0f; } + /* lerp based on distance to light */ + if (entity) { + // From 0 to _dirt_off_radius units, no dirt. + // From _dirt_off_radius to _dirt_on_radius, the dirt linearly ramps from 0 to full, and after _dirt_on_radius, it's full dirt. + + if (entity->dirt_on_radius.isChanged() + && entity->dirt_off_radius.isChanged()) { + + const float onRadius = entity->dirt_on_radius.floatValue(); + const float offRadius = entity->dirt_off_radius.floatValue(); + + if (entitydist < offRadius) { + outDirt = 0.0; + } else if (entitydist >= offRadius && entitydist < onRadius) { + const float frac = fraction(offRadius, entitydist, onRadius); + outDirt = frac * outDirt; + } + } + } + /* return to sender */ return 1.0f - outDirt; } @@ -1293,7 +1320,7 @@ GetDirectLighting(const globalconfig_t &cfg, raystream_t *rs, const vec3_t origi GetLightContrib(cfg, &entity, normal, origin, false, color, surfpointToLightDir, normalcontrib, &surfpointToLightDist); - const float dirt = Dirt_GetScaleFactor(cfg, occlusion, &entity, /* FIXME: pass */ nullptr); + const float dirt = Dirt_GetScaleFactor(cfg, occlusion, &entity, surfpointToLightDist, /* FIXME: pass */ nullptr); VectorScale(color, dirt, color); // NOTE: Skip negative lights, which would make no sense to bounce! @@ -1332,7 +1359,7 @@ GetDirectLighting(const globalconfig_t &cfg, raystream_t *rs, const vec3_t origi float dirt = 1; if (sun.dirt) { - dirt = Dirt_GetScaleFactor(cfg, occlusion, nullptr, /* FIXME: pass */ nullptr); + dirt = Dirt_GetScaleFactor(cfg, occlusion, nullptr, 0.0, /* FIXME: pass */ nullptr); } VectorMA(colorout, dirt * cosangle * sun.sunlight / 255.0f, sun.sunlight_color, colorout); @@ -1392,7 +1419,7 @@ LightFace_Entity(const bsp2_t *bsp, GetLightContrib(cfg, entity, surfnorm, surfpoint, lightsurf->twosided, color, surfpointToLightDir, normalcontrib, &surfpointToLightDist); - const float occlusion = Dirt_GetScaleFactor(cfg, lightsurf->occlusion[i], entity, lightsurf); + const float occlusion = Dirt_GetScaleFactor(cfg, lightsurf->occlusion[i], entity, surfpointToLightDist, lightsurf); VectorScale(color, occlusion, color); /* Quick distance check first */ @@ -1481,7 +1508,7 @@ LightFace_Sky(const sun_t *sun, const lightsurf_t *lightsurf, lightmapdict_t *li angle = (1.0 - sun->anglescale) + sun->anglescale * angle; float value = angle * sun->sunlight; if (sun->dirt) { - value *= Dirt_GetScaleFactor(cfg, lightsurf->occlusion[i], NULL, lightsurf); + value *= Dirt_GetScaleFactor(cfg, lightsurf->occlusion[i], NULL, 0.0, lightsurf); } vec3_t color, normalcontrib; @@ -1548,7 +1575,7 @@ LightFace_Min(const bsp2_t *bsp, const bsp2_dface_t *face, vec_t value = light; if (cfg.minlightDirt.boolValue()) { - value *= Dirt_GetScaleFactor(cfg, lightsurf->occlusion[i], NULL, lightsurf); + value *= Dirt_GetScaleFactor(cfg, lightsurf->occlusion[i], NULL, 0.0, lightsurf); } if (cfg.addminlight.boolValue()) { Light_Add(sample, value, color, vec3_origin); @@ -1608,7 +1635,7 @@ LightFace_Min(const bsp2_t *bsp, const bsp2_dface_t *face, vec_t value = entity.light.floatValue(); lightsample_t *sample = &lightmap->samples[i]; - value *= Dirt_GetScaleFactor(cfg, lightsurf->occlusion[i], &entity, lightsurf); + value *= Dirt_GetScaleFactor(cfg, lightsurf->occlusion[i], &entity, 0.0 /* TODO: pass distance */, lightsurf); if (cfg.addminlight.boolValue()) { Light_Add(sample, value, *entity.color.vec3Value(), vec3_origin); } else { @@ -1640,7 +1667,7 @@ LightFace_DirtDebug(const lightsurf_t *lightsurf, lightmapdict_t *lightmaps) /* Overwrite each point with the dirt value for that sample... */ for (int i = 0; i < lightsurf->numpoints; i++) { lightsample_t *sample = &lightmap->samples[i]; - const float light = 255 * Dirt_GetScaleFactor(cfg, lightsurf->occlusion[i], NULL, lightsurf); + const float light = 255 * Dirt_GetScaleFactor(cfg, lightsurf->occlusion[i], NULL, 0.0, lightsurf); VectorSet(sample->color, light, light, light); } @@ -1832,7 +1859,7 @@ LightFace_Bounce(const bsp2_t *bsp, const bsp2_dface_t *face, const lightsurf_t * Except, not in bouncedebug mode. */ if (debugmode != debugmode_bounce) { - const vec_t dirtscale = Dirt_GetScaleFactor(cfg, lightsurf->occlusion[i], NULL, lightsurf); + const vec_t dirtscale = Dirt_GetScaleFactor(cfg, lightsurf->occlusion[i], NULL, 0.0, lightsurf); VectorScale(indirect, dirtscale, indirect); } diff --git a/testmaps/dirttest2.map b/testmaps/dirttest2.map index 3a4d94e7..26a1fd5b 100644 --- a/testmaps/dirttest2.map +++ b/testmaps/dirttest2.map @@ -4,16 +4,53 @@ { "classname" "worldspawn" "wad" "free_wad.wad" +"_dirt" "1" // brush 0 { ( -1056 -864 576 ) ( -1056 -880 576 ) ( -1056 -864 896 ) stuff4 0 0 0 1 1 ( -1248 -1152 576 ) ( -1256 -1144 576 ) ( -1248 -1152 736 ) stuff4 0 0 0 1 1 ( -1312 -936 576 ) ( -1312 -920 576 ) ( -1312 -936 832 ) stuff4 0 0 0 1 1 -( -1024 -896 456 ) ( -1024 -896 480 ) ( -1056 -896 480 ) stuff4 0 0 0 1 1 +( -1024 -592 456 ) ( -1024 -592 480 ) ( -1056 -592 480 ) stuff4 -0 -0 -0 1 1 ( -1136 -1152 576 ) ( -1152 -1152 576 ) ( -1136 -1152 832 ) stuff4 0 0 0 1 1 ( -1096 -1152 736 ) ( -1080 -1152 736 ) ( -1096 -1184 736 ) stuff4 0 0 0 -1 1 ( -1120 -1184 576 ) ( -1120 -1200 576 ) ( -1056 -1184 576 ) stuff4 0 0 0 1 1 } +// brush 1 +{ +( -1280 -896 896 ) ( -1088 -896 912 ) ( -1088 -896 896 ) stuff4 32 0 0 1 1 +( -1280 -896 896 ) ( -1280 -640 912 ) ( -1280 -896 912 ) stuff4 32 0 0 1 1 +( -1280 -896 896 ) ( -1088 -640 896 ) ( -1280 -640 896 ) stuff4 32 0 0 1 1 +( -1280 -896 912 ) ( -1088 -640 912 ) ( -1088 -896 912 ) stuff4 32 0 0 1 1 +( -1280 -592 896 ) ( -1088 -592 912 ) ( -1280 -592 912 ) stuff4 32 -0 -0 1 1 +( -1056 -896 896 ) ( -1056 -640 912 ) ( -1056 -640 896 ) stuff4 32 -0 -0 1 1 +} +// brush 2 +{ +( -1232 -1136 928 ) ( -1056 -1136 944 ) ( -1056 -1136 928 ) stuff4 0 0 0 1 1 +( -1232 -1136 928 ) ( -1232 -896 944 ) ( -1232 -1136 944 ) stuff4 0 0 0 1 1 +( -1232 -1136 928 ) ( -1056 -896 928 ) ( -1232 -896 928 ) stuff4 0 0 0 1 1 +( -1232 -1136 944 ) ( -1056 -896 944 ) ( -1056 -1136 944 ) stuff4 0 0 0 1 1 +( -1232 -912 928 ) ( -1056 -912 944 ) ( -1232 -912 944 ) stuff4 -0 -0 -0 1 1 +( -1056 -1136 928 ) ( -1056 -896 944 ) ( -1056 -896 928 ) stuff4 0 0 0 1 1 +} +// brush 3 +{ +( -1056 -1152 720 ) ( -1024 -1152 736 ) ( -1024 -1152 720 ) stuff4 -0 16 -0 1 1 +( -1056 -1152 720 ) ( -1056 -864 736 ) ( -1056 -1152 736 ) stuff4 -0 16 -0 1 1 +( -1056 -1152 720 ) ( -1024 -864 720 ) ( -1056 -864 720 ) stuff4 -0 -0 -0 1 1 +( -1056 -1152 928 ) ( -1024 -864 928 ) ( -1024 -1152 928 ) stuff4 -0 -0 -0 1 1 +( -1056 -592 720 ) ( -1024 -592 736 ) ( -1056 -592 736 ) stuff4 -0 16 -0 1 1 +( -1024 -1152 720 ) ( -1024 -864 736 ) ( -1024 -864 720 ) stuff4 -0 16 -0 1 1 +} +// brush 4 +{ +( -1248 -592 720 ) ( -1056 -592 736 ) ( -1056 -592 720 ) stuff4 0 0 0 1 1 +( -1248 -592 720 ) ( -1248 -560 736 ) ( -1248 -592 736 ) stuff4 0 0 0 1 1 +( -1248 -592 720 ) ( -1056 -560 720 ) ( -1248 -560 720 ) stuff4 0 0 0 1 1 +( -1248 -592 896 ) ( -1056 -560 896 ) ( -1056 -592 896 ) stuff4 -0 -0 -0 1 1 +( -1248 -576 720 ) ( -1056 -576 736 ) ( -1248 -576 736 ) stuff4 -0 -0 -0 1 1 +( -1056 -592 720 ) ( -1056 -560 736 ) ( -1056 -560 720 ) stuff4 0 0 0 1 1 +} } // entity 1 { @@ -117,7 +154,7 @@ } // brush 5 { -( -1088 -1240 760 ) ( -1088 -1240 768 ) ( -1088 -808 768 ) stuff4 32 0 90 1 1 +( -1056 -1240 760 ) ( -1056 -1240 768 ) ( -1056 -808 768 ) stuff4 32 -0 90 1 1 ( -1272 -912 928 ) ( -1272 -912 896 ) ( -1280 -896 896 ) stuff4 32 0 90 1 1 ( -1072 -896 896 ) ( -1104 -896 896 ) ( -1104 -896 888 ) stuff4 32 0 90 1 1 ( -1272 -912 896 ) ( -1272 -912 928 ) ( -1088 -912 928 ) stuff4 0 -16 0 1 1 @@ -135,7 +172,7 @@ } // brush 7 { -( -1088 -1240 768 ) ( -1088 -808 768 ) ( -1088 -808 760 ) stuff4 32 0 90 1 1 +( -1056 -1240 768 ) ( -1056 -808 768 ) ( -1056 -808 760 ) stuff4 32 -0 90 1 1 ( -1248 -1152 896 ) ( -1240 -1136 896 ) ( -1240 -1136 928 ) stuff4 32 0 90 1 1 ( -1088 -1136 928 ) ( -1272 -1136 928 ) ( -1272 -1136 896 ) stuff4 0 -16 0 1 1 ( -1104 -1152 888 ) ( -1104 -1152 896 ) ( -1072 -1152 896 ) stuff4 32 0 90 1 1 @@ -157,7 +194,7 @@ "classname" "func_group" // brush 0 { -( -1216 -912 512 ) ( -1216 -928 512 ) ( -1216 -912 768 ) stuff4 32 0 0 1 1 +( -1056 -912 512 ) ( -1056 -928 512 ) ( -1056 -912 768 ) stuff4 32 -0 -0 1 1 ( -1248 -1152 512 ) ( -1248 -1152 832 ) ( -1248 -1184 832 ) stuff4 32 0 0 1 1 ( -1248 -1152 832 ) ( -1248 -1152 512 ) ( -1024 -1152 512 ) stuff4 0 0 0 -1 1 ( -1192 -1184 512 ) ( -1208 -1184 512 ) ( -1192 -1184 768 ) stuff4 32 0 0 1 1 @@ -177,7 +214,7 @@ { ( -1248 -864 640 ) ( -1248 -880 640 ) ( -1248 -864 960 ) stuff4 32 0 0 1 1 ( -1280 -896 896 ) ( -1280 -896 736 ) ( -1280 -864 736 ) stuff4 32 0 0 1 1 -( -1056 -864 520 ) ( -1056 -864 544 ) ( -1088 -864 544 ) stuff4 32 0 0 1 1 +( -1056 -592 520 ) ( -1056 -592 544 ) ( -1088 -592 544 ) stuff4 32 -0 -0 1 1 ( -1280 -896 736 ) ( -1280 -896 896 ) ( -1248 -896 896 ) stuff4 32 0 0 1 1 ( -1128 -1120 896 ) ( -1112 -1120 896 ) ( -1128 -1152 896 ) stuff4 32 0 0 1 1 ( -1160 -1152 736 ) ( -1160 -1168 736 ) ( -1096 -1152 736 ) stuff4 32 0 0 1 1 @@ -229,7 +266,7 @@ } // brush 8 { -( -1088 -912 576 ) ( -1088 -928 576 ) ( -1088 -912 832 ) stuff4 32 0 0 1 1 +( -1056 -912 576 ) ( -1056 -928 576 ) ( -1056 -912 832 ) stuff4 32 -0 -0 1 1 ( -1248 -1152 576 ) ( -1248 -1152 896 ) ( -1248 -1184 896 ) stuff4 32 0 0 1 1 ( -1248 -1152 896 ) ( -1248 -1152 576 ) ( -1024 -1152 576 ) stuff4 0 0 0 -1 1 ( -1192 -1184 576 ) ( -1208 -1184 576 ) ( -1192 -1184 832 ) stuff4 32 0 0 1 1 @@ -252,3 +289,12 @@ "origin" "-1152 -1024 760" "angle" "180" } +// entity 6 +{ +"classname" "light" +"origin" "-1272 -1096 856" +"angle" "-0" +"wait" "0.3" +"_dirt_off_radius" "100" +"_dirt_on_radius" "500" +}