Counter-Strike 2 Workshop Tools/Level Design/Lighting

==Overview==
When rendering objects in 3D, the engine behind Counter-Strike 2 uses a simulation of how light appears in real life - allowing surfaces to respond realistically to light sources, ambient lighting and suchlike, with both static and dynamic objects casting shadows from those light sources. To ensure both high visual fidelity and high performance, the Workshop Tools need to precalculate a lot of information - storing lighting data in various forms such as lightmap textures, light probe volumes and cubemaps.
But what are all these things, anyway?
Inputs into the lighting system can be broken down into the following: 
* Lightmap textures on static geometry (Hammer meshes, static props)
* Light probe volumes and cubemaps (ambient lighting on dynamic objects, reflections)
* Light sources (environment, point, ortho and spot lights)
To get a preview of how things will look in Hammer, you can use the 'Preview Baked Lighting' menu at the top. This will do a lower-quality preview of how the final lighting will look in CS2 - hugely helping with artistic direction, gameplay design and similar. It uses vertex lighting and many per-pixel dynamic light sources instead of lightmaps - requiring much less precalculation, but resulting in lower quality. To view this in editor, go to the "All Lighting" (F6 by default) view in the viewport
Another preview option is the new GPU Path Tracing preview (Ctrl+Alt+F6 by default), this utilizes the RT cores inside of a users GPU to compute lighting in real time and is a BEST CASE scenario of how your maps lighting may currently look. Due to the expensive nature of Path Tracing, this view is not usable for in-game purposes but the compiler will utilize the RT cores in your GPU to compute the lighting more accurately than older CPU based compiles did. This mode also correctly accounts for "Bounce" lighting, which we will go over further down in this article. 
For simple test compiles, you can usually get away with Resolution 2048, Quality Standard lighting. Utilizing your GPU, these compiles are much quicker than previous CPU based compiles and will allow for fast iteration and testing. Quality Final will give you a much cleaner and more precise lighting on the lightmap at the cost of taking a longer time and Resolution 4096 and 8192 will give you more lightmap space, the engine will optimize the space used so even if it looks like the lightmap space fits fine at 2048 or 4096, the compiler will improve the individual lightmap islands to fit the newly given space in a 8192 compile resulting in fuller and more accurate looking lighting.
We will go over ways to optimize Lightmap space and solve possibly issues you may encounter further down in the Lighting Optimizations section
You can find more information on Compile settings in the Compiles and Post-Compile Cleanup Page
== Hammer Minimum Specs ==
Hammer now leverages GPU accelerated raytracing to both preview and bake lighting for maps, drastically speeding up compile times, even on lower end hardware. As such, a GPU capable of raytracing is now required for Hammer to be fully functional. 
GPU Minimum Specs:
* GeForce RTX 2060 (or Quadro/Titan equivalent)
** 
* AMD Radeon 6600 XT (or other RDNA 2 cards)
* Intel Arc series (tested on Battlemage)
GPU Recommended Specs:
* GeForce RTX 2080 Ti+ (or Quadro/Titan equivalent)
* AMD Radeon 6800 XT+ (or other RDNA 2 cards)
* Intel Arc series (tested on Battlemage only as of Jan 5th, 2025.)
=== Hammer - Known issues ===
== Light source types ==
Light sources come in several different types, with different behaviors in how light dissipates. You can place light sources into your map with the Entity Tool in Hammer from the left-hand toolbar - conveniently, it has a stylized light bulb as an icon.
These entities have a collection of features they share such as being able to; rotate, set color, adjust brightness (Brightness, except on light_environment, is now adjusted under Lumens/Candela/Nits/Legacy depending on what Unit you choose), set maximum distance, and adjust the shape; all of which can be adjusted in the Object Properties window.
Examples of All lighting types can be found in csgo_addons/addon_template/maps/content_examples/lighting_info.vmap
* Environment Light - light_environment
** Virtual sunlight from sky - light source infinitely far away
** No falloff over distance
** Usually just one of these in a map
** light_environment controls both the angle and intensity of the sunlight and the color/IBL/intensity of the skylight.
** The skylight IBL material is selected via a named env_sky entity.
* Ortho Light - light_ortho
** Need to select 'light_ortho' in entity class popup menu to place this
** Cross between an environment light and a spot light
** Light is parallel, but only exists within a particular cuboid
** As with environment light, no falloff over distance
** Great for limited skylights and other special uses etc.
* Omni Light - light_omni2
** Single all-directional light source
** Bit like a light bulb!
**This replaces the legacy light_omni, and is a much more flexible, capable omni-directional light type. 
**You can set a size, hemispherical falloff, cookie and toggle between point, shere or tube light shapes.
**Omni2 supports both Stationary and Dynamic light types, with dynamic shadows requiring space for 4 additional shadow map slots in the global shadow map atlas, otherwise, shadows from these lights will not render.
**Note: Cascade shadow maps from light_environment take up the majority of the shadow map atlas, however, more space will be freed when the sun is occluded in indoor areas.
**Omni2 when set to Point and Sphere will look identical in-editor but will not after baking lighting/compiling.
* Barn Door Light - light_barn
**This is the most versatile light type: It can be manipulated to be many different shapes and sizes and supports light cookies. 
**It can also cast dynamic shadows when direct lighting is set to "Dynamic" or "Stationary", and shadows are set to "Yes".
**Dynamic barn lights cast dynamic, per-pixel direct light, direct specular, shadows and can be manipulated, scripted/etc. 
**Note: A max of 380 un-shadowed dynamic lights can be in a map, with shadowed lights being limited by available space in the global shadow map atlas.
**Stationary lights are static lights that cast per-pixel direct light + direct specular, along with a mix of static and dynamic shadows (for dynamic/physics objects) 
**Stationary lights can have their direct lighting manipulated at runtime, but indirect bounce light is static. 
**Note: There is a limit of 4 overlapping stationary lights. The overlap count is determined by the light cone/radius+range of the light, so be careful when setting large ranges or cone sizes
* Rectangular Light - light_rect
** This is useful for simulating area lights. These are only supported as a static light, and will not render correctly if set to Dynamic or Stationary.
** Note: An accurate representation of this light type can only be seen in the raytraced lighting preview
* Emissive Materials - Emissive Lighting
**Emissive materials are now supported for any shader that has the option for self-illumination. 
**Emissive materials can be boosted on a per mesh/prop basis using the Emissive Lighting Boost multiplier. Emissive materials also can take into account per object tinting.
== Direct and Indirect Lighting ==
Light sources are effectively made of two components:
* Direct lighting - primary component based on line of sight to light source
* Indirect lighting - secondary component from light bouncing from one surface to another - can be fairly subtle but adds enormously to visual realism
How direct lighting gets rendered is the main choice here.
=== Stationary Direct Lighting ===
* Selected with 'Direct Lighting' set to 'Stationary'
* By default, indirect lighting gets baked into lightmaps (for static surfaces) and light probe volumes (for dynamic objects)
* Advantages: 
** Direct lighting has specular (shiny) component
** Can cast shadows from dynamic objects (characters, physics props etc.)
** Realistic contact hardening on shadows from static geometry (using Light Source Radius / SunSpreadAngle)
** Direct lighting can flicker, strobe, turn on and off (give the light entity a targetname, set 'Create Client-Only Entity' to 'No' and tell it what to do via entity I/O)
** Relatively cheap to render!
* Disadvantages:
** Can have a maximum of four stationary lights shining on one surface at a time or the overlapping lights will have no shadows (best to keep it to one or two to make things cheaper to render)
*** Preview with menu at top right of 3D view in Hammer - set 'Tools Visualization Mode' to 'Lighting Complexity'
*** Gray is zero indexed lights on that surface, blue one, aquamarine two, green three, yellow four and orange is DON'T DO THAT
** Light source cannot move
** Shadows of dynamic objects will only appear if there is space in the shadow atlas for the light
** Indirect component can't be switched on or off - set it to 'None' if you want a fully switchable light
** There's a limit on the total number of indexed lights in a map, although it's pretty high and you're unlikely to reach it in normal usage
=== Static Direct Lighting ===
* Selected with 'Direct Lighting' set to 'Static'
* Advantages:
** Basically free to render!
*** Direct component gets stored in lightmaps and light probe volumes, the same as with the indirect component
** Realistic contact hardening on shadows from static geometry (using Light Source Radius / SunSpreadAngle)
* Disadvantages:
** Direct lighting has no specular component
*** Lit surfaces can look dry and crusty
*** Don't get directionality from directional lightmaps
** Can't cast shadows from dynamic objects
** Light source cannot move
** Cannot switch light on or off, cannot flicker or strobe
=== Per-Pixel Direct Lighting ===
* Selected with 'Direct Light' set to 'Per Pixel'
* Can be very expensive; usually only used for special occasions (e.g. player flashlight) or for very small light sources (glows on ammo clips, resin etc.)
* Only use these if you know what you're letting yourself in for, pretty much
** Look for examples in shipped maps for further details
* Advantages:
** Can have high-quality specular component (although specular would be switched off for small light sources as listed above)
** Can have fully dynamic shadows (again, would be switched off for those small light sources)
** Can move light source, as with player flashlight!
** Direct lighting can flicker, strobe, turn on and off
* Disadvantages:
** Can be expensive!
** No contact hardening (Light Source Radius / SunSpreadAngle do nothing)
** Indirect component is still baked into lightmaps etc. if enabled (switch to 'None' for most purposes)
** Outside of preview lighting, we only support
*** A single light_spot or light_ortho with shadows enabled in view
*** Up to 8 light_omnis with shadows and specular disabled, and fully linear falloff
=== Indirect lighting ===
For proper indirect lighting on dynamic objects, you want to place Light Probe Volume and Cubemap entities - env_combined_light_probe_volume
* You want the center of each to be a typical, average view in that particular volume, be it a room, corridor, outdoors scene etc.
** For a simple cuboid room, you'd place it right at the centre, about eye height
* Extend the volume bounds (red, green and blue 3D arrows) to fully enclose that volume
** Reflections are done with box-projected cubemaps - imagine a box with a texture on each face
** In that simple cuboid room, you'd want the volume bounds to meet the walls, floor and ceiling
** Reflections would thus be of a simplified version of that very room, with correct apparent depth and everything
* Volumes can be rotated and can overlap - can set the priority to make one override another (e.g. a dark player-accessible box surrounded by sunlit outdoors)
* Hammer geometry should be broken into separate meshes as necessary
** Each mesh can only receive reflections from one cubemap
** Don't worry about effectively adding extra geometry, vertices etc. in the process - all kinds of fancy mesh dissection stuff goes on behind the scenes with visibility and similar anyway.
* All accessible areas should be enclosed by light probe volumes - if you have dynamic objects suddenly flashing really bright or whatever, you may have missed a bit
* CS2 now allows for setting an edge fade distance between LPVs to allow for smoother visual transitions between LPVs.
** You can see a visual indication of this inside of Hammer by clicking on the LPV and looking for the faint light blue line that is moved from the edge of the LPV based on the values entered into the Edge Fade Dist field.
== Lightmap Density ==
Lightmap density describes how dense the lightmap texture is on a particular face. This is necessary to control because giving all faces a uniform density would be inefficient to calculate.
You can preview lightmap density in-game with the command mat_luxels 1.
=== Lightmap Player Spaces ===
Lightmaps are textures containing precalculated lighting information for static surfaces. You want these to be as high resolution as possible for the best visual fidelity. You can ensure the compilation process automatically prioritizes player-accessible stuff by placing lightmap player space volumes - quite simply, these are Hammer meshes with materials/tools/toolslightmapres.vmat on them. The closer a surface is to one of these meshes, the more lightmap texels are assigned to it.
The general gist of it is - place these lightmap player space volumes within areas the player can get to. Inaccessible areas - things behind fences, high up on walls, distant buildings - will thus be assigned fewer and fewer lightmap texels depending on how far away they are.
The net result is apparently seamless lightmap detail!
=== Lightmap Resolution Bias ===
When editing a face, you can control the Lightmap Resolution Bias. This is a value that will influence how large the lightmap texture space is for that face relative to the rest of the map.
Bias scales by powers of 2. A lightmap bias of +1 will make the texture resolution 2x what it would be normally, +2 is 4x resolution, etc. Negative bias will lower the lightmap resolution.
Be wary of adjusting this option by accident, as a single face with a very large lightmap bias can effectively destroy the lightmap density for the rest of your map! If you have bad shadows and your console is reporting 'Mesh with material <x> is extremely large in lightmap (x.x%)' with a large value, this may be why. You can go to the coordinates listed in console to get an idea of where these faces may be, and use mat_luxels 1 in game to find suspiciously dense faces.
=== Lightmap Optimization Methods ===
Optimizing your lightmap space can be a tricky subject and involves a bit of work to ensure good looking results while also not creating other problems with visuals.
* As mentioned before, changing the Lightmap bias on a given face can improve texture resolution, but it can also decrease it by setting the value to a negative number. For areas that you believe don't need as heavy of a bias, you can decrease the bias amount to allow for other textures to shine. This same feature also works on Props such as foliage, where it is recommended that you set the lightmap bias as low as possible due to the many faces foliage models can have.
*Minor props on a map, that can get away with it, can also have their baked lighting disabled outright and instead opt to use the Light Probe Volume instead. This can allow you to achieve the same effect while not affecting lightmap space. This is done by simply turning the Baked Lighting option to "No"
*Lightmap Space was mentioned previously as a helpful way to guide the lightmap generator to understanding where your maps highlights might be. While you might not need to be super precise on the accuracy of the mesh, it is recommended that it is fairly accurate to your maps in-bounds areas to best help the lightmap generator in its goal of creating you a good looking lightmap. The more accurate this mesh is to your given playable space, the better optimized the generated lightmap should look towards your in bounds zones VS areas of the map that won't be up to as heavy scrutiny.
== Basic summary of lighting: ==
* Use indexed lights for the key lights in your scene - sunlight, major light sources etc. that you want specular from, switchable / flickering lights etc.
** The 'Baked Lighting Complexity' visualization mode will show you how things are looking in terms of rendering cost
** Ideally, you want things black, red and a bit of orange and yellow
* Use fully baked lights for visually less important things - fill lights, things in background, dimmer light sources
* Use per-pixel lights only for very particular reasons - if in doubt, don't.
* Use Emissive Materials when you want a given material to "shine" and act as if it was lit. Be careful adjusting boost values too far as it can lead to some poor lighting.
===Helpful Tips===
Some of the employees at Valve have been kind enough to answer various questions asked about their process when creating the new remake maps such as Inferno and Italy. So the below will be some helpful information learned from them.
*Emphasized the sun's lighting to highlight the difference between the places in shade and areas that were exposed to the sun.
**Most instances of surface hit by sun have a light_rect added to triple boost fake light bounces and get something similar to "ambient" lighting and ensure a nice gradient
*Indoor Lighting relies heavily on light_rect to fake light bounces, seen at the bottom of most passageways which use a number of them to improve the bounces.
*If the environment is super busy, like on Inferno, it's best to keep the lighting simplistic as well. Frequencies stack, and piling busy lighting on top of busy environments can overload players and make it hard to understand where they need to be looking.
**Try to guide the players eyes as best as possible to make sure that they're looking at areas they need to be.
***Helpful publication on guiding the players eyes Link
*Notes that the legacy light entities work but do not always react the same way as the newer light entities with the cubemaps.
== Volumetric Fog ==
Counter-Strike 2 does not use the volumetric fog system utilized by Half-Life: Alyx and other Source 2 games. It is currently not functioning after the Limited Test, and still isn't after release, and Valve have stated that there is no intention right now to add it back.
== Building Lighting ==
=== Preview Baked Lighting ===
For an in-Hammer preview of how your map will look when fully compiled, make use of the Preview Baked Lighting : Bake All Lighting menu. 
This will perform some lower-quality calculations which will help you iterate on the overall look and visual feel of your map - it'll let you continue working on the map beyond this point, but remember to re-bake preview lighting whenever you make any significant changes so that you'll get an up-to-date representation of how everything will look.
=== GPU Path Traced Preview ===
For an in-Hammer preview of how your map might look with bounce, direct, indirect, specular, etc lighting; we can make use of the GPU Path Traced Preview. This mode requires no prior compilations or calculations and is done entirely in realtime on the GPU and can help show you a "best case" look and visual feel of your map. Lighting changes done while in this mode can be seen in realtime allowing for extremely fast lighting tests without the need for lengthy compiles. 
=== Building Lightmaps ===
Once you're happy with how your map will look, you can now compile the thing. Press F9 to bring up the Map Builder dialogue box. The default settings for Full Compile will generate 1k lightmaps - this should be relatively fast for a simple map, just taking a few minutes. To build cubemaps for proper reflections on metallic surfaces, remember to check the Build cubemaps on load checkbox.
As stated before, the resolution will determine the amount of total space your lightmap materials have to fill while the Quality will determine the accuracy of the lightmap itself.
==== Release Builds ====
For a release version of your map, it is recommended to run at Resolution 8192 which will generate an 8k lightmaps - This compile will take a while as 8k is a massive resolution to compute through. Thankfully, GPU compiles help make these day+ long times go down to more reasonable hours in most situations. On top of Resolution being set to 8192, it is also recommended to have Quality at Final for a release candidate version of your map.
Together, both of these settings will produce the best looking version of your map that you've given it.