17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-10-29 20:57:32 +01:00

Draw the cab probe with all the lights of the cab

This commit is contained in:
2026-10-29 20:05:03 +01:00
parent 8bd41f431d
commit 96100f1155
14 changed files with 143 additions and 89 deletions

View File

@@ -261,10 +261,12 @@ shadows of the sun, see `headlight shadows:` in Shift+F12); with the vehicle on
| `gfx.lights.shadows.headlights.range` | `250` | 10..1000: distance ahead of the vehicle within which things cast the shadows of its headlights, metres |
**The probe of the cab** (`gfx.cabprobe`, OpenGL and Vulkan): two cube maps drawn from the middle of the box of the cab model,
in the space of the cab (they stay right while the vehicle moves): the light of the cab lamp the cab reflects (with the
shadows of the lamp) and the light of what glows in it (the lights of the desk), and the albedo of the cab. The glasses
in the space of the cab (they stay right while the vehicle moves): the light of the lights of the cab the cab reflects (the
lamp, or the light points of the cab model, the brightest 16 of them, each with its cone, radius and shadows) and the light
of what glows in it, and the albedo of the cab. So a lamp aimed down lights the floor and the desk, and their light lights the
ceiling and the rest of the cab again. The glasses
aren't drawn, so through them the probe shows nothing. They are drawn every `gfx.cabprobe.interval` frames (for the moving
parts and the lights of the desk) and at once when the cab or the lamp change, the six faces in one pass with the opaque
parts and the lights of the desk) and at once when the cab or its lights change (switched, dimmed), the six faces in one pass with the opaque
parts of the cab (as the shadow map of the lamp). The parts of the cab read them:
- the light of the lamp the cab reflects lights the cab again (`gfx.cabprobe.bounce`, from spherical harmonics of the
probe) in place of `gfx.lights.cab.bounce`, so the light bounces where the lamp actually lights the cab;

View File

@@ -88,6 +88,7 @@ void gl::glsl_common_setup()
"#define LOCAL_SHADOW_LAMPS_TEX " + std::to_string(LOCAL_SHADOW_LAMPS_TEX) + "\n" +
"#define HEADLIGHT_SHADOW_TEX " + std::to_string(HEADLIGHT_SHADOW_TEX) + "\n" +
"#define MAX_HEADLIGHT_SHADOWS " + std::to_string(MAX_HEADLIGHT_SHADOWS) + "U\n" +
"#define MAX_CAB_PROBE_LAMPS " + std::to_string(MAX_CAB_PROBE_LAMPS) + "U\n" +
"#define FOG_VOLUME_TEX " + std::to_string(FOG_VOLUME_TEX) + "\n" +
"#define CLOUD_SHADOW_TEX " + std::to_string(CLOUD_SHADOW_TEX) + "\n" +
"#define CLOUD_TEX " + std::to_string(CLOUD_TEX) + "\n" +

View File

@@ -67,6 +67,8 @@ namespace gl
// shadow maps of the headlights of vehicles (2d array, depth compared; opengl46_local_shadows), and how many of them there may be
const size_t HEADLIGHT_SHADOW_TEX = MAX_TEXTURES + HELPER_TEXTURES + 3;
const size_t MAX_HEADLIGHT_SHADOWS = 4;
// lights of the occupied cab the probe of the cab is drawn with (gfx::cab_probe, gl::scene_ubs::cab_probe_lamp), at most
const size_t MAX_CAB_PROBE_LAMPS = 16;
// weather (opengl46_weather): the fog of the main view (3d, apply_fog.glsl) and the shadows the clouds cast (2d), read by the
// shading. bound directly, like the ones above
const size_t FOG_VOLUME_TEX = MAX_TEXTURES + HELPER_TEXTURES + 4;
@@ -161,11 +163,17 @@ namespace gl
// x the share of the light of the lamps the cab reflects which lights it again (gfx.cabprobe.bounce), y 1 when the cab reflects
// itself (gfx.cabprobe.reflections), z the last level of the mipmaps of the probe, w unused
glm::vec4 cab_probe_params;
// the drawing of the probe (cabprobe.glsl), set for it only: xyz the cab lamp in the space of the probe, w 1 / its range
// squared (0: no lamp); rgb its light, a 1 with its shadow map (LOCAL_SHADOW_TEX); the headlight_weights of that map
glm::vec4 cab_probe_lamp;
glm::vec4 cab_probe_lamp_color;
glm::vec4 cab_probe_lamp_shadow;
// the drawing of the probe (cabprobe.glsl), set for it only: the lights of the cab (gfx::local_lights::cab_lights()), the
// brightest first, each: xyz the light in the space of the probe, w 1 / its range squared (0: no more lights); rgb its light,
// a 1 with a shadow map (LOCAL_SHADOW_TEX); the headlight_weights of that map; xyz the axis of its cone in the space of the
// probe, w the cosine of its outer half angle (-1: all around); x the cosine of the inner one, y its radius (negative: the
// soft falloff), zw unused; xyz the light the map was drawn for (the light itself, or the closest one with a map), w unused
glm::vec4 cab_probe_lamp[MAX_CAB_PROBE_LAMPS];
glm::vec4 cab_probe_lamp_color[MAX_CAB_PROBE_LAMPS];
glm::vec4 cab_probe_lamp_shadow[MAX_CAB_PROBE_LAMPS];
glm::vec4 cab_probe_lamp_cone[MAX_CAB_PROBE_LAMPS];
glm::vec4 cab_probe_lamp_shape[MAX_CAB_PROBE_LAMPS];
glm::vec4 cab_probe_lamp_map[MAX_CAB_PROBE_LAMPS];
// the occlusion of the sky and of the sun by the scenery around the camera (gfx.skyvisibility, gfx::sky_occlusion), zero when
// there are no maps: x, y the world x, z of the camera of the pass wrapped to the size of the maps (the place of the camera on
// them), metres; z the world height of the camera; w 1 with the maps, 2 when the volumetric fog reads them too
@@ -186,7 +194,7 @@ namespace gl
glm::vec4 cab_probe_sun_world;
};
static_assert(sizeof(scene_ubs) == 976 + 80 * MAX_HEADLIGHT_SHADOWS, "bad size of ubs");
static_assert(sizeof(scene_ubs) == 928 + 80 * MAX_HEADLIGHT_SHADOWS + 96 * MAX_CAB_PROBE_LAMPS, "bad size of ubs");
const size_t MAX_PARAMS = 3;

View File

@@ -73,7 +73,8 @@ void cab_probe::release()
m_masked = false;
}
bool cab_probe::update_wanted(TDynamicObject const *Vehicle, TModel3d const *Cab, glm::vec3 const &Center, glm::vec3 const &Extent, gfx::local_lights::light const *Lamp, unsigned int const Framestamp)
bool cab_probe::update_wanted(TDynamicObject const *Vehicle, TModel3d const *Cab, glm::vec3 const &Center, glm::vec3 const &Extent, std::vector<gfx::local_lights::cab_light> const &Lights,
unsigned int const Framestamp)
{
auto const level{std::clamp(Global.gfx_cabprobe, 0, 3)};
if (level != m_level)
@@ -92,7 +93,12 @@ bool cab_probe::update_wanted(TDynamicObject const *Vehicle, TModel3d const *Cab
m_masked = false;
return false;
}
auto const lamp{Lamp != nullptr ? Lamp->color : glm::vec3{0.f}};
// the lights the probe is drawn with, together: one of them switched or dimmed changes it
glm::vec3 lamp{0.f};
for (std::size_t idx = 0; idx < std::min(Lights.size(), gl::MAX_CAB_PROBE_LAMPS); ++idx)
{
lamp += Lights[idx].source.color;
}
auto const lampchange{glm::length(lamp - m_lamp)};
auto const lampchanged{(lampchange > 0.f) && ((max_component(m_lamp) <= 0.f) || (max_component(lamp) <= 0.f) || (lampchange > LAMP_CHANGED * glm::length(m_lamp)))};
if ((Vehicle != m_vehicle) || (Cab != m_cab) || (Center != m_center) || (Extent != m_extent))
@@ -120,19 +126,28 @@ bool cab_probe::update_wanted(TDynamicObject const *Vehicle, TModel3d const *Cab
return true;
}
void cab_probe::setup_drawing(gl::scene_ubs &Scene, gfx::local_lights::light const *Lamp, glm::vec3 const &Lamplocal, bool const Shadows, glm::vec4 const &Shadowweights) const
void cab_probe::setup_drawing(gl::scene_ubs &Scene, std::vector<gfx::local_lights::cab_light> const &Lights, gfx::local_shadows const &Shadows, TDynamicObject const *Vehicle) const
{
if (Lamp == nullptr)
for (std::size_t idx = 0; idx < gl::MAX_CAB_PROBE_LAMPS; ++idx)
{
Scene.cab_probe_lamp = glm::vec4{0.f};
Scene.cab_probe_lamp_color = glm::vec4{0.f};
Scene.cab_probe_lamp_shadow = glm::vec4{0.f};
return;
if (idx >= Lights.size())
{
// the end of the lights
Scene.cab_probe_lamp[idx] = glm::vec4{0.f};
Scene.cab_probe_lamp_color[idx] = glm::vec4{0.f};
continue;
}
auto const &light{Lights[idx]};
// as the light buffer has it (Write_Local_Light()): the shading takes the light to end at 1 / sqrt(quadratic)
Scene.cab_probe_lamp[idx] = glm::vec4{light.local - m_center, 1.f / sq(std::max(light.source.range, 0.01f))};
Scene.cab_probe_lamp_cone[idx] = glm::vec4{light.local_direction, light.source.cos_outer};
Scene.cab_probe_lamp_shape[idx] = glm::vec4{light.source.cos_inner, (light.source.soft_falloff ? -light.source.radius : light.source.radius), 0.f, 0.f};
// with the shadow map of the light, or of the closest light with one
auto const slot{Shadows.cab_slot_of(Vehicle, light)};
Scene.cab_probe_lamp_color[idx] = glm::vec4{light.source.color, (slot >= 0 ? 1.f : 0.f)};
Scene.cab_probe_lamp_shadow[idx] = (slot >= 0 ? Shadows.weights(static_cast<std::size_t>(slot)) : glm::vec4{0.f});
Scene.cab_probe_lamp_map[idx] = glm::vec4{(slot >= 0 ? Shadows.cab(static_cast<std::size_t>(slot)).lamp : light.local) - m_center, 0.f};
}
// as the light buffer has it (Write_Local_Light()): the shading takes the light to end at 1 / sqrt(quadratic)
Scene.cab_probe_lamp = glm::vec4{Lamplocal - m_center, 1.f / sq(std::max(Lamp->range, 0.01f))};
Scene.cab_probe_lamp_color = glm::vec4{Lamp->color, Shadows ? 1.f : 0.f};
Scene.cab_probe_lamp_shadow = Shadowweights;
}
void cab_probe::setup_sun(gl::scene_ubs &Scene, TDynamicObject const *Vehicle, glm::vec3 const &Tosun, glm::vec3 const &Sunlight, glm::dvec3 const &Camera) const

View File

@@ -15,6 +15,7 @@ http://mozilla.org/MPL/2.0/.
#include "gl/ubo.h"
#include "rendering/common/locallights.h"
#include "rendering/common/localshadows.h"
class TDynamicObject;
class TModel3d;
@@ -25,8 +26,8 @@ namespace gfx
// the probe of the occupied cab (Global.gfx_cabprobe, the stage A4 of claude/renderers-plan.md), the part shared by the renderers;
// the backend (opengl46_cab_probe, vk14::cab_probe_maps) keeps the maps and draws to them through the gpu_* methods.
// - two cube maps drawn from the middle of the box of the cab model (mdKabina), in the space of the model, so they stay right while
// the vehicle moves and turns: the light of the cab lamp the cab reflects (with the shadow map of the lamp) and the light of what
// glows in it, and the albedo of the cab. both are cleared to nothing and premultiplied by the share of the direction the cab
// the vehicle moves and turns: the light of the lights of the cab (the lamp, the light points of the cab model, the brightest
// gl::MAX_CAB_PROBE_LAMPS of them, with their shadow maps) the cab reflects and the light of what glows in it, and the albedo of the cab. both are cleared to nothing and premultiplied by the share of the direction the cab
// fills, which is in their alpha (the glasses aren't drawn: through them the cab shows nothing), and have mipmaps;
// - the six faces are drawn at once (a geometry shader with opengl, multiview with vulkan) by the programs of the probe
// (cabprobe.vert, cabprobe.frag), every few frames (Global.gfx_cabprobe_interval: the moving parts of the cab, the lights of the
@@ -53,12 +54,13 @@ class cab_probe
// size of a face of the maps of the level (Global.gfx_cabprobe), 0 for none
static int size_of(int const Level);
// whether the probe is to be drawn in this frame. Vehicle: the occupied vehicle whose cab is drawn (nullptr: none), Cab its cab
// model, Center and Extent the box of the model (model space); Lamp the cab lamp when it's a light of the frame (nullptr: none).
// (re)makes the maps when the level changed
bool update_wanted(TDynamicObject const *Vehicle, TModel3d const *Cab, glm::vec3 const &Center, glm::vec3 const &Extent, gfx::local_lights::light const *Lamp, unsigned int const Framestamp);
// the fields of the block of the scene the drawing of the probe reads: the cab lamp (Lamp, at Lamplocal in the space of the cab
// model, nullptr: none) with its shadow map when Shadows (Shadowweights: the headlight_weights of the map)
void setup_drawing(gl::scene_ubs &Scene, gfx::local_lights::light const *Lamp, glm::vec3 const &Lamplocal, bool const Shadows, glm::vec4 const &Shadowweights) const;
// model, Center and Extent the box of the model (model space); Lights the lights of the cab of the frame, the brightest first
// (empty: none). (re)makes the maps when the level changed
bool update_wanted(TDynamicObject const *Vehicle, TModel3d const *Cab, glm::vec3 const &Center, glm::vec3 const &Extent, std::vector<gfx::local_lights::cab_light> const &Lights,
unsigned int const Framestamp);
// the fields of the block of the scene the drawing of the probe reads: the lights of the cab of Vehicle (Lights, the brightest first)
// with the shadow maps Shadows holds for them
void setup_drawing(gl::scene_ubs &Scene, std::vector<gfx::local_lights::cab_light> const &Lights, gfx::local_shadows const &Shadows, TDynamicObject const *Vehicle) const;
// the fields of the block of the scene the drawing of the probe takes the sun with: Vehicle the vehicle whose cab is drawn, Tosun the
// direction towards the sun (the moon), world space, Sunlight its light as the shading gets it (the colour of the light buffer times
// its intensity), Camera the camera of the main view (world space). no sun until the mask holds the cab
@@ -123,7 +125,7 @@ class cab_probe
TModel3d const *m_cab{nullptr};
glm::vec3 m_center{0.f};
glm::vec3 m_extent{0.f};
// the light of the cab lamp the probe was drawn with, 0 without the lamp
// the light of the lights of the cab the probe was drawn with (their sum), 0 without them
glm::vec3 m_lamp{0.f};
unsigned int m_drawnframe{0};
// statistics

View File

@@ -350,6 +350,7 @@ void gfx::local_lights::gather_cab_lights(gfx::geometrybank_manager const &Geome
cab_light cablight;
cablight.source = m_lights[idx];
cablight.local = glm::vec3{m_lights[idx].position};
cablight.local_direction = m_lights[idx].direction;
cablight.source.position = vehicle->GetWorldPosition(m_lights[idx].position);
auto const direction{glm::vec3{rotation * glm::dvec3{m_lights[idx].direction}}};
cablight.source.direction = (glm::length2(direction) > 0.f ? glm::normalize(direction) : glm::vec3{0.f, -1.f, 0.f});

View File

@@ -87,17 +87,13 @@ class local_lights
{
light source;
glm::vec3 local{0.f};
glm::vec3 local_direction{0.f, -1.f, 0.f}; // the axis of its cone in the space of the cab model
};
// the lights of the occupied cab which are on, when the cab is drawn, the brightest first; empty otherwise
std::vector<cab_light> const &cab_lights() const
{
return m_cablights;
}
// the brightest light of the cab, which lights its probe; nullptr when there is none
cab_light const *cab_principal() const
{
return m_cablights.empty() ? nullptr : &m_cablights.front();
}
// the vehicle of the lights of the cab, when any of them is on
TDynamicObject const *cab_lamp_vehicle() const
{

View File

@@ -6320,16 +6320,15 @@ void opengl46_renderer::Render_cab_probe()
glm::vec3 extent{0.f};
if ((vehicle != nullptr) && (false == m_locallights.cab_bounds(vehicle->mdKabina, m_geometry, center, extent)))
vehicle = nullptr;
// the brightest light of the cab lights the probe when it's a light of the frame
auto const *principal{(vehicle != nullptr) && (m_locallights.cab_lamp_vehicle() == vehicle) ? m_locallights.cab_principal() : nullptr};
auto const *lamp{principal != nullptr ? &principal->source : nullptr};
if (false == m_cabprobe.update_wanted(vehicle, (vehicle != nullptr ? vehicle->mdKabina : nullptr), center, extent, lamp, m_framestamp))
// the lights of the cab light the probe when they're lights of the frame
std::vector<gfx::local_lights::cab_light> const nolights;
auto const &lights{(vehicle != nullptr) && (m_locallights.cab_lamp_vehicle() == vehicle) ? m_locallights.cab_lights() : nolights};
if (false == m_cabprobe.update_wanted(vehicle, (vehicle != nullptr ? vehicle->mdKabina : nullptr), center, extent, lights, m_framestamp))
return;
glDebug("render cab probe");
// the light with its shadow map, when the map holds the shadows of the light where it is
auto const slot{principal != nullptr ? m_localshadows.cab_slot_of(vehicle, *principal) : -1};
m_cabprobe.setup_drawing(scene_ubs, lamp, (principal != nullptr ? principal->local : glm::vec3{0.f}), (slot >= 0), (slot >= 0 ? m_localshadows.weights(static_cast<std::size_t>(slot)) : glm::vec4{0.f}));
// the lights with their shadow maps, where the maps hold their shadows
m_cabprobe.setup_drawing(scene_ubs, lights, m_localshadows, vehicle);
// the sun coming in through the windows, as the shading of the last frame got it
m_cabprobe.setup_sun(scene_ubs, vehicle, -m_sunlight.direction, glm::vec3{light_data.lights[0].color} * light_data.lights[0].intensity, m_colorpass.pass_camera.position());
scene_ubo->update(scene_ubs);

View File

@@ -348,10 +348,10 @@ void vulkan14_renderer::render_cab_probe()
{
vehicle = nullptr;
}
// the brightest light of the cab lights the probe when it's a light of the frame
auto const *principal{(vehicle != nullptr) && (m_locallights.cab_lamp_vehicle() == vehicle) ? m_locallights.cab_principal() : nullptr};
auto const *lamp{principal != nullptr ? &principal->source : nullptr};
if (false == probe.update_wanted(vehicle, (vehicle != nullptr ? vehicle->mdKabina : nullptr), center, extent, lamp, m_framestamp))
// the lights of the cab light the probe when they're lights of the frame
std::vector<gfx::local_lights::cab_light> const nolights;
auto const &lights{(vehicle != nullptr) && (m_locallights.cab_lamp_vehicle() == vehicle) ? m_locallights.cab_lights() : nolights};
if (false == probe.update_wanted(vehicle, (vehicle != nullptr ? vehicle->mdKabina : nullptr), center, extent, lights, m_framestamp))
{
return;
}
@@ -361,9 +361,8 @@ void vulkan14_renderer::render_cab_probe()
return;
}
ctx.passes.begin_pass("cab probe");
// the light with its shadow map, when the map holds the shadows of the light where it is
auto const slot{principal != nullptr ? scene.lamps.cab_slot_of(vehicle, *principal) : -1};
probe.setup_drawing(scene_ubs, lamp, (principal != nullptr ? principal->local : glm::vec3{0.f}), (slot >= 0), (slot >= 0 ? scene.lamps.weights(static_cast<std::size_t>(slot)) : glm::vec4{0.f}));
// the lights with their shadow maps, where the maps hold their shadows
probe.setup_drawing(scene_ubs, lights, scene.lamps, vehicle);
// the sun coming in through the windows, as the shading of the last frame got it. the mask is read once it was copied
probe.setup_sun(scene_ubs, vehicle, -m_sunlight.direction, glm::vec3{light_data.lights[0].color} * light_data.lights[0].intensity, m_colorpass.pass_camera.position());
if (probe.mask_map() == nullptr)

View File

@@ -889,6 +889,7 @@ std::string binding_preamble(bool const Raytracing)
define("MAX_CASCADES", static_cast<unsigned int>(gl::MAX_CASCADES), "U");
define("MAX_PARAMS", static_cast<unsigned int>(gl::MAX_PARAMS), "U");
define("MAX_HEADLIGHT_SHADOWS", static_cast<unsigned int>(gl::MAX_HEADLIGHT_SHADOWS), "U");
define("MAX_CAB_PROBE_LAMPS", static_cast<unsigned int>(gl::MAX_CAB_PROBE_LAMPS), "U");
define("CLUSTER_GRID_X", gl::CLUSTER_GRID_X);
define("CLUSTER_GRID_Y", gl::CLUSTER_GRID_Y);
define("CLUSTER_GRID_Z", gl::CLUSTER_GRID_Z);

View File

@@ -1,10 +1,10 @@
// the shading of the probe of the occupied cab (gfx::cab_probe), for cabprobe.frag and cabprobe_alpha.frag: what the cab shows
// towards the middle of its box lit by the cab lamp alone, with the cube shadow map of the lamp (and what glows in it, the lights
// of the desk), and its albedo, each with 1 in the alpha: the probe is cleared to nothing, so the alpha of a direction tells how
// much of it the cab fills, and both are premultiplied by it. the light of the cab lamp is the one the shading gives it
// (calc_local_light() in light_common.glsl). the sun (the moon) lights the cab where it comes in through the windows
// towards the middle of its box lit by the lights of the cab alone (its lamp or the light points of the cab model, the brightest
// MAX_CAB_PROBE_LAMPS, each with its cube shadow map; and what glows in it), and its albedo, each with 1 in the alpha: the probe is cleared to nothing, so the alpha of a direction tells how
// much of it the cab fills, and both are premultiplied by it. the light of a light of the cab is about the one the shading gives
// it (calc_local_light() in light_common.glsl): its cone, its sphere or soft falloff, its shadows. the sun (the moon) lights the cab where it comes in through the windows
// (gl::scene_ubs::cab_probe_sun), so the light which bounces around the cab holds it; the ambient light is left out, the cab gets it as
// before. the parameters of the lamp and of the sun are in the block of the scene (gl::scene_ubs::cab_probe_lamp, cab_probe_sun), in
// before. the parameters of the lights and of the sun are in the block of the scene (gl::scene_ubs::cab_probe_lamp, cab_probe_sun), in
// the space of the probe. the including shader declares cab_probe_mask (CAB_PROBE_MASK_TEX) and includes weather_common.glsl
layout(location = 0) out vec4 out_light;
@@ -24,11 +24,11 @@ vec3 probe_material_diffuse()
return (value > 0.0 ? diffusecolor * (param[1].x / value) : vec3(0.0));
}
// share of the light of the cab lamp held back before the point of the space of its cube shadow map (origin at the lamp), 0..1, as
// local_light_shadow() of light_common.glsl takes it with a single sample
float probe_lamp_shadow(vec3 position, vec3 normal)
// share of the light of the light Lamp of the cab held back before the point of the space of its cube shadow map (origin at the
// light the map was drawn for), 0..1, as local_light_shadow() of light_common.glsl takes it with a single sample
float probe_lamp_shadow(int lamp, vec3 position, vec3 normal)
{
vec4 weights = cab_probe_lamp_shadow;
vec4 weights = cab_probe_lamp_shadow[lamp];
float distance = length(position);
float texel = weights.z * distance;
vec3 tolamp = -position / max(distance, 1e-4);
@@ -63,17 +63,28 @@ void probe_shade(vec4 tex_color)
if (dot(normal, position) > 0.0)
normal = -normal;
vec3 light = vec3(emission);
if (cab_probe_lamp.w > 0.0)
for (int i = 0; i < int(MAX_CAB_PROBE_LAMPS); i++)
{
vec3 tolight = cab_probe_lamp.xyz - position;
vec4 lamp = cab_probe_lamp[i];
if (lamp.w <= 0.0)
break;
vec3 tolight = lamp.xyz - position;
float distance2 = dot(tolight, tolight);
vec3 light_dir = tolight * inversesqrt(max(distance2, 1e-8));
float edge = clamp(1.0 - distance2 * distance2 * (cab_probe_lamp.w * cab_probe_lamp.w), 0.0, 1.0);
float atten = edge * edge / max(distance2, PROBE_LIGHT_MIN_DISTANCE2);
float edge = clamp(1.0 - distance2 * distance2 * (lamp.w * lamp.w), 0.0, 1.0);
// as lamp_falloff() of common.glsl: the soft falloff (a negative radius), or the light of the sphere, which is the one of a
// point outside it
float radius = cab_probe_lamp_shape[i].y;
float falloff = (radius < 0.0) ? 1.0 / max(distance2 + radius * radius, 1e-6) : 1.0 / max(distance2, (radius > 0.0) ? radius * radius : PROBE_LIGHT_MIN_DISTANCE2);
float atten = edge * edge * falloff;
// the cone of a spot light
vec4 cone = cab_probe_lamp_cone[i];
if (cone.w > -1.0)
atten *= smoothstep(cone.w, cab_probe_lamp_shape[i].x, dot(-light_dir, normalize(cone.xyz)));
float NdotL = max(dot(normal, light_dir), 0.0);
if ((atten > 0.0) && (NdotL > 0.0) && (cab_probe_lamp_color.a > 0.5))
atten *= 1.0 - probe_lamp_shadow(-tolight, normal);
light += cab_probe_lamp_color.rgb * (NdotL * atten);
if ((atten > 0.0) && (NdotL > 0.0) && (cab_probe_lamp_color[i].a > 0.5))
atten *= 1.0 - probe_lamp_shadow(i, position - cab_probe_lamp_map[i].xyz, normal);
light += cab_probe_lamp_color[i].rgb * (NdotL * atten);
}
if (cab_probe_sun.w > 0.0)
{

View File

@@ -97,6 +97,7 @@
#define LOCAL_SHADOW_LAMPS_TEX 14
#define HEADLIGHT_SHADOW_TEX 15
#define MAX_HEADLIGHT_SHADOWS 4U
#define MAX_CAB_PROBE_LAMPS 16U
#define FOG_VOLUME_TEX 16
#define CLOUD_SHADOW_TEX 17
#define CLOUD_TEX 18
@@ -343,13 +344,16 @@ layout(std140, binding = SCENE_UBO_BINDING) uniform scene_ubo
vec4 rain_wind;
// the ambient occlusion in the light of the surfaces, see gl::scene_ubs
vec4 ao_params;
// the probe of the occupied cab, and the lamp it's drawn with, see gl::scene_ubs
// the probe of the occupied cab, and the lights of the cab it's drawn with, see gl::scene_ubs
mat4 cab_probe_view;
vec4 cab_probe_box;
vec4 cab_probe_params;
vec4 cab_probe_lamp;
vec4 cab_probe_lamp_color;
vec4 cab_probe_lamp_shadow;
vec4 cab_probe_lamp[MAX_CAB_PROBE_LAMPS];
vec4 cab_probe_lamp_color[MAX_CAB_PROBE_LAMPS];
vec4 cab_probe_lamp_shadow[MAX_CAB_PROBE_LAMPS];
vec4 cab_probe_lamp_cone[MAX_CAB_PROBE_LAMPS];
vec4 cab_probe_lamp_shape[MAX_CAB_PROBE_LAMPS];
vec4 cab_probe_lamp_map[MAX_CAB_PROBE_LAMPS];
// the occlusion of the sky and of the sun by the scenery around the camera, see gl::scene_ubs
vec4 sky_occlusion_origin;
vec4 sky_occlusion_params;

View File

@@ -1,10 +1,10 @@
// the shading of the probe of the occupied cab (gfx::cab_probe, as shaders/ogl46/cabprobe.glsl), for cabprobe.frag and cabprobe_alpha.frag: what the cab shows
// towards the middle of its box lit by the cab lamp alone, with the cube shadow map of the lamp (and what glows in it, the lights
// of the desk), and its albedo, each with 1 in the alpha: the probe is cleared to nothing, so the alpha of a direction tells how
// much of it the cab fills, and both are premultiplied by it. the light of the cab lamp is the one the shading gives it
// (calc_local_light() in light_common.glsl). the sun (the moon) lights the cab where it comes in through the windows
// towards the middle of its box lit by the lights of the cab alone (its lamp or the light points of the cab model, the brightest
// MAX_CAB_PROBE_LAMPS, each with its cube shadow map; and what glows in it), and its albedo, each with 1 in the alpha: the probe is cleared to nothing, so the alpha of a direction tells how
// much of it the cab fills, and both are premultiplied by it. the light of a light of the cab is about the one the shading gives
// it (calc_local_light() in light_common.glsl): its cone, its sphere or soft falloff, its shadows. the sun (the moon) lights the cab where it comes in through the windows
// (gl::scene_ubs::cab_probe_sun), so the light which bounces around the cab holds it; the ambient light is left out, the cab gets it as
// before. the parameters of the lamp and of the sun are in the block of the scene (gl::scene_ubs::cab_probe_lamp, cab_probe_sun), in
// before. the parameters of the lights and of the sun are in the block of the scene (gl::scene_ubs::cab_probe_lamp, cab_probe_sun), in
// the space of the probe. the including shader declares cab_probe_mask (CAB_PROBE_MASK_TEX) and includes weather_common.glsl
layout(location = 0) out vec4 out_light;
@@ -24,11 +24,11 @@ vec3 probe_material_diffuse()
return (value > 0.0 ? diffusecolor * (param[1].x / value) : vec3(0.0));
}
// share of the light of the cab lamp held back before the point of the space of its cube shadow map (origin at the lamp), 0..1, as
// local_light_shadow() of light_common.glsl takes it with a single sample
float probe_lamp_shadow(vec3 position, vec3 normal)
// share of the light of the light Lamp of the cab held back before the point of the space of its cube shadow map (origin at the
// light the map was drawn for), 0..1, as local_light_shadow() of light_common.glsl takes it with a single sample
float probe_lamp_shadow(int lamp, vec3 position, vec3 normal)
{
vec4 weights = cab_probe_lamp_shadow;
vec4 weights = cab_probe_lamp_shadow[lamp];
float distance = length(position);
float texel = weights.z * distance;
vec3 tolamp = -position / max(distance, 1e-4);
@@ -63,17 +63,28 @@ void probe_shade(vec4 tex_color)
if (dot(normal, position) > 0.0)
normal = -normal;
vec3 light = vec3(emission);
if (cab_probe_lamp.w > 0.0)
for (int i = 0; i < int(MAX_CAB_PROBE_LAMPS); i++)
{
vec3 tolight = cab_probe_lamp.xyz - position;
vec4 lamp = cab_probe_lamp[i];
if (lamp.w <= 0.0)
break;
vec3 tolight = lamp.xyz - position;
float distance2 = dot(tolight, tolight);
vec3 light_dir = tolight * inversesqrt(max(distance2, 1e-8));
float edge = clamp(1.0 - distance2 * distance2 * (cab_probe_lamp.w * cab_probe_lamp.w), 0.0, 1.0);
float atten = edge * edge / max(distance2, PROBE_LIGHT_MIN_DISTANCE2);
float edge = clamp(1.0 - distance2 * distance2 * (lamp.w * lamp.w), 0.0, 1.0);
// as lamp_falloff() of common.glsl: the soft falloff (a negative radius), or the light of the sphere, which is the one of a
// point outside it
float radius = cab_probe_lamp_shape[i].y;
float falloff = (radius < 0.0) ? 1.0 / max(distance2 + radius * radius, 1e-6) : 1.0 / max(distance2, (radius > 0.0) ? radius * radius : PROBE_LIGHT_MIN_DISTANCE2);
float atten = edge * edge * falloff;
// the cone of a spot light
vec4 cone = cab_probe_lamp_cone[i];
if (cone.w > -1.0)
atten *= smoothstep(cone.w, cab_probe_lamp_shape[i].x, dot(-light_dir, normalize(cone.xyz)));
float NdotL = max(dot(normal, light_dir), 0.0);
if ((atten > 0.0) && (NdotL > 0.0) && (cab_probe_lamp_color.a > 0.5))
atten *= 1.0 - probe_lamp_shadow(-tolight, normal);
light += cab_probe_lamp_color.rgb * (NdotL * atten);
if ((atten > 0.0) && (NdotL > 0.0) && (cab_probe_lamp_color[i].a > 0.5))
atten *= 1.0 - probe_lamp_shadow(i, position - cab_probe_lamp_map[i].xyz, normal);
light += cab_probe_lamp_color[i].rgb * (NdotL * atten);
}
if (cab_probe_sun.w > 0.0)
{

View File

@@ -98,6 +98,7 @@
#define MAX_CASCADES 3U
#define MAX_PARAMS 3U
#define MAX_HEADLIGHT_SHADOWS 4U
#define MAX_CAB_PROBE_LAMPS 16U
#define CLUSTER_GRID_X 16
#define CLUSTER_GRID_Y 9
#define CLUSTER_GRID_Z 24
@@ -310,13 +311,16 @@ layout(std140, set = PASS_SET, binding = SCENE_UBO) uniform scene_ubo
vec4 rain_wind;
// the ambient occlusion in the light of the surfaces, see gl::scene_ubs
vec4 ao_params;
// the probe of the occupied cab, and the lamp it's drawn with, see gl::scene_ubs
// the probe of the occupied cab, and the lights of the cab it's drawn with, see gl::scene_ubs
mat4 cab_probe_view;
vec4 cab_probe_box;
vec4 cab_probe_params;
vec4 cab_probe_lamp;
vec4 cab_probe_lamp_color;
vec4 cab_probe_lamp_shadow;
vec4 cab_probe_lamp[MAX_CAB_PROBE_LAMPS];
vec4 cab_probe_lamp_color[MAX_CAB_PROBE_LAMPS];
vec4 cab_probe_lamp_shadow[MAX_CAB_PROBE_LAMPS];
vec4 cab_probe_lamp_cone[MAX_CAB_PROBE_LAMPS];
vec4 cab_probe_lamp_shape[MAX_CAB_PROBE_LAMPS];
vec4 cab_probe_lamp_map[MAX_CAB_PROBE_LAMPS];
// the occlusion of the sky and of the sun by the scenery around the camera, see gl::scene_ubs
vec4 sky_occlusion_origin;
vec4 sky_occlusion_params;