17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-11-06 01:12:26 +01:00

Light the cab with cablight/dashboardlight light points of the cab model

This commit is contained in:
2026-10-28 20:55:45 +01:00
parent 8f891fdc14
commit 9904eddd0d
22 changed files with 512 additions and 214 deletions

View File

@@ -24,8 +24,6 @@ float const SHADOW_NEAR{gfx::local_shadows::shadow_near};
// uniform locations of shadowcube.geom
GLint const NEAR_LOCATION{0};
GLint const LAYER_LOCATION{1};
// layer of the map of the cab lamp in the array
int const CAB_SLOT{gfx::local_shadows::cab_slot};
// cube map array of depth maps compared to the reference, one level, Cubes cubes of Size x Size faces
GLuint make_cube_array(int const Size, int const Cubes)
@@ -136,7 +134,7 @@ void opengl46_local_shadows::init()
m_multidraw_program.reset();
m_alpha_multidraw_program.reset();
}
set_layer(CAB_SLOT * 6);
set_layer(0);
// a shadow sampler with no depth texture to read from is undefined, also where the shading doesn't read it
glCreateTextures(GL_TEXTURE_CUBE_MAP_ARRAY, 1, &m_empty);
@@ -173,9 +171,9 @@ void opengl46_local_shadows::set_layer(int const Layer)
glProgramUniform1i(*m_alpha_multidraw_program, LAYER_LOCATION, Layer);
}
bool opengl46_local_shadows::gpu_allocate(int const Size)
bool opengl46_local_shadows::gpu_allocate(int const Count, int const Size)
{
m_texture = make_cube_array(Size, CAB_SLOT + 1);
m_texture = make_cube_array(Size, Count);
m_framebuffer = make_framebuffer(m_texture);
return (m_framebuffer != 0);
}
@@ -235,21 +233,25 @@ void opengl46_local_shadows::bind()
glBindTextureUnit(gl::HEADLIGHT_SHADOW_TEX, (m_headlightstexture != 0) ? m_headlightstexture : m_emptyheadlights);
}
void opengl46_local_shadows::gpu_begin_cab()
void opengl46_local_shadows::gpu_begin_cab(std::size_t const Slot)
{
m_timer.begin();
set_layer(CAB_SLOT * 6);
set_near(SHADOW_NEAR);
if (Slot == m_cabdraws.front())
m_timer.begin();
set_layer(static_cast<int>(Slot) * 6);
// the near plane of the light, which the shading reads the map with (weights())
set_near(m_cabslots[Slot].nearplane);
setup_drawing(m_framebuffer, m_size);
float const farthest{0.f};
glClearNamedFramebufferfv(m_framebuffer, GL_DEPTH, 0, &farthest);
glClearTexSubImage(m_texture, 0, 0, 0, static_cast<GLint>(Slot) * 6, m_size, m_size, 6, GL_DEPTH_COMPONENT, GL_FLOAT, &farthest);
}
void opengl46_local_shadows::gpu_end_cab()
{
glEnable(GL_CULL_FACE);
gl::framebuffer::unbind();
m_timer.end();
set_layer(0);
if (m_cabdrawing == m_cabdraws.back())
m_timer.end();
}
void opengl46_local_shadows::gpu_begin_lamp(int const Scenerycube, int const Workingcube, bool const Vehicles)
@@ -274,7 +276,7 @@ void opengl46_local_shadows::gpu_end_lamp()
{
glEnable(GL_CULL_FACE);
gl::framebuffer::unbind();
set_layer(CAB_SLOT * 6);
set_layer(0);
}
void opengl46_local_shadows::gpu_lamps_timer(bool const Begin)

View File

@@ -51,13 +51,13 @@ class opengl46_local_shadows : public gfx::local_shadows
std::string info_times();
protected:
bool gpu_allocate(int const Size) override;
bool gpu_allocate(int const Count, int const Size) override;
void gpu_release() override;
bool gpu_allocate_lamps(int const Count, int const Size) override;
void gpu_release_lamps() override;
bool gpu_allocate_headlights(int const Count, int const Size) override;
void gpu_release_headlights() override;
void gpu_begin_cab() override;
void gpu_begin_cab(std::size_t const Slot) override;
void gpu_end_cab() override;
void gpu_begin_lamp(int const Scenerycube, int const Workingcube, bool const Vehicles) override;
void gpu_end_lamp() override;
@@ -76,7 +76,7 @@ class opengl46_local_shadows : public gfx::local_shadows
std::unique_ptr<gl::program> m_alpha_multidraw_program;
GLuint m_empty{0}; // stand-in: a cube map array of 1x1 faces with the farthest depth
GLuint m_emptyheadlights{0}; // the same, a 2d array of one 1x1 layer
// cab lamp: cube map array, one cube
// lights of the cab: cube map array, a cube per slot
GLuint m_texture{0};
GLuint m_framebuffer{0};
gl::gpu_timer m_timer;

View File

@@ -1826,7 +1826,7 @@ void opengl46_renderer::Render_pass(viewport_config &vp, rendermode const Mode)
setup_shadow_bind_map();
m_weather.render_view(
OpenGLMatrices.data( GL_PROJECTION ), glm::mat4{ m_colorpass.pass_camera.modelview() }, m_colorpass.pass_camera.position(), fogtarget,
( m_cablamplit && Global.gfx_lights_clustered && vp.clusters->valid() ) ? 1 : -1 );
( m_cablamplit && Global.gfx_lights_clustered && vp.clusters->valid() ) ? m_cablamps : 0 );
}
m_weather.setup_pass( vp.main, fogtarget );
}
@@ -6080,29 +6080,34 @@ void opengl46_renderer::Update_Lights(light_array &Lights, bool const Headlights
size_t light_i = 1;
m_lights_dropped = 0;
// the lights other than the headlights are only taken from the lists of the clusters. the lamp of the occupied cab goes first:
// it is next to the camera, and it is not to be the one left out of a full cluster
// the lights other than the headlights are only taken from the lists of the clusters. the lights of the occupied cab go first:
// they are next to the camera, and they are not to be the ones left out of a full cluster
auto const locallights{Headlights && Clustered};
m_cablamplit = false;
m_cablamps = 0;
if( locallights ) {
if( auto const *lamp{ m_locallights.cab_lamp() } ) {
auto const *vehicle{ m_locallights.cab_lamp_vehicle() };
for( auto const &cablight : m_locallights.cab_lights() ) {
if( light_i >= gl::MAX_LIGHTS ) {
break;
}
auto &light{ light_data.lights[ light_i++ ] };
Write_Local_Light( light, *lamp, camera, mv );
m_cablamplit = true;
auto const *vehicle{ m_locallights.cab_lamp_vehicle() };
if( m_localshadows.ready( vehicle ) ) {
// view space to the space of the map: the space of the cab model, with the lamp at the origin. the vehicle is
Write_Local_Light( light, cablight.source, camera, mv );
++m_cablamps;
if( auto const slot{ m_localshadows.cab_slot_of( vehicle, cablight ) }; slot >= 0 ) {
// view space to the space of the map: the space of the cab model, with the light at the origin. the vehicle is
// where it is now, the map stays right as it moves
auto const toworld{ glm::dmat4{ glm::transpose( glm::mat3{ mv } ) } };
auto const tomap{
glm::translate( glm::dmat4{ 1.0 }, -glm::dvec3{ m_localshadows.lamp() } )
glm::translate( glm::dmat4{ 1.0 }, -glm::dvec3{ m_localshadows.cab( static_cast<std::size_t>( slot ) ).lamp } )
* glm::inverse( vehicle->mMatrix )
* glm::translate( glm::dmat4{ 1.0 }, camera - vehicle->GetPosition() )
* toworld };
light.headlight_projection = glm::mat4{ tomap };
light.headlight_weights = m_localshadows.weights();
light.headlight_weights = m_localshadows.weights( static_cast<std::size_t>( slot ) );
}
}
m_cablamplit = ( m_cablamps > 0 );
}
auto const headlightsstart{light_i};
@@ -6274,22 +6279,26 @@ void opengl46_renderer::Render_local_shadows()
{
// only the light buffers with the lamps read the maps
auto const *vehicle{Global.gfx_lights_clustered ? m_locallights.cab_lamp_vehicle() : nullptr};
if (false == m_localshadows.update_wanted(vehicle, (vehicle != nullptr ? vehicle->mdKabina : nullptr), m_locallights.cab_lamp_local(), m_framestamp))
m_localshadows.update_cab(vehicle, (vehicle != nullptr ? vehicle->mdKabina : nullptr), m_locallights.cab_lights(), m_framestamp);
if (m_localshadows.cab_draws().empty())
return;
glDebug("render lamp shadows");
// the cab drawn by the shadow pass, with the programs of the cube map. the camera is put at the vehicle, which Render_cab()
// places the cab relative to, and the modelview takes the cab model to the space of the map
// the cab drawn by the shadow pass to the map of each light, with the programs of the cube map. the camera is put at the vehicle,
// which Render_cab() places the cab relative to, and the modelview takes the cab model to the space of the map
m_renderpass.draw_mode = rendermode::shadows;
m_renderpass.pass_camera.position() = vehicle->GetPosition();
m_renderpass.draw_stats = {};
OpenGLMatrices.mode(GL_MODELVIEW);
OpenGLMatrices.load_matrix(glm::mat4{glm::translate(glm::dmat4{1.0}, -glm::dvec3{m_localshadows.lamp()}) * glm::inverse(vehicle->mMatrix)});
m_localshadows.begin();
m_cubeshadows = true;
Render_cab(vehicle, 0.0f, false);
m_cubeshadows = false;
m_localshadows.end(static_cast<std::uint32_t>(m_renderpass.draw_stats.drawcalls));
for (auto const slot : m_localshadows.cab_draws())
{
m_renderpass.draw_stats = {};
OpenGLMatrices.load_matrix(glm::mat4{glm::translate(glm::dmat4{1.0}, -glm::dvec3{m_localshadows.cab(slot).lamp}) * glm::inverse(vehicle->mMatrix)});
m_localshadows.begin(slot);
m_cubeshadows = true;
Render_cab(vehicle, 0.0f, false);
m_cubeshadows = false;
m_localshadows.end(static_cast<std::uint32_t>(m_renderpass.draw_stats.drawcalls));
}
m_renderpass = m_colorpass;
glPolygonMode(GL_FRONT_AND_BACK, Global.bWireFrame ? GL_LINE : GL_FILL);
}
@@ -6311,15 +6320,16 @@ 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 cab lamp lights the probe when it's a light of the frame
auto const *lamp{(vehicle != nullptr) && (m_locallights.cab_lamp_vehicle() == vehicle) ? m_locallights.cab_lamp() : 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))
return;
glDebug("render cab probe");
// the lamp with its shadow map, when the map holds the shadows of the lamp where it is
auto const shadows{(lamp != nullptr) && m_localshadows.ready(vehicle) && (m_localshadows.lamp() == m_locallights.cab_lamp_local())};
m_cabprobe.setup_drawing(scene_ubs, lamp, m_locallights.cab_lamp_local(), shadows, m_localshadows.weights());
// 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 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

@@ -280,7 +280,7 @@ void opengl46_weather::prepare_view(glm::ivec2 const &Size, quality_level const
m_view_level = Level;
}
void opengl46_weather::render_view(glm::mat4 const &Projection, glm::mat4 const &View, glm::dvec3 const &Camera, glm::ivec2 const &Size, int const Cablamp)
void opengl46_weather::render_view(glm::mat4 const &Projection, glm::mat4 const &View, glm::dvec3 const &Camera, glm::ivec2 const &Size, int const Cablamps)
{
auto const level{gfx::weather_state::quality(Global.gfx_clouds, Global.gfx_fog_quality)};
prepare_view(Size, level);
@@ -353,7 +353,7 @@ void opengl46_weather::render_view(glm::mat4 const &Projection, glm::mat4 const
auto const sunshadows{Global.gfx_fog_shadows && Global.gfx_shadowmap_enabled};
auto const share{temporal ? std::clamp(Global.gfx_fog_temporal_share, 0.02f, 1.f) : 1.f};
glProgramUniform4f(*m_inject_program, 6, share, Global.gfx_fog_lights, sunshadows ? 1.f : 0.f, Global.gfx_fog_shadows ? 1.f : 0.f);
glProgramUniform1i(*m_inject_program, 7, Cablamp);
glProgramUniform1i(*m_inject_program, 7, Cablamps);
glProgramUniform2f(*m_inject_program, 8, previousfog.slicing.x, previousfog.slicing.z);
glProgramUniform2f(*m_inject_program, 9, jitter.x, jitter.y);
m_inject_program->dispatch(groups(m_fog_grid.x), groups(m_fog_grid.y), static_cast<GLuint>(m_fog_grid.z));

View File

@@ -52,9 +52,9 @@ class opengl46_weather
// moon, Keycolor: its colour as the shading gets it, Ambient: the ambient light of the sky, Fogcolor: the old colour of the fog
void update(opengl46_sky const &Sky, glm::vec3 const &Keylight, glm::vec3 const &Keycolor, glm::vec3 const &Ambient, glm::vec3 const &Fogcolor, glm::dvec3 const &Camera);
// the clouds and the fog volume of the colour pass of the main view. Projection and View (rotation, world axes to the view)
// of its camera, Size of the target the scene is drawn into, Cablamp the light of the cab lamp (it lights no fog) or -1.
// of its camera, Size of the target the scene is drawn into, Cablamps the number of the lights of the cab (they light no fog), from the light 1 on.
// the light buffer, the light clusters and the shadow map of the pass are bound
void render_view(glm::mat4 const &Projection, glm::mat4 const &View, glm::dvec3 const &Camera, glm::ivec2 const &Size, int const Cablamp);
void render_view(glm::mat4 const &Projection, glm::mat4 const &View, glm::dvec3 const &Camera, glm::ivec2 const &Size, int const Cablamps);
// the fog of a pass: the volume of the main view (after render_view() in the same frame), or along the ray
void setup_pass(bool const Volume, glm::ivec2 const &Size);
// the stars, in the sky pass. View: rotation of the camera of the pass