mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-19 02:39:19 +02:00
Light the scene with lamps of models, vehicle compartments and the cab lamp in the GL 4.6 renderer
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Clustered lighting
|
||||
|
||||
How the OpenGL 4.6 renderer (`rendering/opengl46/`) gives the shaders the lights of vehicle headlights.
|
||||
How the OpenGL 4.6 renderer (`rendering/opengl46/`) gives the shaders the lights of vehicle headlights and lamps.
|
||||
For the settings and what changed for players see [opengl46-renderer.md](opengl46-renderer.md).
|
||||
|
||||
## Idea
|
||||
@@ -29,13 +29,13 @@ The UBO numbers go together with the scene (0), model (1) and instance (3) block
|
||||
space of their own. Layouts of the structures are checked with `static_assert`s on sizes and offsets in
|
||||
`gl/ubo.h`, and have to stay equal to the blocks in `gl/glsl_common.cpp`.
|
||||
|
||||
Sizes: `MAX_LIGHTS` = 256 (the sun and 255 headlights), `MAX_LIGHTS_PER_CLUSTER` = 64. The buffers have a
|
||||
Sizes: `MAX_LIGHTS` = 1024 (the sun and 1023 headlights and lamps), `MAX_LIGHTS_PER_CLUSTER` = 64. The buffers have a
|
||||
fixed size, so changing the resolution, the field of view or the draw range only makes the grid parameters
|
||||
and boxes be recomputed.
|
||||
|
||||
`gl::light_data.lights_total` is the number of lights written to `lights[]`, which the culling reads.
|
||||
`lights_count` is the length of the plain loop over the lights (the sun and the first `dynamiclights` headlights) used
|
||||
when the lights are not clustered. `lights_clustered` is set per pass and tells the shading which one to use.
|
||||
when the lights are not clustered; then only headlights are written, from slot 1 on. `lights_clustered` is set per pass and tells the shading which one to use.
|
||||
|
||||
## Frame order
|
||||
|
||||
@@ -44,9 +44,11 @@ In `Render_pass()` for the color pass of a view (`opengl46_renderer.cpp`):
|
||||
1. `Update_Clusters(vp)`: `cluster_grid::update()` compares the projection and near / far plane with those the
|
||||
boxes were built for. When they differ, `cluster_build.comp` recomputes the boxes (one invocation per
|
||||
cluster, 54 work groups of 64). This is the "clusters" timer.
|
||||
2. `Update_Lights(...)`: sorts the lights of the scene (`simulation::Lights`) by distance squared over
|
||||
intensity, skips the lights that are off or farther than 1 km, writes each lit headlight to `lights[]`
|
||||
in view space, and uploads the header and the part of the array in use.
|
||||
2. `Update_Lights(...)`: with clusters, writes the cab lamp first (slot 1), when it is on. Then it sorts the lights of
|
||||
the scene (`simulation::Lights`) by distance squared over intensity, skips the lights that are off or farther than
|
||||
1 km and writes each lit headlight to `lights[]` in view space. With clusters the lamps of models and vehicles follow
|
||||
(`opengl46_local_lights`, in their order of importance), those whose sphere is in the view frustum of the pass, while
|
||||
there is room. Then it uploads the header and the part of the array in use.
|
||||
3. `Cull_Lights(vp)`: the CPU zeroes the counters, then `cluster_cull.comp` runs (one invocation per cluster, 54
|
||||
work groups of 64): it tests every light against the box of its cluster and writes the indices of the ones
|
||||
that reach it. Then `glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT)`. This is the
|
||||
@@ -81,6 +83,26 @@ reverse-Z with the far plane at infinity, so the `znear` / `zfar` of the pass bo
|
||||
cluster (`ndc.xy` times `w` at the near and far side of the slice) map back to view space through the
|
||||
inverse of the corresponding 3x3 part of the projection. The box is the min and max of the corners.
|
||||
|
||||
## Lamps
|
||||
|
||||
`opengl46_local_lights` (`rendering/opengl46/opengl46locallights.*`) gathers the other lights once per frame, in
|
||||
`Render()`, before the views are drawn, within `gfx.lights.range` of the camera:
|
||||
|
||||
- light points (`TP_FREESPOTLIGHT`) of scenery models: the instances on the translucent lists of the cells around the camera
|
||||
whose model has light points (that list is kept per cell and made anew when the list of the cell changes, and every frame
|
||||
while the editor is on). For each, `RaAnimate()` and `RaPrepare()` set the state of the shared model, as the render does,
|
||||
and the submodel tree is gone through the way `Render_Alpha(TSubModel *)` goes through it (visibility, lod ranges,
|
||||
transforms, animations). A point which is lit (emission above 0 and the light level below its `fLight`) becomes a spot light
|
||||
along its -z axis, with the cone of its glare;
|
||||
- the same for vehicles within the range, after `ABuLittleUpdate()`, with their main model, attachments and low poly interior,
|
||||
and a point light in the middle of each lit section of the low poly interior which has no light points of its own;
|
||||
- the cab lamp: a point light under the top of the bounds of the cab model, when the cab is drawn and its lamp is on.
|
||||
|
||||
Lamps are `POINT` or `SPOT` lights. The shading (`calc_local_light()`) lets them fall off with the square of the
|
||||
distance (no nearer than 10 cm) and to nothing at their range, which is written as `quadratic` = 1 / range^2 and
|
||||
which the culling takes as the end of the light. A spot light fades from `in_cutoff` to `out_cutoff` (cosines of the half
|
||||
angles); the culling tests a cone only when it is narrower than a half of the space.
|
||||
|
||||
## Culling
|
||||
|
||||
`cluster_cull.comp` handles one cluster per invocation and goes through `lights[1 .. lights_total)`.
|
||||
@@ -122,9 +144,8 @@ guarantee any storage blocks in the vertex and geometry stages.
|
||||
The work group size in the shaders and the number of groups dispatched both come from `CLUSTER_*_GROUP_SIZE`.
|
||||
- Check the shaders with `ci_shadervalidator` (see [opengl46-renderer.md](opengl46-renderer.md)); CI does it for
|
||||
changes in `shaders/` and `gl/`.
|
||||
- Only vehicle headlights feed `lights[]` today. The culling already knows `SPOT`, `POINT` and `DIR`, but
|
||||
`add_headlights()` runs `calc_headlights()` for every listed light, so a new kind of light also needs
|
||||
its own branch there.
|
||||
- A new kind of light needs its branch in `add_headlights()` (today `HEADLIGHTS` goes to `calc_headlights()`, the others
|
||||
to `calc_local_light()`) and in `light_range()` / `light_reaches_box()` of `cluster_cull.comp`.
|
||||
|
||||
## Not covered
|
||||
|
||||
|
||||
@@ -96,6 +96,40 @@ before the shading (a depth prepass), which is planned later.
|
||||
| `gfx.postfx.ao.bounce` | `0.3` | 0..1: albedo of the surfaces assumed for the light that comes back after more bounces (brightens the occlusion a little) |
|
||||
| `gfx.postfx.ao.quality slices steps` | `3 4` | directions searched around each pixel (1..8) and samples on each side of a direction (1..16) |
|
||||
|
||||
### Lamps
|
||||
|
||||
With the clustered lights on, lamps light their surroundings, besides the sun and the vehicle headlights. Without the
|
||||
clustered lights (`gfx.lights.clustered no`) none of this happens and the cab is lit as before. The switches and
|
||||
scales can also be changed in the **Light clusters** debug window.
|
||||
|
||||
- **Light points of models** (`freespotlight` submodels: street and platform lamps, signals, lamps of vehicles) are taken
|
||||
the way the experimental renderer takes them. A point which is visible, has self-illumination (`SelfIllum` `true`, or a
|
||||
threshold the light level is below) shines as a spot light along the -z axis of its submodel, in the cone of its glare
|
||||
(`FalloffAngle`, full brightness within `HotspotAngle`), in its colour; `hotspotpower` scales it. Lamps of scenery
|
||||
models switched with `Light_On` / `Light_Off` (`lights` of the model node, events) turn their light points on and off
|
||||
with them. Nothing in the models has to change; a light point without self-illumination stays a glare only.
|
||||
- **Lit compartments of vehicles** (the `cab`, `corridor`/`korytarz` and `compartment`/`przedzial` sections of the low
|
||||
poly interior) give a point light in the middle of the section, in the colour of the interior light, unless the
|
||||
section holds light points of its own (these light it then, through its self-illumination).
|
||||
- **The cab lamp** of the occupied cab is a point light under the top of the cab model. Before, it added to the ambient
|
||||
light of the whole cab and weakened the shadows of the sun in it; now a share of that ambient light is kept for the light
|
||||
which bounces around the cab (`gfx.lights.cab.bounce`), and the sun shadows stay.
|
||||
|
||||
The lamps of models and compartments fade in from the light level at which scenery lamps switch on (`ls_Dark`) to full
|
||||
darkness; in daylight they are not gathered at all. None of these lights casts shadows yet, so they also light what is
|
||||
behind walls within their reach; that reach is kept short for compartments and the cab.
|
||||
|
||||
| Entry | Default | Meaning |
|
||||
|---|---|---|
|
||||
| `gfx.lights.scenery yes/no` | `yes` | light points of scenery models light their surroundings |
|
||||
| `gfx.lights.vehicles yes/no` | `yes` | light points of vehicles and their lit compartments light their surroundings |
|
||||
| `gfx.lights.cab yes/no` | `yes` | the cab lamp is a point light; `no`: it adds to the ambient light of the cab, as before |
|
||||
| `gfx.lights.freespot.intensity` | `10` | brightness of a light point (the experimental renderer uses the same default) |
|
||||
| `gfx.lights.compartment.intensity` | `1.0` | brightness of the light of a lit compartment |
|
||||
| `gfx.lights.cab.intensity` | `1.5` | brightness of the cab lamp |
|
||||
| `gfx.lights.cab.bounce` | `0.3` | 0..1: share of the former ambient light of the cab lamp kept with the lamp on |
|
||||
| `gfx.lights.range` | `300` | distance from the camera the lamps of models and vehicles are gathered from, metres |
|
||||
|
||||
### Changed option
|
||||
|
||||
`dynamiclights` (0..7) used to limit the number of headlight sets that light the surroundings. It is still
|
||||
@@ -104,7 +138,8 @@ read, but it only takes effect with `gfx.lights.clustered no`.
|
||||
## What looks different from the previous renderer
|
||||
|
||||
- **No limit of 7 lit headlights.** All lit headlights within 1 km take part in the lighting (each lit end
|
||||
of a vehicle counts separately), up to 255 in the buffer and 64 reaching any one part of the view. Beyond
|
||||
of a vehicle counts separately), up to 1023 lights in the buffer (headlights, lamps and the cab lamp) and 64 reaching
|
||||
any one part of the view. Beyond
|
||||
these capacities the farthest and dimmest lights are dropped, and the statistics show how many.
|
||||
- **Outside the beam texture a headlight adds nothing.** Before, the edge of the texture was stretched
|
||||
beyond the beam, which could leave a faint glow around vehicles. This also applies with
|
||||
@@ -127,7 +162,10 @@ editor goes through the first `dynamiclights` headlights, the reflections throug
|
||||
time, and `cluster lists:` the size of the lists and the number of dropped (cluster, light) pairs
|
||||
(`overflow`, with its peak). A non-zero overflow means some cluster held more than 64 lights.
|
||||
- **Light clusters** window (in debug mode, menu *Windows*, item *Headlight config* opens the renderer debug
|
||||
windows): the switch for clustered lights, the heat map, the grid state and the same counters.
|
||||
windows): the switch for clustered lights, the heat map, the grid state and the same counters, and the switches and
|
||||
scales of the lamps with their counts. Shift+F12 shows the lamps in the `local lights:` row: how many were gathered (from
|
||||
scenery models, vehicles and compartments, and the cab lamp), how many were placed in the light buffer of the main view
|
||||
(those that may light something in view) and did not fit, and the cpu time of gathering them.
|
||||
- **Sky and exposure** window (next to the Light clusters window): the switches and scales above, the share of the
|
||||
atmosphere, the colours of the sun, ambient light and fog in use, and the measured luminance and exposure.
|
||||
Shift+F12 shows the GPU time of `atmosphere:` (look-up tables, only when the sun moved or the weather changed),
|
||||
|
||||
Reference in New Issue
Block a user