EWTOOLS-LIGHT(1)
โจ EWTOOLS-LIGHT(1) โจ
okay bestie, welcome to ewtools-light (also known as light, same girl different name ๐
) from the ericw-tools family. she's a compiler utility, she's iconic, and she's about to explain lightmaps to you like it's a group chat. strap in. ๐
๐ธ NAME ๐ธ
ewtools-light โ cacluate lightmap data for a Quake BSP file. yes, "cacluate". no, we're not fixing it. it's vintage. it's giving โจ character โจ.
also answers to light, her government name. same vibe, same job, same girl.
๐ฆ SYNOPSIS ๐ฆ
light [OPTION]... BSPFILE
๐ DESCRIPTION ๐
so here's the tea, bestie: light opens up your Quake .bsp file and does the math on all the light and shadow stuff, using the entity definitions that are already chillin' inside that .bsp. once she's done calculating, she updates the .bsp file with the fresh new light data, and that data overwrites whatever lighting was there before. so like, the old lighting? gone. blocked. unfollowed. โจ
๐ OPTIONS ๐
real talk first: literally any of the Worldspawn Keys listed down in the next section can be passed as a command-line option, and if you do that, it overrides whatever setting is in worldspawn. command line stays winning, periodt.
๐ Logging
-logโ write log files. this is on by default, she's diligent like that.-nologโ don't write log files. okay, closed-book exam then.-verbose-vโ verbose output. she will tell you everything, and honestly? slay.-nopercentโ don't output percentage messages.-nostatโ don't output statistic messages.-noprogressโ don't output progress messages.-nocolorโ don't output color codes (for TB, etc).-quiet-noverboseโ suppress non-important messages. this is literally equivalent to-nopercent -nostat -noprogress, same combo, different outfit.
๐ Game
-gamedir"relative/path" or "C:/absolute/path" โ override the default mod base directory. if you don't set it, or if what you set is relative, she'll derive it from the input file or from the basedir if you specified one. girl does her own research. ๐-basedir"relative/path" or "C:/absolute/path" โ override the default game base directory. same deal: not set, or set but relative, and she derives it from the input file or the gamedir if you specified one. independent queen. ๐-filepriorityarchive | loose โ which types of archives (folders/loose files, or packed archives) get higher priority and get picked first when she's searching paths.-path"/path/to/folder" <multiple allowed> โ extra paths or archives to add to the search path, mostly for loose files. you can stack these, she's not gonna stop you.-q2rtxโ adjust settings to best support Q2RTX.-defaultpathsโ whether the compiler should attempt to automatically derive game/base paths for games that support it. enabled by default.-nodefaultpathsโ opt out of-defaultpaths.
๐ฅ Performance
-lowpriority[0] โ run at lower priority so other processes get some breathing room. generous of her, honestly ๐ซถ-threadsn โ set the number of threads explicitly. by default,lighttries to sniff out how many CPUs/cores you've got.-extraโ calculate extra samples (2x2) and average the results for smoother shadows. lowkey the glow-up.-extra4โ calculate even MORE samples (4x4) and average the results for smoother shadows. highkey the glow-up.-gaten โ set a minimum light level, below which she counts it as zero brightness. this can dramatically speed things up when you've got a huge number of lights with inverse or inverse square falloff. in most cases, values below 1.0 cause no discernible visual differences. default 0.001.-sunsamples[n] โ set the number of samples to use for_sunlight_penumbraand_sunlight2(heads up: sunlight2 may use more or fewer because of how the suns get set up in a sphere ๐). default 100.-surflight_subdivide[n] โ configure the spacing of all surface lights. default 16 units. the value must be between 1 and 8192. she says: in the future she'd like to make this configurable per-surface-light. someday โจ-emissivequalitylow | high โ for emissive surfaces (both direct light and bounced light), either use a single point in the middle of the face (low), or subdivide the face into multiple points, which gives anti-aliased results and more shadows, at the cost of compile time (high). when you're using high, you can usesurflight_subdivideto control the point spacing and get better anti-aliasing. default is low.
๐ง Output format options
-litโ force generation of a.litfile, even if your map has zero coloured lights. by defaultlightwill just automatically generate the.litwhen it's needed.-world_units_per_luxeln โ enables output ofDECOUPLED_LMBSPX lump.-onlyentsโ updates the entities lump in the bsp. you should run this after running qbsp with-onlyents, if your map uses any switchable lights. all it does is assign style numbers to each switchable light. that's it, that's the whole job.-litonlyโ generate a.litfile that is compatible with the.bspwithout modifying the.bsp. this one's for tweaking lighting or adding colored lights when you can't modify an existing.bsp(like for multiplayer maps, bestie ๐ฎ). typically you'd make a temporary copy of the.bsp, update the lights in the entity lump (for example with"qbsp -onlyents"), then re-light it with"light -litonly". heads up: engines may enforce a restriction that you can't make areas brighter than they originally were (that's cheat protection, and it will catch you). also, styled lights (flickering/switchable) can't be added in new areas, and their styles can't be changed.-nolightingโ do all the stuff required for lighting to work without actually performing any lighting calculations. mainly for engines that don't use the light data but still need switchable lights and so on.-nolightsโ ignore light entities (only sunlight/minlight). ๐-facestylesn โ max amount of styles per face; requires the BSPX lump if it's > 4.-exportobjโ export an.OBJfor inspection.-lmshiftn โ force a specified lmshift to be applied to the entire map. useful if you want to re-light a map with higher quality BSPX lighting without the sources. will add theLMSHIFTlump to the BSP.
๐ Postprocessing options
-soft[n] โ perform post-processing on the lightmap that averages adjacent samples to smooth out shadow edges. if n is specified, the algorithm takes n samples on each side of the sample point and replaces the original value with the average. so a value of 1 means averaging a 3x3 square centered on the original sample, 2 implies a 5x5 square, and so on and so on. if-softis specified but n is omitted, the value becomes whatever the level of oversampling you requested was. if there's no oversampling, then the implied value is 1.-extraimplies a value of 2, and-extra4implies 3. default 0 (off).
๐ Debug modes
-dirtdebugโ implies_dirt "1", and renders just the dirtmap against a fullbright background, ignoring all the lights in the map. chef's kiss for previewing and tuning the dirt settings. ๐-phongdebugโ write normals to the lit file for debugging phong shading.-bouncedebugโ write bounced lighting only to the lightmap, for debugging/previewing-bounce.-bouncelightsdebugโ only save bounced emitters lighting to the lightmap.-surflight_dumpโ saves the lights generated by surfacelights to a"mapname-surflights.map"file.-visapproxauto | none | rays | vis โ change the approximate visibility algorithm.- auto โ choose default based on format
- vis โ use BSP vis data (slow but precise).
- rays โ use sphere culling with fired rays (fast but may miss faces).
- none โ disable approximate visibility culling of lights, which has a small chance of introducing artifacts where lights cut off too soon.
-novisapproxโ alias for-visapprox none.-phongdebug_objโ save map as.objwith phonged normals.-debugoccludedโ save luxel occlusion data to lightmap.-debugneighboursโ save neighboring faces data to lightmap (requires-debugface).-debugmottleโ save mottle pattern (used by Q2 minlight, when opted in with_minlight_mottle) to lightmap.-debugfacex y z-debugvertx y z-highlightseams
๐งช Experimental options
these ones are the "in her lab era" options. still here, still real, just โจ experimental โจ.
-addminโ changes the behaviour of minlight. instead of raising low light levels up to the global minimum, it adds the global minimum light level to all style 0 lightmaps. this may help reduce that sometimes-uniform minlight effect.-lit2โ force generation of a.lit2file, even if your map has no coloured lights.-luxโ generate a.luxfile storing average incoming light directions for surfaces. usable by FTEQW with"r_deluxemapping 1".-bspxluxโ writes lux data into the bsp itself.-lmscalen โ equivalent to the"_lightmap_scale"worldspawn key.-bspxlitโ writes rgb data into the bsp itself.-bspxโ writes both rgb and directions data into the bsp itself.-bspxonlyโ writes both rgb and directions data only into the bsp itself.-hdrโ write.litfile with e5bgr9 data.-bspxhdrโ writes e5bgr9 data into the bsp itself.-novanillaโ fallback scaled lighting will be omitted. standard grey lighting will be omitted if there are coloured lights. implies-bspxlit. and-litwill no longer be implied by the presence of coloured lights. bye bestie ๐-wrnormalsโ writes normal data into the bsp itself.-arghradcompatโ enable compatibility for Arghrad-specific keys.-radlights"filename.rad" โ loads a<surfacename> <r> <g> <b> <intensity>file.-lightgridโ generates a lightgrid and writes it to a bspx lump (LIGHTGRID_OCTREE).-lightgrid_distx y z โ distance between lightgrid sample points, in world units. controls lightgrid size.-lightgrid_formatoctree โ lightgrid BSPX lump to use. currently there's only one supported format, octree. it's the only child. the chosen one. โญ
๐ MODEL ENTITY KEYS ๐
๐ธ Worldspawn Keys
the following keys can be added to the worldspawn entity:
"light""n""_minlight""n" โ set a global minimum light level of "n" across the whole map. this is an easy way to eliminate completely dark areas of the level, BUT you may lose some contrast as a result, so use with care, bestie. default 0.
Note: in Q2 mode, minlight uses a 0..1 range.
"_minlight_color""r g b""_mincolor""r g b" โ specify the red (r), green (g) and blue (b) components for the colour of the minlight. RGB component values are between 0 and 255 (between 0 and 1 is also accepted). default is white light ("255 255 255")."_maxlight""n""_dist""n" โ scales the fade distance of all lights by a factor of n. if n > 1, lights fade more quickly with distance, and if n < 1, lights fade more slowly with distance and the light reaches further.
...and that's only part 1, bestie. keep scrolling, there's more ๐
"_range" "n"โ rescales the brightness range of all the lights, and it does it without touching their fade distance. Son > 0.5makes lights brighter, andn < 0.5makes them less bright. Wanna do this for just one light instead? You can get the exact same effect on an individual light by tweaking both its"light"and"wait"attributes. ๐"_sunlight" "n","_sun_light" "n"โ sets how bright the sunlight is, like, the light coming from an unseen sun up in the sky. Sky brushes (or, more accurately, bsp leafs with sky contents) will emit sunlight at the angle your"_sun_mangle"key specifies. Default is0. โ๏ธ"_anglescale" "n","_anglesense" "n"โ sets the scaling of sunlight brightness as a function of the angle of incidence with a surface (there's a more detailed explanation waiting for you in the"_anglescale"light entity key below, bestie). โจ"_sunlight_mangle" "yaw pitch roll","_sun_mangle" "yaw pitch roll","_sun_angle" "yaw pitch roll"โ tells you the direction of the sunlight, using yaw, pitch and roll in degrees. Yaw is the angle around the Z-axis,0to359degrees. Pitch is the angle from90(shining straight up) all the way to-90(shining straight down from above). Roll has no effect, so honestly use any value you want (e.g.0). Default is straight down:"0 -90 0". ๐ค๏ธ"_sun2" "n","_sun2_color" "x y z","_sun2_mangle" "x y z"โ the source page doesn't spell these three out at all, so I'm not gonna make anything up. They're just here, holding space, being mysterious. ๐ซถ"_sunlight_penumbra" "n"โ the penumbra width of sunlight, in degrees. Useful values:3-4for a gentle soft edge, or10-20+for more diffuse sunlight. Default is0. ๐ธ"_sunlight_color" "r g b","_sun_color" "r g b"โ the red (r), green (g) and blue (b) components for the colour of the sunlight. RGB component values go between0and255(between0and1is also accepted, queen). Default is white light:"255 255 255". ๐ค"_sunlight2" "n"โ sets the brightness of a whole dome of lights arranged around the upper hemisphere. i.e. ambient light, coming from above the horizon. Default0. ๐"_sunlight_color2" "r g b","_sunlight2_color" "r g b"โ the colour of_sunlight2, same format as"_sunlight_color". Default is white light:"255 255 255"."_sunlight3" "n"โ literally the same as"_sunlight2", but for the bottom hemisphere (i.e. ambient light coming from below the horizon). Combine"_sunlight2"and"_sunlight3"and you get light coming equally from every direction, e.g. for levels floating in the clouds. Default0. โ๏ธ"_sunlight_color3" "r g b","_sunlight3_color" "r g b"โ the colour of"_sunlight3". Default is white light:"255 255 255"."_dirt" "n","_dirty" "n"โ1enables dirtmapping (ambient occlusion) on all lights, borrowed from q3map2. It adds shadows to corners and crevices, which is so good. You can override the global setting for specific lights with the"_dirt"light entity key, or with the"_sunlight_dirt","_sunlight2_dirt"and"_minlight_dirt"worldspawn keys. Default is no dirtmapping (-1)."_sunlight_dirt" "n"โ1enables dirtmapping (ambient occlusion) on sunlight,-1disables it (which makes it illuminate the dirtmapping shadows instead). Default is to use whatever value"_dirt"has."_sunlight2_dirt" "n"โ1enables dirtmapping (ambient occlusion) on sunlight2/3,-1disables it. Default is to use the value of"_dirt"."_minlight_dirt" "n"โ1enables dirtmapping (ambient occlusion) on minlight,-1disables it. Default is to use the value of"_dirt"."_dirtmode" "n"โ pick your fighter: ordered (0, which is the default) or randomized (1) dirtmapping."_dirtdepth" "n"โ maximum depth of occlusion checking for dirtmapping, default128."_dirtscale" "n"โ the scale factor used in dirt calculations, default1. Lower values (e.g.0.5) make the dirt fainter, while2.0would create much darker shadows. ๐"_dirtgain" "n"โ exponent used in the dirt calculation, default1. Lower values (e.g.0.5) make the shadows darker and stretch further away from corners."_dirtangle" "n"โ cone angle in degrees for occlusion testing, default88. Allowed range is1-90. Lower values can avoid unwanted dirt on arches, pipe interiors, etc."_gamma" "n"โ adjusts the brightness of the final lightmap. Default1,>1is brighter,<1is darker."_lightmap_scale" "n"โ forces all surfaces+submodels to use this specific lightmap scale. Also removes the"LMSHIFT"field."_bounce" "n"โ non-zero enables bounce lighting, which is disabled by default. The value is the maximum number of bounces to perform. ๐"_bouncescale" "n"โ scales the brightness of bounce lighting, default1."_bouncecolorscale" "n"โ the weight for bounce lighting to use texture colors from the map:0=ignore map textures (default),1=multiply bounce light color by texture color."_bouncelightsubdivision" "n"โ no description in the source for this one, so I'm leaving it exactly as mysterious as I found it. ๐"_surflightscale" "n"โ scales the surface light emission from Q2 surface lights (sky faces don't count) by this amount."_surflight_atten" "n"โ Float, default1.0.
๐ง Todo ๐ง
Document this. ๐
"_surflightskyscale" "n"โ scales the surface light emission from Q2 sky faces by this amount."_surflightsubdivision" "n"โ no description given in the source. ๐ฆ"_choplight" "n"โ no description given in the source either. ๐"_bouncestyled" "n"โ1lets styled lights bounce too (like flickering or switchable lights). Default is1."_spotlightautofalloff" "n"โ when it's set to1, the spotlight falloff gets calculated from the distance to the targetedinfo_null. It's ignored when"_falloff"is not0. Default0. ๐ฆ"_surflight_radiosity" "n"โ whether to use Q1-style surface subdivision (0) or Q2-style surface radiosity."_sky_surface" "x y z"โ no description in the source, bestie. ๐"_sun_surface" "x y z"โ also no description in the source."_compilerstyle_start" "n"โ no description in the source. โญ"_compilerstyle_max" "n"โ no description in the source either."_surflight_minlight_scale" "n"โ scale factor for the automatic minlight on an emissive face, derived from the light color being emitted. This is intended to prevent, e.g., a light fixture texture that's configured as a surface light from being completely black. Default1.0, and you can set it to0.0to disable minlight entirely.
๐งธ Model Entity Keys ๐งธ
The following keys can be used on any entity that has a brush model. ๐ซถ
If you use them on func_detail* or func_group, a full qbsp pass needs to be run.
"_minlight" "n"โ sets the minimum light level for any surface of the brush model. Default0.
Note: Q2 uses a 0..1 scale for this key.
"_minlight_mottle" "n","_minlightMottle" "n"โ whether minlight should have a mottled pattern. Defaults to0."_minlight_exclude" "texname","_minlight_exclude2" "texname","_minlight_exclude3" "texname"โ faces with the given texture are excluded from receiving minlight on this brush model. ๐ซ"_minlight_color" "r g b","_mincolor" "r g b"โ the red (r), green (g) and blue (b) components for the colour of the minlight. RGB component values go between0and255(between0and1is also accepted). Default is white light:"255 255 255"."_shadow" "n"โ ifnis1, this model will cast shadows on other models and itself (i.e."_shadow"implies"_shadowself"). Heads up though: this doesn't magically give Quake dynamic lighting powers, so the shadows will not move if the model moves. Set it to-1onfunc_detail/func_groupto stop them from casting shadows. Default0. ๐"_shadowself" "n","_selfshadow" "n"โ ifnis1, this model will cast shadows on itself whenever one part of the model blocks the light from another model surface. For moving models this can be a better compromise than full shadowing. Default0."_shadowworldonly" "n"โ ifnis1, this model will cast shadows on the world only (not on other bmodels)."_switchableshadow" "n"โ ifnis1, this model casts a shadow that can be switched on/off using QuakeC. To make that work, a lightstyle is automatically assigned and stored in a key called"switchshadstyle", which the QuakeC will need to read and call the"lightstyle()"builtin with"a"or"m"to switch the shadow on or off. Entities that share the same targetname, and have"_switchableshadow"set to1, will share the same lightstyle.
These models are only able to block style 0 light (i.e., non-flickering or switchable lights). Flickering or switchable lights will shine straight through the switchable shadow casters, regardless of whether the shadow is off or on. ๐
See also: The light entity key _switchableshadow_target allows using switchable shadows in ID1 Quake, without custom QC, although the setup is more awkward. ๐
"_dirt" "n"โ for brush models,-1prevents dirtmapping on the brush model. Super useful if the bmodel touches or sticks into the world and you want to stop those areas from turning black. Default0."_phong" "n"โ1enables phong shading on this model with a default_phong_angleof89(which softens columns etc). โจ"_phong_angle" "n"โ enables phong shading on faces of this model with a custom angle. Adjacent faces with normals this many degrees apart (or less) will be smoothed. Consider setting"_anglescale"to"1"on lights or worldspawn to make the effect of phong shading more visible. Use the-phongdebugcommand-line flag to save the interpolated normals to the lightmap for previewing (use"r_lightmap 1"or"gl_lightmaps 1"in your engine to preview.) ๐"_phong_angle_concave" "n"โ optional key for setting a different angle threshold for concave joints. A pair of faces will either use"_phong_angle"or"_phong_angle_concave"as the smoothing threshold, depending on whether the joint between the faces is concave or not."_phong_angle(_concave)"is the maximum angle (in degrees) between the face normals that will still cause the pair of faces to be smoothed. The minimum setting for"_phong_angle_concave"is1, and this should make all concave joints non-smoothed (unless they're less than1degree apart, i.e. basically a flat plane.) If it's0or unset, the same value as"_phong_angle"is used."_phong_group" "n"โ an integer that hands a face its very own "smoothing group ID" for phong shading ๐ . Default is0, and the way this works is lowkey exclusive: faces with a_phong_groupwill only smooth with other faces that have a matching_phong_group. Girlies in the same group only. Equivalent to the Q2.mapformat's "value" field."_lightignore" "n"โ set this bad boy to1and the model receives minlight only, straight up ignoring all lights / sunlight. Could be useful on rotators / trains. Not the moment for full lighting, and that's valid.
See also:
- Lighting Channels for a more powerful version of this
"_light_twosided" "n"โ set to1to enable receiving light from either side ๐ซถ. The default is0, except on liquids (Q1* <#texture-0>, Q2 contentsLAVA/SLIME/WATER), where it defaults to1. Liquid girlies get double-sided light for free, no cap."_light_alpha" "n"โ a float, range0-1. Lets you customize the opacity of this face when it's acting as "stained glass" โจ. Stained glass core fr.
๐ Todo ๐
Document default, and which conditions cause a face to be "stained glass"
Bestie, that todo is in the original, so it's staying in. Some mysteries remain unsolved. ๐
"_litwater" "n"โ okay so here's the thingโฆ there's literally no description listed for this one in the original, it's just vibing there. Mysterious. Iconic, honestly. ๐"_splitturb" "n"โ overrides the worldspawn/command line optionqbsp -litwater <#cmdoption-qbsp-litwater>for these specific brushes. Per-brush power moves, we love to see it ๐"_surflight_atten" "n"โ overrides the worldspawn key_surflight_attenfor these brushes."_surflight_rescale" "n"โ integer,0or1. If it's1, it rescales any surface light emitted by these brushes to emit 50% light at 90 degrees from the surface normal. Otherwise, you get a more natural angle falloff of 0% at 90 degrees. Default is0on sky faces, otherwise1. Sky stays diff, everything else gets the glow-up ๐"_surflight_color" "r g b"โ customize the emissive color of a surface light ๐จ. Default is to use the average texture color."_surflight_style" "n"โ override the surface light lightstyle number for light emitted from these brushes."_surflight_targetname" "name"โ override the surface light targetname for light emitted from these brushes."_surflight_minlight_scale" "n"โ overrides the worldspawn setting_surflight_minlight_scale"_bounce" "n"โ set to-1to prevent this model from bouncing light (i.e. it prevents its brushes from emitting bounced light they receive from elsewhere). Only has an effect if"_bounce"is enabled in worldspawn. No worldspawn bounce, no per-model bounce, iykyk."_autominlight" "n"โ okay so "Autominlight" is a feature for automatically choosing a suitable minlight color for a bmodel entity (e.g. afunc_door), by averaging incoming light at the center of the bmodel bounding box. Genuinely so smart ๐ง
Default behaviour is to apply autominlight on occluded luxels only โ like, for a door that opens vertically upwards, it would apply to the bottom face of the door, which is initially pressed against the ground.
A value of "-1" disables the feature (occluded luxels will be solid black ๐ญ), and "1" enables it as a minlight color even on non-occluded luxels.
"_autominlight_target" "name"โ for autominlight, instead of using the center of the model bounds as the sample point, this searches for an entity with its"targetname"key set to"name", and uses that entity's origin (typically you'd use an"info_null"for this). So the sample point gets to be somewhere else entirely, main character behavior for real ๐ฏ"_world_units_per_luxel" "n"โ when-world_units_per_luxelis in use, this customizes the lightmap scale on this entity."_surflight_group" "n"โ integer. Default0.
Can be set to a nonzero value to make these brushes emit as surface lights only from a light template with a matching _surflight_group value. Matchy-matchy on purpose ๐
"_lightcolorscale" "n"โ saturation control as a postprocessing step on these specific faces' lightmaps. Default1.0, and0.0is fully desaturated to greyscale. Faded filter moment ๐ธ
โจ LIGHT ENTITY KEYS โจ
Okay bestie, gather round, because these keys are the moment ๐ก Any entity whose classname starts with the first five letters "light" can use them โ so like "light", "light_globe", "light_flame_small_yellow", all of them. Same five letters. That's the whole vibe check. ๐
๐ธ Point Lights ๐ธ
"light" "[r g b] [n]"โ the classic. Usually you just give it one value,n, which is how bright the light is. Negative values are totally allowed and they make the entity subtract light that other entities cast. Default is300.
For Half-Life compatibility, you can also stick a color in here before the light value, formatted exactly like _color would be.
Heads up: if a color is set in both places, _color wins. It takes priority, no cap. ๐
"wait" "n"โ scales how fast the light fades with distance byn. Values ofn> 1 mean the light fades quicker as you get further away, and values < 1 mean it fades slower (so it reaches further out). Default1."delay" "n"โ picks an attenuation formula for the light. Choose your fighter:
0 => Linear attenuation (default)
1 => 1/x attenuation
2 => 1/(x^2) attenuation
3 => No attenuation (same brightness at any distance)
4 => "local minlight" - No attenuation and like minlight,
it won't raise the lighting above it's light value.
Unlike minlight, it will only affect surfaces within
line of sight of the entity.
5 => 1/(x^2) attenuation, but slightly more attenuated and
without the extra bright effect that "delay 2" has
near the source.
"_falloff" "n"โ sets the distance (in map units) where the light drops to0.
In this mode "wait" is ignored, and "light" only controls the brightness at the center of the light โ it no longer affects the falloff distance at all.
Currently only supported on linear attenuation (delay 0) lights. Don't @ me. ๐
"_color" "r g b"โ sets the red (r), green (g) and blue (b) of your light's color. RGB component values go between0and255(and between0and1is also accepted, cute of them). Default is white light:"255 255 255"."targetname" "name"โ turns the light into a switchable light, toggled by another entity that targets its name. ๐"style" "n"โ set the animated light style. Default0."_anglescale" "n""_anglesense" "n"โ sets a scaling factor for how much the angle of incidence of light on a surface affects that surface's brightness.nhas to be between0.0and1.0. Smaller values mean less attenuation, and zero means angle of incidence has no effect on brightness whatsoever. Default0.5."_dirtscale" "n""_dirtgain" "n"โ override the global"_dirtscale"or"_dirtgain"settings so you can change how this light gets affected by dirtmapping (that's ambient occlusion, bestie). See the descriptions of these keys in the worldspawn section."_dirt" "n"โ overrides the worldspawn"_dirt"setting for this specific light.-1disables dirtmapping (ambient occlusion) for this light, which makes it illuminate the dirtmapping shadows.1enables ambient occlusion for this light. Default is to just defer to whatever the worldspawn says."_deviance" "n"โ splits the light into a whole sphere of randomly positioned lights within radiusn(in world units). Lowkey useful for giving shadows a wider penumbra."_samples"decides how many lights are in that sphere. The"light"value gets automatically scaled down for most lighting formulas (except linear and non-additive minlight) to try to keep the brightness equal. Default is0, aka don't split up lights."_samples" "n"โ how many lights to use for"_deviance". Default16(and it's only used if"_deviance"is actually set)."_bouncescale" "n"โ scales how much light comes from bounces. Default is1.0, and0.0disables bounce lighting for this light entirely."_nostaticlight" "n"โ set to1and the light compiler will justโฆ ignore this entity (so it casts zero light). Could be handy with rtlights, iykyk."_switchableshadow_target" "name"โ calculates lighting with and without bmodels that have a"targetname"equal to"name", and stores the resulting switchable shadow data in a light style, which gets stored in this light entity's"style"key.
You should give this light a targetname and typically set "spawnflags" "1" (start off).
Implies _nostaticlight โ meaning this entity itself does not cast any light.
Hint:
- If your mod supports it, you should prefer using the bmodel key
_switchableshadowto enable switchable shadows. โจ
๐ฆ Spotlights ๐ฆ
These support every key from Point Lights, plus the following:
"target" "name"โ turns the light into a spotlight, where the direction of light points toward another entity whose"targetname"key is set to"name"."mangle" "yaw pitch roll"โ turns the light into a spotlight and specifies the direction with yaw, pitch and roll in degrees. Yaw is the angle around the Z-axis from0to359degrees, and pitch is the angle from90(straight up) to-90(straight down). Roll does nothing, so just use any value (like0). Often way easier than the"target"method. ๐"angle" "n"โ the angle in degrees for a spotlight cone. Default40."_softangle" "n"โ the angle in degrees for an inner spotlight cone (and it must be less than the"angle"cone). Creates a softer transition between the full brightness of the inner cone and the edge of the outer cone. Default0(disabled).
๐ Surface Lights ๐
"_surface" "texturename"โ makes surfaces with that texture name emit light, by using this light as a template that gets copied across all those surfaces. Lights are spaced about128units apart (though possibly closer because of bsp splitting) and positioned2units above the surfaces.
To restrict this surface light config to just a subset of brushes with the "texturename" texture applied, check out the _surflight_group key.
"_surface_offset" "n"โ controls the offset that lights get placed above surfaces for_surface. Default2."_surface_spotlight" "n"โ for a surface light template (aka a light with_surfaceset), setting this to"1"makes each instance a spotlight, with the direction of light pointing along the surface normal. In other words, it automatically sets"mangle"on every generated light. Obsessed."_surface_radiosity" "n"โ whether to use Q1-style surface subdivision (0) or Q2-style surface radiosity (1) on this light specifically.
Use it in conjunction with _surface.
The default can be changed for all surface lights in a map with the worldspawn key _surflight_radiosity.
"_surflight_group" "n"โ integer, default0.
For use with _surface lights.
Can be set to a nonzero value to restrict this surface light template to only emit from brushes with a matching _surflight_group value.
๐จ Projected Texture Lights ๐จ
"_project_texture" "texture"โ says this light should project that texture. The texture has to be used somewhere in the map, bestie.
Todo
- This is a qbsp limitation which could be fixed
"_project_mangle" "yaw pitch roll"โ specifies the yaw/pitch/roll angles for a texture projection (this overridesmangle)."_project_fov" "n"โ specifies the fov angle for a texture projection. Default90.
โ๏ธ Sun Light โ๏ธ
Also called a directional light. It's emitted from sky faces.
"_sun" "n"โ set to1to make this entity a sun, as an alternative to using the sunlight worldspawn keys."target" "t"โ if the light targets aninfo_nullentity, the direction toward that entity sets the sun direction. The light itself is disabled, so you can place it literally anywhere in the map."mangle" "yaw pitch roll"โ alternate way of specifying sunlight direction.
Equivalent to worldspawn key _sunlight_mangle.
"light" "n"โ equivalent to worldspawn key_sunlight."_color" "r g b"โ equivalent to worldspawn key_sunlight_color."deviance" "n"โ equivalent to worldspawn key_sunlight_penumbra."_dirt" "n"โ equivalent to worldspawn key_sunlight_dirt."_anglescale" "n"โ equivalent to worldspawn key_anglescale."style" "n"โ flicker style for styled sunlight."targetname" "name"โ targetname for switchable sunlight."_suntexture" "texname"โ this sunlight is only emitted from faces with this texture name. Default is to be emitted from all sky textures.
๐ฆ Sky Light ๐ฆ
Hemisphere shaped light, emitted from sky faces.
"_sunlight2" "n"โ set to1to make this entity control the upper dome lighting emitted from sky faces, as an alternative to the worldspawn key_sunlight2. The light entity itself is disabled, so it can be placed anywhere in the map."_sunlight3" "n"โ same as_sunlight2, but makes this sky light come from the lower hemisphere."light" "n"โ sets the dome light brightness. Equivalent to worldspawn key_sunlight2."_color" "r g b"โ sets the dome light color. Equivalent to worldspawn key_sunlight2_color."_dirt" "n"โ equivalent to worldspawn key_sunlight2_dirt."_anglescale" "n"โ equivalent to worldspawn key_anglescale."style" "n"โ flicker style for styled sky light."targetname" "name"โ targetname for switchable skylight."_suntexture" "texname"โ this sky light is only emitted from faces with this texture name. Default is to be emitted from all sky textures.
๐ก LIGHTING CHANNELS ๐ก
okay bestie this is the good stuff, lighting channels are literally how you build custom lighting setups where a specific light entity only touches a specific bmodel and nothing else โจ super handy for lighting rotators, doors, that kind of thing ๐
Note: rn, bounced light, surface lights, and sunlight are always on channel 1. no negotiating, that's just how it is ๐
๐ Light Keys ๐
"_light_channel_mask" "n"โ this is the mask of lighting channels that the light actually casts on. ๐
so for this light to cast anything onto a bmodel, there's gotta be at least 1 bit in common between _light_channel_mask and the receiving bmodel's _object_channel_mask โ like, the bitwise AND needs to be nonzero, no cap. ๐ค
Default is 1.
Note: lightgrids only ever receive light channel mask 1. that's it, that's the whole rule ๐ญ
"_shadow_channel_mask" "n"โ this one is the mask of lighting channels that will block this entity's light rays. if the bitwise AND of this and another bmodel's_object_channel_maskis nonzero, then boom, the light ray is stopped. ๐
this is an advanced option, for making bmodels only cast shadows for specific lights (and not the others). very main character energy, very selective ๐
Defaults to whatever _light_channel_mask is.
๐ธ Model Keys ๐ธ
"_object_channel_mask" "n"โ the mask of lighting channels that this bmodel receives light on, blocks light on, and tests for AO on. it does all three, she's versatile ๐
Default is 1.
Note: changing this from 1 will disable bouncing light off of this bmodel. ๐
Note: changing this from1implicitly enables_shadow.
Note: changing it to2, for example, will cause the bmodel to initially be solid black. ๐ญ you'll need to addminlight, or lights with_light_channel_mask 2, to actually see anything.
๐ OTHER INFORMATION ๐
the \b escape sequence toggles red text on/off, and you can use it in any strings in the map file. obsessed. it's giving vintage. โจ
for example:
"message" "Here is \bsome red text\b..."
๐ AUTHOR ๐
- Eric Wasylishen
- Kevin Shanahan (aka Tyrann) โ
http://disenchant.net - David Walton (aka spike)
- Based on source provided by id Software
๐ซถ REPORTING BUGS ๐ซถ
pls pls pls post bug reports at https://github.com/ericwa/ericw-tools/issues โ we're literally begging ๐
improvements to the documentation are welcome and encouraged, fr fr ๐
๐ COPYRIGHT ๐
- Copyright (C) 2017 Eric Wasylishen
- Copyright (C) 2013 Kevin Shanahan
- Copyright (C) 1997 id Software
License GPLv2+: GNU GPL version 2 or later โ http://gnu.org/licenses/gpl2.html.
this is free software: you are free to change and redistribute it. there is NO WARRANTY, to the extent permitted by law. โ ๏ธ
aaaand that's the whole page bestie, you made it to the end, iconic behavior truly ๐โจ this is EWTOOLS-LIGHT(1), dated Jul 29, 2026 โ go forth and light things up, no cap ๐
๐๐ฆ
๐ฆ where this page comes from
- ubuntu stonking: ericw-tools 2.0.0~alpha11+ds-1 ยท GPL-2.0-or-later
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms