16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-22 19:49:19 +02:00

cab shadows enhancement

This commit is contained in:
tmj-fstate
2019-06-17 00:51:26 +02:00
parent 49e34fa3d8
commit a2426d9c2e
3 changed files with 85 additions and 20 deletions

View File

@@ -362,6 +362,11 @@ global_settings::ConfigParse(cParser &Parser) {
>> shadowtune.depth >> shadowtune.depth
>> shadowtune.distance; >> shadowtune.distance;
} }
else if( token == "gfx.shadows.cab.range" ) {
// shadow render toggle
Parser.getTokens();
Parser >> RenderCabShadowsRange;
}
else if (token == "smoothtraction") else if (token == "smoothtraction")
{ {
// podwójna jasność ambient // podwójna jasność ambient

View File

@@ -108,6 +108,7 @@ struct global_settings {
bool ScaleSpecularValues{ true }; bool ScaleSpecularValues{ true };
bool BasicRenderer{ false }; bool BasicRenderer{ false };
bool RenderShadows{ true }; bool RenderShadows{ true };
int RenderCabShadowsRange{ 0 };
struct shadowtune_t { struct shadowtune_t {
unsigned int map_size{ 2048 }; unsigned int map_size{ 2048 };
float width{ 250.f }; // no longer used float width{ 250.f }; // no longer used

View File

@@ -471,10 +471,10 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
// run shadowmaps pass before color // run shadowmaps pass before color
Timer::subsystem.gfx_shadows.start(); Timer::subsystem.gfx_shadows.start();
Render_pass( rendermode::shadows );
if( false == FreeFlyModeFlag ) { if( false == FreeFlyModeFlag ) {
Render_pass( rendermode::cabshadows ); Render_pass( rendermode::cabshadows );
} }
Render_pass( rendermode::shadows );
Timer::subsystem.gfx_shadows.stop(); Timer::subsystem.gfx_shadows.stop();
m_debugtimestext += "shadows: " + to_string( Timer::subsystem.gfx_shadows.average(), 2 ) + " msec (" + std::to_string( m_cellqueue.size() ) + " sectors)\n"; m_debugtimestext += "shadows: " + to_string( Timer::subsystem.gfx_shadows.average(), 2 ) + " msec (" + std::to_string( m_cellqueue.size() ) + " sectors)\n";
#ifdef EU07_USE_DEBUG_SHADOWMAP #ifdef EU07_USE_DEBUG_SHADOWMAP
@@ -663,7 +663,6 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
// setup // setup
::glEnable( GL_POLYGON_OFFSET_FILL ); // alleviate depth-fighting ::glEnable( GL_POLYGON_OFFSET_FILL ); // alleviate depth-fighting
::glPolygonOffset( 1.f, 1.f ); ::glPolygonOffset( 1.f, 1.f );
::glDisable( GL_CULL_FACE );
::glBindFramebufferEXT( GL_FRAMEBUFFER, m_cabshadowframebuffer ); ::glBindFramebufferEXT( GL_FRAMEBUFFER, m_cabshadowframebuffer );
::glViewport( 0, 0, m_shadowbuffersize / 2, m_shadowbuffersize / 2 ); ::glViewport( 0, 0, m_shadowbuffersize / 2, m_shadowbuffersize / 2 );
@@ -686,6 +685,11 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
#else #else
setup_units( false, false, false ); setup_units( false, false, false );
#endif #endif
::glDisable( GL_CULL_FACE );
if( Global.RenderCabShadowsRange > 0 ) {
Render( simulation::Region );
}
Render_cab( simulation::Train->Dynamic(), 0.f, false ); Render_cab( simulation::Train->Dynamic(), 0.f, false );
Render_cab( simulation::Train->Dynamic(), 0.f, true ); Render_cab( simulation::Train->Dynamic(), 0.f, true );
m_cabshadowpass = m_renderpass; m_cabshadowpass = m_renderpass;
@@ -830,7 +834,7 @@ opengl_renderer::setup_pass( renderpass_config &Config, rendermode const Mode, f
switch( Mode ) { switch( Mode ) {
case rendermode::color: { Config.draw_range = Global.BaseDrawRange; break; } case rendermode::color: { Config.draw_range = Global.BaseDrawRange; break; }
case rendermode::shadows: { Config.draw_range = Global.BaseDrawRange * 0.5f; break; } case rendermode::shadows: { Config.draw_range = Global.BaseDrawRange * 0.5f; break; }
case rendermode::cabshadows: { Config.draw_range = simulation::Train->Occupied()->Dim.L; break; } case rendermode::cabshadows: { Config.draw_range = ( Global.RenderCabShadowsRange > 0 ? clamp( Global.RenderCabShadowsRange, 5, 100 ) : simulation::Train->Occupied()->Dim.L ); break; }
case rendermode::reflections: { Config.draw_range = Global.BaseDrawRange; break; } case rendermode::reflections: { Config.draw_range = Global.BaseDrawRange; break; }
case rendermode::pickcontrols: { Config.draw_range = 50.f; break; } case rendermode::pickcontrols: { Config.draw_range = 50.f; break; }
case rendermode::pickscenery: { Config.draw_range = Global.BaseDrawRange * 0.5f; break; } case rendermode::pickscenery: { Config.draw_range = Global.BaseDrawRange * 0.5f; break; }
@@ -1722,6 +1726,7 @@ opengl_renderer::Render( scene::basic_region *Region ) {
break; break;
} }
case rendermode::shadows: case rendermode::shadows:
case rendermode::cabshadows:
case rendermode::pickscenery: { case rendermode::pickscenery: {
// these render modes don't bother with lights // these render modes don't bother with lights
Render( std::begin( m_sectionqueue ), std::end( m_sectionqueue ) ); Render( std::begin( m_sectionqueue ), std::end( m_sectionqueue ) );
@@ -1752,7 +1757,8 @@ opengl_renderer::Render( section_sequence::iterator First, section_sequence::ite
break; break;
} }
case rendermode::shadows: { case rendermode::shadows:
case rendermode::cabshadows: {
// experimental, for shadows render both back and front faces, to supply back faces of the 'forest strips' // experimental, for shadows render both back and front faces, to supply back faces of the 'forest strips'
::glDisable( GL_CULL_FACE ); ::glDisable( GL_CULL_FACE );
break; } break; }
@@ -1775,6 +1781,7 @@ opengl_renderer::Render( section_sequence::iterator First, section_sequence::ite
case rendermode::color: case rendermode::color:
case rendermode::reflections: case rendermode::reflections:
case rendermode::shadows: case rendermode::shadows:
case rendermode::cabshadows:
case rendermode::pickscenery: { case rendermode::pickscenery: {
if( false == section->m_shapes.empty() ) { if( false == section->m_shapes.empty() ) {
// since all shapes of the section share center point we can optimize out a few calls here // since all shapes of the section share center point we can optimize out a few calls here
@@ -1798,6 +1805,7 @@ opengl_renderer::Render( section_sequence::iterator First, section_sequence::ite
switch( m_renderpass.draw_mode ) { switch( m_renderpass.draw_mode ) {
case rendermode::color: case rendermode::color:
case rendermode::shadows: case rendermode::shadows:
case rendermode::cabshadows:
case rendermode::pickscenery: { case rendermode::pickscenery: {
for( auto &cell : section->m_cells ) { for( auto &cell : section->m_cells ) {
if( ( true == cell.m_active ) if( ( true == cell.m_active )
@@ -1821,7 +1829,8 @@ opengl_renderer::Render( section_sequence::iterator First, section_sequence::ite
} }
switch( m_renderpass.draw_mode ) { switch( m_renderpass.draw_mode ) {
case rendermode::shadows: { case rendermode::shadows:
case rendermode::cabshadows: {
// restore standard face cull mode // restore standard face cull mode
::glEnable( GL_CULL_FACE ); ::glEnable( GL_CULL_FACE );
break; } break; }
@@ -1908,6 +1917,22 @@ opengl_renderer::Render( cell_sequence::iterator First, cell_sequence::iterator
break; break;
} }
case rendermode::cabshadows: {
// since all shapes of the section share center point we can optimize out a few calls here
::glPushMatrix();
auto const originoffset { cell->m_area.center - m_renderpass.camera.position() };
::glTranslated( originoffset.x, originoffset.y, originoffset.z );
// render
// opaque non-instanced shapes
for( auto const &shape : cell->m_shapesopaque ) { Render( shape, false ); }
// NOTE: tracks aren't likely to cast shadows into the cab, so we skip them in this pass
// post-render cleanup
::glPopMatrix();
break;
}
case rendermode::pickscenery: { case rendermode::pickscenery: {
// same procedure like with regular render, but editor-enabled nodes receive custom colour used for picking // same procedure like with regular render, but editor-enabled nodes receive custom colour used for picking
// since all shapes of the section share center point we can optimize out a few calls here // since all shapes of the section share center point we can optimize out a few calls here
@@ -1946,7 +1971,8 @@ opengl_renderer::Render( cell_sequence::iterator First, cell_sequence::iterator
switch( m_renderpass.draw_mode ) { switch( m_renderpass.draw_mode ) {
case rendermode::color: case rendermode::color:
case rendermode::shadows: { case rendermode::shadows:
case rendermode::cabshadows: {
// opaque parts of instanced models // opaque parts of instanced models
for( auto *instance : cell->m_instancesopaque ) { Render( instance ); } for( auto *instance : cell->m_instancesopaque ) { Render( instance ); }
// opaque parts of vehicles // opaque parts of vehicles
@@ -2037,7 +2063,8 @@ opengl_renderer::Render( scene::shape_node const &Shape, bool const Ignorerange
if( false == Ignorerange ) { if( false == Ignorerange ) {
double distancesquared; double distancesquared;
switch( m_renderpass.draw_mode ) { switch( m_renderpass.draw_mode ) {
case rendermode::shadows: { case rendermode::shadows:
case rendermode::cabshadows: {
// 'camera' for the light pass is the light source, but we need to draw what the 'real' camera sees // 'camera' for the light pass is the light source, but we need to draw what the 'real' camera sees
distancesquared = Math3D::SquareMagnitude( ( data.area.center - Global.pCamera.Pos ) / Global.ZoomFactor ) / Global.fDistanceFactor; distancesquared = Math3D::SquareMagnitude( ( data.area.center - Global.pCamera.Pos ) / Global.ZoomFactor ) / Global.fDistanceFactor;
break; break;
@@ -2069,6 +2096,7 @@ opengl_renderer::Render( scene::shape_node const &Shape, bool const Ignorerange
} }
// pick modes are painted with custom colours, and shadow pass doesn't use any // pick modes are painted with custom colours, and shadow pass doesn't use any
case rendermode::shadows: case rendermode::shadows:
case rendermode::cabshadows:
case rendermode::pickscenery: case rendermode::pickscenery:
case rendermode::pickcontrols: case rendermode::pickcontrols:
default: { default: {
@@ -2091,7 +2119,8 @@ opengl_renderer::Render( TAnimModel *Instance ) {
double distancesquared; double distancesquared;
switch( m_renderpass.draw_mode ) { switch( m_renderpass.draw_mode ) {
case rendermode::shadows: { case rendermode::shadows:
case rendermode::cabshadows: {
// 'camera' for the light pass is the light source, but we need to draw what the 'real' camera sees // 'camera' for the light pass is the light source, but we need to draw what the 'real' camera sees
distancesquared = Math3D::SquareMagnitude( ( Instance->location() - Global.pCamera.Pos ) / Global.ZoomFactor ) / Global.fDistanceFactor; distancesquared = Math3D::SquareMagnitude( ( Instance->location() - Global.pCamera.Pos ) / Global.ZoomFactor ) / Global.fDistanceFactor;
break; break;
@@ -2105,6 +2134,11 @@ opengl_renderer::Render( TAnimModel *Instance ) {
|| ( distancesquared >= Instance->m_rangesquaredmax ) ) { || ( distancesquared >= Instance->m_rangesquaredmax ) ) {
return; return;
} }
// crude way to reject early items too far to affect the output (mostly relevant for shadow passes)
auto const drawdistancethreshold{ m_renderpass.draw_range + 250 };
if( distancesquared > drawdistancethreshold * drawdistancethreshold ) {
return;
}
switch( m_renderpass.draw_mode ) { switch( m_renderpass.draw_mode ) {
case rendermode::pickscenery: { case rendermode::pickscenery: {
@@ -2137,17 +2171,23 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) {
if( false == Dynamic->renderme ) { if( false == Dynamic->renderme ) {
return false; return false;
} }
// debug data
++m_debugstats.dynamics;
// setup
TSubModel::iInstance = reinterpret_cast<std::uintptr_t>( Dynamic ); //żeby nie robić cudzych animacji
glm::dvec3 const originoffset = Dynamic->vPosition - m_renderpass.camera.position();
// lod visibility ranges are defined for base (x 1.0) viewing distance. for render we adjust them for actual range multiplier and zoom // lod visibility ranges are defined for base (x 1.0) viewing distance. for render we adjust them for actual range multiplier and zoom
float squaredistance; float squaredistance;
glm::dvec3 const originoffset = Dynamic->vPosition - m_renderpass.camera.position();
switch( m_renderpass.draw_mode ) { switch( m_renderpass.draw_mode ) {
case rendermode::shadows: { case rendermode::shadows: {
squaredistance = glm::length2( glm::vec3{ glm::dvec3{ Dynamic->vPosition - Global.pCamera.Pos } } / Global.ZoomFactor ) / Global.fDistanceFactor; squaredistance = glm::length2( glm::vec3{ glm::dvec3{ Dynamic->vPosition - Global.pCamera.Pos } } / Global.ZoomFactor ) / Global.fDistanceFactor;
if( false == FreeFlyModeFlag ) {
// filter out small details if we're in vehicle cab
squaredistance = std::max( 100.f * 100.f, squaredistance );
}
break;
}
case rendermode::cabshadows: {
squaredistance = glm::length2( glm::vec3{ glm::dvec3{ Dynamic->vPosition - Global.pCamera.Pos } } / Global.ZoomFactor ) / Global.fDistanceFactor;
// filter out small details
squaredistance = std::max( 100.f * 100.f, squaredistance );
break; break;
} }
default: { default: {
@@ -2155,6 +2195,18 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) {
break; break;
} }
} }
// crude way to reject early items too far to affect the output (mostly relevant for shadow passes)
auto const drawdistancethreshold { m_renderpass.draw_range + 250 };
if( squaredistance > drawdistancethreshold * drawdistancethreshold ) {
return false;
}
// debug data
++m_debugstats.dynamics;
// setup
TSubModel::iInstance = reinterpret_cast<std::uintptr_t>( Dynamic ); //żeby nie robić cudzych animacji
Dynamic->ABuLittleUpdate( squaredistance ); // ustawianie zmiennych submodeli dla wspólnego modelu Dynamic->ABuLittleUpdate( squaredistance ); // ustawianie zmiennych submodeli dla wspólnego modelu
::glPushMatrix(); ::glPushMatrix();
@@ -2209,7 +2261,8 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) {
} }
break; break;
} }
case rendermode::shadows: { case rendermode::shadows:
case rendermode::cabshadows: {
if( Dynamic->mdLowPolyInt ) { if( Dynamic->mdLowPolyInt ) {
// low poly interior // low poly interior
// if( FreeFlyModeFlag ? true : !Dynamic->mdKabina || !Dynamic->bDisplayCab ) { // if( FreeFlyModeFlag ? true : !Dynamic->mdKabina || !Dynamic->bDisplayCab ) {
@@ -2757,7 +2810,8 @@ opengl_renderer::Render( scene::basic_cell::path_sequence::const_iterator First,
::glColor3fv( glm::value_ptr( colors::white ) ); ::glColor3fv( glm::value_ptr( colors::white ) );
// setup // setup
switch( m_renderpass.draw_mode ) { switch( m_renderpass.draw_mode ) {
case rendermode::shadows: { case rendermode::shadows:
case rendermode::cabshadows: {
// NOTE: roads-based platforms tend to miss parts of shadows if rendered with either back or front culling // NOTE: roads-based platforms tend to miss parts of shadows if rendered with either back or front culling
::glDisable( GL_CULL_FACE ); ::glDisable( GL_CULL_FACE );
break; break;
@@ -2797,7 +2851,8 @@ opengl_renderer::Render( scene::basic_cell::path_sequence::const_iterator First,
} }
break; break;
} }
case rendermode::shadows: { case rendermode::shadows:
case rendermode::cabshadows: {
if( ( std::abs( track->fTexHeight1 ) < 0.35f ) if( ( std::abs( track->fTexHeight1 ) < 0.35f )
|| ( track->iCategoryFlag != 2 ) ) { || ( track->iCategoryFlag != 2 ) ) {
// shadows are only calculated for high enough roads, typically meaning track platforms // shadows are only calculated for high enough roads, typically meaning track platforms
@@ -2840,7 +2895,8 @@ opengl_renderer::Render( scene::basic_cell::path_sequence::const_iterator First,
} }
break; break;
} }
case rendermode::shadows: { case rendermode::shadows:
case rendermode::cabshadows: {
if( ( std::abs( track->fTexHeight1 ) < 0.35f ) if( ( std::abs( track->fTexHeight1 ) < 0.35f )
|| ( ( track->iCategoryFlag == 1 ) || ( ( track->iCategoryFlag == 1 )
&& ( track->eType != tt_Normal ) ) ) { && ( track->eType != tt_Normal ) ) ) {
@@ -2887,7 +2943,8 @@ opengl_renderer::Render( scene::basic_cell::path_sequence::const_iterator First,
} }
break; break;
} }
case rendermode::shadows: { case rendermode::shadows:
case rendermode::cabshadows: {
if( ( std::abs( track->fTexHeight1 ) < 0.35f ) if( ( std::abs( track->fTexHeight1 ) < 0.35f )
|| ( ( track->iCategoryFlag == 1 ) || ( ( track->iCategoryFlag == 1 )
&& ( track->eType != tt_Normal ) ) ) { && ( track->eType != tt_Normal ) ) ) {
@@ -2907,7 +2964,8 @@ opengl_renderer::Render( scene::basic_cell::path_sequence::const_iterator First,
} }
// post-render reset // post-render reset
switch( m_renderpass.draw_mode ) { switch( m_renderpass.draw_mode ) {
case rendermode::shadows: { case rendermode::shadows:
case rendermode::cabshadows: {
::glEnable( GL_CULL_FACE ); ::glEnable( GL_CULL_FACE );
break; break;
} }
@@ -2926,7 +2984,8 @@ opengl_renderer::Render( TMemCell *Memcell ) {
switch( m_renderpass.draw_mode ) { switch( m_renderpass.draw_mode ) {
case rendermode::color: case rendermode::color:
case rendermode::shadows: { case rendermode::shadows:
case rendermode::cabshadows: {
::gluSphere( m_quadric, 0.35, 4, 2 ); ::gluSphere( m_quadric, 0.35, 4, 2 );
break; break;
} }