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

feat(gl46): leave out instance buckets beyond their range before the culling

This commit is contained in:
2026-10-20 14:57:30 +02:00
parent 07ac7406a0
commit dfbe8a6d9e
7 changed files with 70 additions and 1 deletions

View File

@@ -1103,6 +1103,7 @@ void opengl46_renderer::draw_debug_ui()
ImGui::Checkbox("the same for the scenery of the shadow maps of lamps, when it's drawn next (gfx.gpucull.shadows.lamps)", &Global.gfx_gpucull_shadows_lamps);
ImGui::Checkbox("the same for the sleepers of the tracks of the view (gfx.gpucull.sleepers)", &Global.gfx_gpucull_sleepers);
ImGui::Checkbox("the same for the models drawn on their own, with lights, animations or skins of their own (gfx.gpucull.models)", &Global.gfx_gpucull_models);
ImGui::Checkbox("leave out the models of a cell lying wholly beyond their range before the culling (gfx.gpucull.bucketrange)", &Global.gfx_gpucull_bucketrange);
}
ImGui::Checkbox("draw the depth of the whole scene before its colour (gfx.depthprepass.scene)", &Global.gfx_depthprepass_scene);
if (Global.gfx_contactshadows > 0)
@@ -3954,6 +3955,12 @@ void opengl46_renderer::Queue_Instances( scene::basic_cell const *Cell )
auto const distancelimit { slack * ( reflections ? sq( static_cast<double>( Global.reflectiontune.range_instances ) ) : sq( static_cast<double>( m_renderpass.draw_range ) + 250.0 ) ) };
// up close the rounding of the records is too large a part of the distance for the slack to cover it
auto const distancetested { sq( 64.0 ) };
// the nearest point of the cell, measured as the tests below and the gpu culling measure the instances: a bucket whose range
// ends before it has none of its instances drawn, and is left out of the pass before the culling. basic_cell::enclose_area
// keeps the locations of all instances of the cell within the radius of its area
auto const cellnearest { std::max( 0.0, glm::length( Cell->m_area.center - cameraposition ) - static_cast<double>( Cell->m_area.radius ) ) };
auto const cellscaledsquared { cellnearest * cellnearest * distancescale + distanceoffset };
auto const bucketrange { Global.gfx_gpucull_bucketrange && userecords && ( cellnearest * cellnearest > distancetested ) };
for( auto const &bucket : Cell->m_instancebuckets_opaque ) {
auto const &instancebucket { bucket.second };
@@ -3961,6 +3968,12 @@ void opengl46_renderer::Queue_Instances( scene::basic_cell const *Cell )
|| ( instancebucket.records.size() != instancebucket.instances.size() ) ) {
Update_Instance_Records( bucket.first.pModel, instancebucket, Cell->m_area.center );
}
if( bucketrange && ( cellscaledsquared >= slack * instancebucket.rangesquared ) ) {
if( m_instancecullpass ) {
m_passcull->skip_bucket( instancebucket );
}
continue;
}
if( m_instancecullpass ) {
// the gpu tests every instance of the bucket, the way Render_Instanced() does. models with nothing to draw in the
// sun shadows are left out of them, as Render_Instanced() leaves them
@@ -4070,6 +4083,8 @@ void opengl46_renderer::Update_Instance_Records( TModel3d const *Model, scene::b
Bucket.records.clear();
Bucket.records.reserve( Bucket.instances.size() );
// the range of the bucket: past it none of its instances is drawn, by its own range or by the submodels of the model
auto rangesquared { 0.f };
for( auto *instance : Bucket.instances ) {
scene::basic_cell::instance_record record;
if( instance != nullptr ) {
@@ -4077,6 +4092,7 @@ void opengl46_renderer::Update_Instance_Records( TModel3d const *Model, scene::b
record.radius = instance->radius();
record.rangesquaredmin = tofloat( instance->m_rangesquaredmin );
record.rangesquaredmax = tofloat( instance->m_rangesquaredmax );
rangesquared = std::max( rangesquared, record.rangesquaredmax );
record.flags =
( instance->visible() ? scene::basic_cell::instance_visible : 0u )
| ( instance->m_instanceable ? scene::basic_cell::instance_instanceable : 0u );
@@ -4088,6 +4104,7 @@ void opengl46_renderer::Update_Instance_Records( TModel3d const *Model, scene::b
// an empty slot keeps its record without flags, and isn't drawn
Bucket.records.emplace_back( record );
}
Bucket.rangesquared = std::min( rangesquared, lodrangesquared );
Bucket.recordsversion = m_instancerecordsversion;
Bucket.gpustale = true;
}