EWTOOLS-LIGHT(1)

๐Ÿ“ฆ version 2.0.0~alpha11, in ubuntu stonking

โœจ 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. ๐Ÿ’…
  • -filepriority archive | 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 ๐Ÿซถ
  • -threads n โ€” set the number of threads explicitly. by default, light tries 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.
  • -gate n โ€” 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_penumbra and _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 โœจ
  • -emissivequality low | 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 use surflight_subdivide to control the point spacing and get better anti-aliasing. default is low.

๐Ÿงš Output format options

  • -lit โ€” force generation of a .lit file, even if your map has zero coloured lights. by default light will just automatically generate the .lit when it's needed.
  • -world_units_per_luxel n โ€” enables output of DECOUPLED_LM BSPX 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 .lit file that is compatible with the .bsp without 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). ๐Ÿ™ˆ
  • -facestyles n โ€” max amount of styles per face; requires the BSPX lump if it's > 4.
  • -exportobj โ€” export an .OBJ for inspection.
  • -lmshift n โ€” 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 the LMSHIFT lump 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 -soft is 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. -extra implies a value of 2, and -extra4 implies 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.
  • -visapprox auto | 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 .obj with 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.
  • -debugface x y z
  • -debugvert x 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 .lit2 file, even if your map has no coloured lights.
  • -lux โ€” generate a .lux file storing average incoming light directions for surfaces. usable by FTEQW with "r_deluxemapping 1".
  • -bspxlux โ€” writes lux data into the bsp itself.
  • -lmscale n โ€” 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 .lit file 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 -lit will 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_dist x y z โ€” distance between lightgrid sample points, in world units. controls lightgrid size.
  • -lightgrid_format octree โ€” 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. So n > 0.5 makes lights brighter, and n < 0.5 makes 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 is 0. โ˜€๏ธ
  • "_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, 0 to 359 degrees. Pitch is the angle from 90 (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-4 for a gentle soft edge, or 10-20+ for more diffuse sunlight. Default is 0. ๐ŸŒธ
  • "_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 between 0 and 255 (between 0 and 1 is 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. Default 0. ๐ŸŒˆ
  • "_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. Default 0. โ˜๏ธ
  • "_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" โ€” 1 enables 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" โ€” 1 enables dirtmapping (ambient occlusion) on sunlight, -1 disables it (which makes it illuminate the dirtmapping shadows instead). Default is to use whatever value "_dirt" has.
  • "_sunlight2_dirt" "n" โ€” 1 enables dirtmapping (ambient occlusion) on sunlight2/3, -1 disables it. Default is to use the value of "_dirt".
  • "_minlight_dirt" "n" โ€” 1 enables dirtmapping (ambient occlusion) on minlight, -1 disables 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, default 128.
  • "_dirtscale" "n" โ€” the scale factor used in dirt calculations, default 1. Lower values (e.g. 0.5) make the dirt fainter, while 2.0 would create much darker shadows. ๐Ÿ˜ˆ
  • "_dirtgain" "n" โ€” exponent used in the dirt calculation, default 1. 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, default 88. Allowed range is 1-90. Lower values can avoid unwanted dirt on arches, pipe interiors, etc.
  • "_gamma" "n" โ€” adjusts the brightness of the final lightmap. Default 1, >1 is brighter, <1 is 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, default 1.
  • "_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, default 1.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" โ€” 1 lets styled lights bounce too (like flickering or switchable lights). Default is 1.
  • "_spotlightautofalloff" "n" โ€” when it's set to 1, the spotlight falloff gets calculated from the distance to the targeted info_null. It's ignored when "_falloff" is not 0. Default 0. ๐Ÿ”ฆ
  • "_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. Default 1.0, and you can set it to 0.0 to 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. Default 0.
Note: Q2 uses a 0..1 scale for this key.
  • "_minlight_mottle" "n", "_minlightMottle" "n" โ€” whether minlight should have a mottled pattern. Defaults to 0.
  • "_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 between 0 and 255 (between 0 and 1 is also accepted). Default is white light: "255 255 255".
  • "_shadow" "n" โ€” if n is 1, 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 -1 on func_detail/func_group to stop them from casting shadows. Default 0. ๐ŸŒ‘
  • "_shadowself" "n", "_selfshadow" "n" โ€” if n is 1, 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. Default 0.
  • "_shadowworldonly" "n" โ€” if n is 1, this model will cast shadows on the world only (not on other bmodels).
  • "_switchableshadow" "n" โ€” if n is 1, 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 to 1, 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, -1 prevents 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. Default 0.
  • "_phong" "n" โ€” 1 enables phong shading on this model with a default _phong_angle of 89 (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 -phongdebug command-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" is 1, and this should make all concave joints non-smoothed (unless they're less than 1 degree apart, i.e. basically a flat plane.) If it's 0 or 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 is 0, and the way this works is lowkey exclusive: faces with a _phong_group will only smooth with other faces that have a matching _phong_group. Girlies in the same group only. Equivalent to the Q2 .map format's "value" field.
  • "_lightignore" "n" โ€” set this bad boy to 1 and 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 to 1 to enable receiving light from either side ๐Ÿซถ. The default is 0, except on liquids (Q1 * <#texture-0>, Q2 contents LAVA/SLIME/WATER), where it defaults to 1. Liquid girlies get double-sided light for free, no cap.
  • "_light_alpha" "n" โ€” a float, range 0-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 option qbsp -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_atten for these brushes.
  • "_surflight_rescale" "n" โ€” integer, 0 or 1. If it's 1, 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 is 0 on sky faces, otherwise 1. 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 -1 to 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. a func_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_luxel is in use, this customizes the lightmap scale on this entity.
  • "_surflight_group" "n" โ€” integer. Default 0.

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. Default 1.0, and 0.0 is 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 is 300.

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 by n. Values of n > 1 mean the light fades quicker as you get further away, and values < 1 mean it fades slower (so it reaches further out). Default 1.
  • "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 to 0.

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 between 0 and 255 (and between 0 and 1 is 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. Default 0.
  • "_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. n has to be between 0.0 and 1.0. Smaller values mean less attenuation, and zero means angle of incidence has no effect on brightness whatsoever. Default 0.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. -1 disables dirtmapping (ambient occlusion) for this light, which makes it illuminate the dirtmapping shadows. 1 enables 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 radius n (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 is 0, aka don't split up lights.
  • "_samples" "n" โ€” how many lights to use for "_deviance". Default 16 (and it's only used if "_deviance" is actually set).
  • "_bouncescale" "n" โ€” scales how much light comes from bounces. Default is 1.0, and 0.0 disables bounce lighting for this light entirely.
  • "_nostaticlight" "n" โ€” set to 1 and 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 _switchableshadow to 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 from 0 to 359 degrees, and pitch is the angle from 90 (straight up) to -90 (straight down). Roll does nothing, so just use any value (like 0). Often way easier than the "target" method. ๐Ÿ’…
  • "angle" "n" โ€” the angle in degrees for a spotlight cone. Default 40.
  • "_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. Default 0 (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 about 128 units apart (though possibly closer because of bsp splitting) and positioned 2 units 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. Default 2.
  • "_surface_spotlight" "n" โ€” for a surface light template (aka a light with _surface set), 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, default 0.

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 overrides mangle).
  • "_project_fov" "n" โ€” specifies the fov angle for a texture projection. Default 90.

โ˜€๏ธ Sun Light โ˜€๏ธ

Also called a directional light. It's emitted from sky faces.

  • "_sun" "n" โ€” set to 1 to make this entity a sun, as an alternative to using the sunlight worldspawn keys.
  • "target" "t" โ€” if the light targets an info_null entity, 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 to 1 to 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_mask is 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 from 1 implicitly enables _shadow.
Note: changing it to 2, for example, will cause the bmodel to initially be solid black. ๐Ÿ˜ญ you'll need to add minlight, 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 (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