diff --git a/Driver.cpp b/Driver.cpp index 8b660a27..16c234fb 100644 --- a/Driver.cpp +++ b/Driver.cpp @@ -4738,7 +4738,7 @@ TController::UpdateSituation(double dt) { if( ( mvControlling->PantRearVolt == 0.0 ) // filter out cases with single _other_ working pantograph so we don't try to raise something we can't && ( ( mvControlling->PantographVoltage == 0.0 ) - || ( mvControlling->EnginePowerSource.CollectorParameters.CollectorsNo > 1 ) ) ) { + || ( mvControlling->EnginePowerSource.CollectorParameters.CollectorsNo > 1 ) ) ) { mvControlling->OperatePantographValve( end::rear, operation_t::enable ); } } @@ -4747,45 +4747,45 @@ TController::UpdateSituation(double dt) { if( ( mvControlling->PantFrontVolt == 0.0 ) // filter out cases with single _other_ working pantograph so we don't try to raise something we can't && ( ( mvControlling->PantographVoltage == 0.0 ) - || ( mvControlling->EnginePowerSource.CollectorParameters.CollectorsNo > 1 ) ) ) { + || ( mvControlling->EnginePowerSource.CollectorParameters.CollectorsNo > 1 ) ) ) { mvControlling->OperatePantographValve( end::front, operation_t::enable ); } } - } - } - } - if( mvOccupied->Vel > 5 ) { - if( fActionTime > 0.0 ) { - if( mvOccupied->AIHintPantstate != 0 ) { - // use suggested pantograph setup - auto const pantographsetup{ mvOccupied->AIHintPantstate }; - mvControlling->OperatePantographValve( - end::front, - ( pantographsetup & ( 1 << 0 ) ? - operation_t::enable : - operation_t::disable ) ); - mvControlling->OperatePantographValve( - end::rear, - ( pantographsetup & ( 1 << 1 ) ? - operation_t::enable : - operation_t::disable ) ); + + if( mvOccupied->Vel > 5 ) { + // opuszczenie przedniego po rozpędzeniu się o ile jest więcej niż jeden + if( mvControlling->EnginePowerSource.CollectorParameters.CollectorsNo > 1 ) { + if( ( iDirection >= 0 ) && ( useregularpantographlayout ) ) // jak jedzie w kierunku sprzęgu 0 + { // poczekać na podniesienie tylnego + if( ( mvControlling->PantFrontVolt != 0.0 ) + && ( mvControlling->PantRearVolt != 0.0 ) ) { // czy jest napięcie zasilające na tylnym? + mvControlling->OperatePantographValve( end::front, operation_t::disable ); // opuszcza od sprzęgu 0 + } + } + else { // poczekać na podniesienie przedniego + if( ( mvControlling->PantRearVolt != 0.0 ) + && ( mvControlling->PantFrontVolt != 0.0 ) ) { // czy jest napięcie zasilające na przednim? + mvControlling->OperatePantographValve( end::rear, operation_t::disable ); // opuszcza od sprzęgu 1 + } + } + } + } + } else { - // opuszczenie przedniego po rozpędzeniu się o ile jest więcej niż jeden - if( mvControlling->EnginePowerSource.CollectorParameters.CollectorsNo > 1 ) { - if( ( iDirection >= 0 ) && ( useregularpantographlayout ) ) // jak jedzie w kierunku sprzęgu 0 - { // poczekać na podniesienie tylnego - if( ( mvControlling->PantFrontVolt != 0.0 ) - && ( mvControlling->PantRearVolt != 0.0 ) ) { // czy jest napięcie zasilające na tylnym? - mvControlling->OperatePantographValve( end::front, operation_t::disable ); // opuszcza od sprzęgu 0 - } - } - else { // poczekać na podniesienie przedniego - if( ( mvControlling->PantRearVolt != 0.0 ) - && ( mvControlling->PantFrontVolt != 0.0 ) ) { // czy jest napięcie zasilające na przednim? - mvControlling->OperatePantographValve( end::rear, operation_t::disable ); // opuszcza od sprzęgu 1 - } - } + // use suggested pantograph setup + if( mvOccupied->Vel > 5 ) { + auto const pantographsetup{ mvOccupied->AIHintPantstate }; + mvControlling->OperatePantographValve( + end::front, + ( pantographsetup & ( 1 << 0 ) ? + operation_t::enable : + operation_t::disable ) ); + mvControlling->OperatePantographValve( + end::rear, + ( pantographsetup & ( 1 << 1 ) ? + operation_t::enable : + operation_t::disable ) ); } } } @@ -4875,18 +4875,20 @@ TController::UpdateSituation(double dt) { if (AIControllFlag) { CheckTimeControllers(); + if( fActionTime > 0.0 ) { // low priority operations // compartment lights - if( mvOccupied->CompartmentLights.start_type == start_t::manual ) { - auto const currentlightstate { mvOccupied->CompartmentLights.is_enabled }; - auto const lightlevel { Global.fLuminance * ConsistShade }; - auto const desiredlightstate { ( - currentlightstate ? - lightlevel < 0.40 : // turn off if lighting level goes above 0.4 - lightlevel < 0.35 ) }; // turn on if lighting level goes below 0.35 - if( desiredlightstate != currentlightstate ) { - mvOccupied->CompartmentLightsSwitch( desiredlightstate ); - mvOccupied->CompartmentLightsSwitchOff( !desiredlightstate ); + if( mvOccupied->CompartmentLights.start_type == start_t::manual ) { + auto const currentlightstate{ mvOccupied->CompartmentLights.is_enabled }; + auto const lightlevel{ Global.fLuminance * ConsistShade }; + auto const desiredlightstate{ ( + currentlightstate ? + lightlevel < 0.40 : // turn off if lighting level goes above 0.4 + lightlevel < 0.35 ) }; // turn on if lighting level goes below 0.35 + if( desiredlightstate != currentlightstate ) { + mvOccupied->CompartmentLightsSwitch( desiredlightstate ); + mvOccupied->CompartmentLightsSwitchOff( !desiredlightstate ); + } } } } diff --git a/Driver.h b/Driver.h index c3349d8c..1396d2b6 100644 --- a/Driver.h +++ b/Driver.h @@ -454,6 +454,7 @@ private: // returns true if any vehicle in the consist has an open door bool doors_open() const; void AutoRewident(); // ustawia hamulce w składzie + void UpdatePantographs(); // members double fLength = 0.0; // długość składu (do wyciągania z ograniczeń) double fMass = 0.0; // całkowita masa do liczenia stycznej składowej grawitacji diff --git a/DynObj.cpp b/DynObj.cpp index ff28fd81..b3521ea8 100644 --- a/DynObj.cpp +++ b/DynObj.cpp @@ -2194,7 +2194,7 @@ TDynamicObject::init_sections( TModel3d const *Model, std::string const &Namepre if( sectionsubmodel != nullptr ) { // HACK: disable automatic self-illumination threshold, at least until 3d model update if( Overrideselfillum ) { - sectionsubmodel->SetSelfIllum( 2.0f, true, true ); + sectionsubmodel->SetSelfIllum( 2.0f, true, false ); } Sections.push_back( { sectionsubmodel, @@ -2615,7 +2615,7 @@ TDynamicObject::update_load_sections() { SectionLoadVisibility.push_back( { section.load, false } ); // HACK: disable automatic self-illumination threshold, at least until 3d model update if( MoverParameters->CompartmentLights.start_type == start_t::manual ) { - section.load->SetSelfIllum( 2.0f, true, true ); + section.load->SetSelfIllum( 2.0f, true, false ); } } } @@ -3696,9 +3696,9 @@ bool TDynamicObject::Update(double dt, double dt1) // compartment lights // if the vehicle has a controller, we base the light state on state of the controller otherwise we check the vehicle itself - if( ( ctOwner != nullptr ? - ctOwner->Controlling()->Battery != SectionLightsActive : - MoverParameters->CompartmentLights.is_active == true ) ) { // without controller lights are off. NOTE: this likely mess up the EMU + if( ( ctOwner != nullptr ? ctOwner->Controlling()->Battery != SectionLightsActive : + Mechanik != nullptr ? Mechanik->primary() == false : // don't touch lights in a stand-alone manned vehicle + MoverParameters->CompartmentLights.is_active == true ) ) { // without controller switch the lights off toggle_lights(); } diff --git a/Globals.cpp b/Globals.cpp index 36805f86..ec5742b7 100644 --- a/Globals.cpp +++ b/Globals.cpp @@ -648,10 +648,11 @@ global_settings::ConfigParse(cParser &Parser) { // old variable, repurposed as update rate of python screen renderer Parser.getTokens(); Parser >> token; - auto const priority { ToLower( token ) }; + auto const priority { token }; PythonScreenUpdateRate = ( priority == "lower" ? 500 : priority == "lowest" ? 1000 : + priority == "off" ? 0 : 200 ); } else if( token == "python.updatetime" ) @@ -805,6 +806,11 @@ global_settings::ConfigParse(cParser &Parser) { else if (token == "rg32f") gfx_postfx_motionblur_format = GL_RG32F; } + else if (token == "gfx.postfx.chromaticaberration.enabled") + { + Parser.getTokens(1); + Parser >> gfx_postfx_chromaticaberration_enabled; + } else if (token == "gfx.format.color") { Parser.getTokens(1); @@ -833,6 +839,11 @@ global_settings::ConfigParse(cParser &Parser) { else if (token == "z32f") gfx_format_depth = GL_DEPTH_COMPONENT32F; } + else if (token == "gfx.skiprendering") + { + Parser.getTokens(1); + Parser >> gfx_skiprendering; + } else if (token == "gfx.skippipeline") { Parser.getTokens(1); @@ -859,6 +870,11 @@ global_settings::ConfigParse(cParser &Parser) { Parser >> gfx_shadergamma; } */ + else if (token == "python.enabled") + { + Parser.getTokens(1); + Parser >> python_enabled; + } else if (token == "python.threadedupload") { Parser.getTokens(1); diff --git a/Globals.h b/Globals.h index e376d595..ee1f77ba 100644 --- a/Globals.h +++ b/Globals.h @@ -195,10 +195,12 @@ struct global_settings { std::string fullscreen_monitor; + bool python_enabled = true; bool python_mipmaps = true; bool python_threadedupload = true; bool python_uploadmain = true; + bool gfx_skiprendering = false; int gfx_framebuffer_width = -1; int gfx_framebuffer_height = -1; int gfx_framebuffer_fidelity = -1; @@ -209,6 +211,7 @@ struct global_settings { GLenum gfx_postfx_motionblur_format = GL_RG16F; GLenum gfx_format_color = GL_RGB16F; GLenum gfx_format_depth = GL_DEPTH_COMPONENT32F; + bool gfx_postfx_chromaticaberration_enabled = true; bool gfx_skippipeline = false; bool gfx_extraeffects = true; bool gfx_shadergamma = false; diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index da8f4e47..b59ce564 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -2281,7 +2281,7 @@ bool TMoverParameters::IncScndCtrl(int CtrlSpeed) { bool OK = false; - if ((IsMainCtrlNoPowerPos()) && (CabActive != 0) && (TrainType == dt_ET42) && (ScndCtrlPos == 0) && (DynamicBrakeFlag)) + if ( ( DynamicBrakeFlag ) && ( TrainType == dt_ET42 ) && ( CabActive != 0 ) && ( IsMainCtrlNoPowerPos() ) && ( ScndCtrlPos == 0 ) ) { OK = DynamicBrakeSwitch(false); } @@ -2291,18 +2291,23 @@ bool TMoverParameters::IncScndCtrl(int CtrlSpeed) { // if (RList[MainCtrlPos].R=0) and (MainCtrlPos>0) and (ScndCtrlPos 1) - { - ScndCtrlPos = ScndCtrlPosNo; // takie chamskie, potem poprawie + else { + if( CtrlSpeed == 1 ) { + ScndCtrlPos++; + } + else if( CtrlSpeed > 1 ) { + ScndCtrlPos = ScndCtrlPosNo; // takie chamskie, potem poprawie + } + OK = true; } - OK = true; } else // nie mozna zmienic OK = false; diff --git a/PyInt.cpp b/PyInt.cpp index e527a86f..a90e709a 100644 --- a/PyInt.cpp +++ b/PyInt.cpp @@ -247,7 +247,8 @@ void python_taskqueue::exit() { // adds specified task along with provided collection of data to the work queue. returns true on success auto python_taskqueue::insert( task_request const &Task ) -> bool { - if( ( Task.renderer.empty() ) + if( ( false == Global.python_enabled ) + || ( Task.renderer.empty() ) || ( Task.input == nullptr ) || ( Task.target == 0 ) ) { return false; } diff --git a/Train.cpp b/Train.cpp index e153da9b..51c5fc51 100644 --- a/Train.cpp +++ b/Train.cpp @@ -986,16 +986,33 @@ void TTrain::OnCommand_mastercontrollerset( TTrain *Train, command_data const &C void TTrain::OnCommand_secondcontrollerincrease( TTrain *Train, command_data const &Command ) { - if( Command.action != GLFW_RELEASE ) { - // on press or hold - if( ( Train->mvControlled->EngineType == TEngineType::DieselElectric ) - && ( true == Train->mvControlled->ShuntMode ) ) { + if( ( Train->mvControlled->EngineType == TEngineType::DieselElectric ) + && ( true == Train->mvControlled->ShuntModeAllow ) + && ( true == Train->mvControlled->ShuntMode ) ) { + if( Command.action != GLFW_RELEASE ) { Train->mvControlled->AnPos = clamp( Train->mvControlled->AnPos + 0.025, 0.0, 1.0 ); } + } + else { + if( Train->ggScndCtrl.type() == TGaugeType::push ) { + // two-state control, active while the button is down + if( Command.action == GLFW_PRESS ) { + // activate on press + Train->mvControlled->IncScndCtrl( 1 ); + } + else if( Command.action == GLFW_RELEASE ) { + // zero on release + Train->mvControlled->DecScndCtrl( 2 ); + } + } else { - Train->mvControlled->IncScndCtrl( 1 ); + // multi-state control + if( Command.action != GLFW_RELEASE ) { + // on press or hold + Train->mvControlled->IncScndCtrl( 1 ); + } } } } @@ -5521,30 +5538,22 @@ void TTrain::OnCommand_whistleactivate( TTrain *Train, command_data const &Comma void TTrain::OnCommand_radiotoggle( TTrain *Train, command_data const &Command ) { - if( Train->ggRadioButton.SubModel == nullptr ) { - if( Command.action == GLFW_PRESS ) { - WriteLog( "Radio switch is missing, or wasn't defined" ); - } -/* - // NOTE: we ignore the lack of 3d model to allow system reset after receiving radio-stop signal - return; -*/ - } + if( Command.action != GLFW_PRESS ) { return; } - if( Command.action == GLFW_PRESS ) { - // only reacting to press, so the sound can loop uninterrupted - if( false == Train->mvOccupied->Radio ) { - // turn on - Train->mvOccupied->Radio = true; - // visual feedback - Train->ggRadioButton.UpdateValue( 1.0, Train->dsbSwitch ); - } - else { - // turn off - Train->mvOccupied->Radio = false; - // visual feedback - Train->ggRadioButton.UpdateValue( 0.0, Train->dsbSwitch ); - } + // NOTE: we ignore the lack of 3d model to allow system reset after receiving radio-stop signal +/* + if( false == Train->m_controlmapper.contains( "radio_sw:" ) ) { + return; + } +*/ + // only reacting to press, so the sound can loop uninterrupted + if( false == Train->mvOccupied->Radio ) { + // turn on + Train->mvOccupied->Radio = true; + } + else { + // turn off + Train->mvOccupied->Radio = false; } } @@ -6864,7 +6873,6 @@ bool TTrain::Update( double const Deltatime ) ggFuseButton.Update(); ggConverterFuseButton.Update(); ggStLinOffButton.Update(); - ggRadioButton.Update(); ggRadioChannelSelector.Update(); ggRadioChannelPrevious.Update(); ggRadioChannelNext.Update(); @@ -6996,6 +7004,7 @@ bool TTrain::Update( double const Deltatime ) // screens fScreenTimer += Deltatime; if( ( this == simulation::Train ) // no point in drawing screens for vehicles other than our own + && ( Global.PythonScreenUpdateRate > 0 ) && ( fScreenTimer > Global.PythonScreenUpdateRate * 0.001f ) && ( false == FreeFlyModeFlag ) ) { // don't bother if we're outside fScreenTimer = 0.f; @@ -7883,9 +7892,6 @@ bool TTrain::InitializeCab(int NewCabNo, std::string const &asFileName) if( m_radiosound.offset() == nullvector ) { m_radiosound.offset( btLampkaRadio.model_offset() ); } - if( m_radiosound.offset() == nullvector ) { - m_radiosound.offset( ggRadioButton.model_offset() ); - } if( m_radiostop.offset() == nullvector ) { m_radiostop.offset( m_radiosound.offset() ); } @@ -8259,7 +8265,6 @@ void TTrain::clear_cab_controls() ggFuseButton.Clear(); ggConverterFuseButton.Clear(); ggStLinOffButton.Clear(); - ggRadioButton.Clear(); ggRadioChannelSelector.Clear(); ggRadioChannelPrevious.Clear(); ggRadioChannelNext.Clear(); @@ -8443,9 +8448,6 @@ void TTrain::set_cab_controls( int const Cab ) { 1.f : 0.f ) ); // radio - if( true == mvOccupied->Radio ) { - ggRadioButton.PutValue( 1.f ); - } ggRadioChannelSelector.PutValue( ( Dynamic()->Mechanik ? Dynamic()->Mechanik->iRadioChannel : 1 ) - 1 ); // pantographs /* @@ -8985,7 +8987,6 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con { "motorblowersfront_sw:", ggMotorBlowersFrontButton }, { "motorblowersrear_sw:", ggMotorBlowersRearButton }, { "motorblowersalloff_sw:", ggMotorBlowersAllOffButton }, - { "radio_sw:", ggRadioButton }, { "radiochannel_sw:", ggRadioChannelSelector }, { "radiochannelprev_sw:", ggRadioChannelPrevious }, { "radiochannelnext_sw:", ggRadioChannelNext }, @@ -9081,7 +9082,8 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con { "pantfront_sw:", &mvControlled->Pantographs[end::front].valve.is_enabled }, { "pantrear_sw:", &mvControlled->Pantographs[end::rear].valve.is_enabled }, { "pantfrontoff_sw:", &mvControlled->Pantographs[end::front].valve.is_disabled }, - { "pantrearoff_sw:", &mvControlled->Pantographs[end::rear].valve.is_disabled } + { "pantrearoff_sw:", &mvControlled->Pantographs[end::rear].valve.is_disabled }, + { "radio_sw:", &mvOccupied->Radio }, }; { auto lookup = autoboolgauges.find( Label ); diff --git a/Train.h b/Train.h index 6a1b4cb1..135e1f65 100644 --- a/Train.h +++ b/Train.h @@ -486,7 +486,6 @@ public: // reszta może by?publiczna TGauge ggFuseButton; TGauge ggConverterFuseButton; // hunter-261211: przycisk odblokowania nadmiarowego przetwornic i ogrzewania TGauge ggStLinOffButton; - TGauge ggRadioButton; TGauge ggRadioChannelSelector; TGauge ggRadioChannelPrevious; TGauge ggRadioChannelNext; diff --git a/opengl33renderer.cpp b/opengl33renderer.cpp index 008b1eab..5ef8297a 100644 --- a/opengl33renderer.cpp +++ b/opengl33renderer.cpp @@ -151,6 +151,7 @@ bool opengl33_renderer::Init(GLFWwindow *Window) m_pfx_motionblur = std::make_unique("motionblur"); m_pfx_tonemapping = std::make_unique("tonemapping"); + m_pfx_chromaticaberration = std::make_unique( "chromaticaberration" ); m_empty_cubemap = std::make_unique(); m_empty_cubemap->alloc(Global.gfx_format_color, 16, 16, GL_RGB, GL_FLOAT); @@ -584,7 +585,7 @@ void opengl33_renderer::Render_pass(viewport_config &vp, rendermode const Mode) gl::buffer::unbind(); m_current_viewport = &vp; - if (!simulation::is_ready) + if ((!simulation::is_ready) || (Global.gfx_skiprendering)) { gl::program::unbind(); gl::framebuffer::unbind(); @@ -796,9 +797,14 @@ void opengl33_renderer::Render_pass(viewport_config &vp, rendermode const Mode) if (!Global.gfx_usegles && !Global.gfx_shadergamma) glEnable(GL_FRAMEBUFFER_SRGB); - glViewport(0, 0, target_size.x, target_size.y); + glViewport(0, 0, target_size.x, target_size.y); m_pfx_tonemapping->apply(*vp.main2_tex, nullptr); - opengl_texture::reset_unit_cache(); + + if( Global.gfx_postfx_chromaticaberration_enabled ) { + m_pfx_chromaticaberration->apply( *vp.main2_tex, nullptr ); + } + + opengl_texture::reset_unit_cache(); } if (!Global.gfx_usegles && !Global.gfx_shadergamma) diff --git a/opengl33renderer.h b/opengl33renderer.h index 15649e18..7e2030f4 100644 --- a/opengl33renderer.h +++ b/opengl33renderer.h @@ -363,6 +363,7 @@ class opengl33_renderer : public gfx_renderer { std::unique_ptr m_pfx_motionblur; std::unique_ptr m_pfx_tonemapping; + std::unique_ptr m_pfx_chromaticaberration; std::unique_ptr m_shadow_shader; std::unique_ptr m_alpha_shadow_shader; diff --git a/openglrenderer.cpp b/openglrenderer.cpp index 3bf399dc..a0fd386c 100644 --- a/openglrenderer.cpp +++ b/openglrenderer.cpp @@ -404,9 +404,14 @@ opengl_renderer::Render_pass( rendermode const Mode ) { m_colorpass = m_renderpass; + if( ( !simulation::is_ready ) || ( Global.gfx_skiprendering ) ) { + ::glClearColor( 51.0f / 255.f, 102.0f / 255.f, 85.0f / 255.f, 1.f ); // initial background Color + ::glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + break; + } + if( ( true == Global.RenderShadows ) && ( false == Global.bWireFrame ) - && ( true == simulation::is_ready ) && ( m_shadowcolor != colors::white ) ) { // run shadowmaps pass before color @@ -443,8 +448,7 @@ opengl_renderer::Render_pass( rendermode const Mode ) { } } - if( ( true == m_environmentcubetexturesupport ) - && ( true == simulation::is_ready ) ) { + if( true == m_environmentcubetexturesupport ) { // potentially update environmental cube map m_renderpass.draw_stats = {}; if( true == Render_reflections() ) { @@ -454,110 +458,103 @@ opengl_renderer::Render_pass( rendermode const Mode ) { ::glViewport( 0, 0, Global.iWindowWidth, Global.iWindowHeight ); - if( simulation::is_ready ) { - auto const skydomecolour = simulation::Environment.m_skydome.GetAverageColor(); - ::glClearColor( skydomecolour.x, skydomecolour.y, skydomecolour.z, 0.f ); // kolor nieba - } - else { - ::glClearColor( 51.0f / 255.f, 102.0f / 255.f, 85.0f / 255.f, 1.f ); // initial background Color - } + auto const skydomecolour = simulation::Environment.m_skydome.GetAverageColor(); + ::glClearColor( skydomecolour.x, skydomecolour.y, skydomecolour.z, 0.f ); // kolor nieba ::glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); - if( simulation::is_ready ) { - // setup - setup_matrices(); - // render - setup_drawing( true ); - setup_units( true, false, false ); - m_renderpass.draw_stats = {}; - Render( &simulation::Environment ); - // opaque parts... - setup_drawing( false ); - setup_units( true, true, true ); + // setup + setup_matrices(); + // render + setup_drawing( true ); + setup_units( true, false, false ); + m_renderpass.draw_stats = {}; + Render( &simulation::Environment ); + // opaque parts... + setup_drawing( false ); + setup_units( true, true, true ); #ifdef EU07_USE_DEBUG_CAMERA - if( DebugModeFlag ) { - // draw light frustum - ::glLineWidth( 2.f ); - ::glColor4f( 1.f, 0.9f, 0.8f, 1.f ); - ::glDisable( GL_LIGHTING ); - ::glDisable( GL_TEXTURE_2D ); - if( ( true == Global.RenderShadows ) && ( false == Global.bWireFrame ) ) { - m_shadowpass.camera.draw( m_renderpass.camera.position() - m_shadowpass.camera.position() ); - } - if( DebugCameraFlag ) { - ::glColor4f( 0.8f, 1.f, 0.9f, 1.f ); - m_worldcamera.camera.draw( m_renderpass.camera.position() - m_worldcamera.camera.position() ); - } - ::glLineWidth( 1.f ); - ::glEnable( GL_LIGHTING ); - ::glEnable( GL_TEXTURE_2D ); + if( DebugModeFlag ) { + // draw light frustum + ::glLineWidth( 2.f ); + ::glColor4f( 1.f, 0.9f, 0.8f, 1.f ); + ::glDisable( GL_LIGHTING ); + ::glDisable( GL_TEXTURE_2D ); + if( ( true == Global.RenderShadows ) && ( false == Global.bWireFrame ) ) { + m_shadowpass.camera.draw( m_renderpass.camera.position() - m_shadowpass.camera.position() ); } + if( DebugCameraFlag ) { + ::glColor4f( 0.8f, 1.f, 0.9f, 1.f ); + m_worldcamera.camera.draw( m_renderpass.camera.position() - m_worldcamera.camera.position() ); + } + ::glLineWidth( 1.f ); + ::glEnable( GL_LIGHTING ); + ::glEnable( GL_TEXTURE_2D ); + } #endif - // without rain/snow we can render the cab early to limit the overdraw - if( ( false == FreeFlyModeFlag ) - && ( Global.Overcast <= 1.f ) ) { // precipitation happens when overcast is in 1-2 range + // without rain/snow we can render the cab early to limit the overdraw + if( ( false == FreeFlyModeFlag ) + && ( Global.Overcast <= 1.f ) ) { // precipitation happens when overcast is in 1-2 range #ifdef EU07_DISABLECABREFLECTIONS - switch_units( true, true, false ); + switch_units( true, true, false ); #endif - setup_shadow_map( m_cabshadowtexture, m_cabshadowtexturematrix ); - // cache shadow colour in case we need to account for cab light - auto const shadowcolor { m_shadowcolor }; - auto const *vehicle{ simulation::Train->Dynamic() }; - if( vehicle->InteriorLightLevel > 0.f ) { - setup_shadow_color( glm::min( colors::white, shadowcolor + glm::vec4( vehicle->InteriorLight * vehicle->InteriorLightLevel, 1.f ) ) ); - } + setup_shadow_map( m_cabshadowtexture, m_cabshadowtexturematrix ); + // cache shadow colour in case we need to account for cab light + auto const shadowcolor { m_shadowcolor }; + auto const *vehicle{ simulation::Train->Dynamic() }; + if( vehicle->InteriorLightLevel > 0.f ) { + setup_shadow_color( glm::min( colors::white, shadowcolor + glm::vec4( vehicle->InteriorLight * vehicle->InteriorLightLevel, 1.f ) ) ); + } + Render_cab( vehicle, vehicle->InteriorLightLevel, false ); + if( vehicle->InteriorLightLevel > 0.f ) { + setup_shadow_color( shadowcolor ); + } + } + switch_units( true, true, true ); + setup_shadow_map( m_shadowtexture, m_shadowtexturematrix ); + Render( simulation::Region ); + // ...translucent parts + setup_drawing( true ); + Render_Alpha( simulation::Region ); + // particles + Render_particles(); + // precipitation; done at the end, only before cab render + Render_precipitation(); + // cab render + if( false == FreeFlyModeFlag ) { +#ifdef EU07_DISABLECABREFLECTIONS + switch_units( true, true, false ); +#endif + setup_shadow_map( m_cabshadowtexture, m_cabshadowtexturematrix ); + // cache shadow colour in case we need to account for cab light + auto const shadowcolor{ m_shadowcolor }; + auto *vehicle { simulation::Train->Dynamic() }; + if( vehicle->InteriorLightLevel > 0.f ) { + setup_shadow_color( glm::min( colors::white, shadowcolor + glm::vec4( vehicle->InteriorLight * vehicle->InteriorLightLevel, 1.f ) ) ); + } + if( Global.Overcast > 1.f ) { + // with active precipitation draw the opaque cab parts here to mask rain/snow placed 'inside' the cab + setup_drawing( false ); Render_cab( vehicle, vehicle->InteriorLightLevel, false ); - if( vehicle->InteriorLightLevel > 0.f ) { - setup_shadow_color( shadowcolor ); - } + Render_interior( false); + setup_drawing( true ); + Render_interior( true ); } - switch_units( true, true, true ); - setup_shadow_map( m_shadowtexture, m_shadowtexturematrix ); - Render( simulation::Region ); - // ...translucent parts - setup_drawing( true ); - Render_Alpha( simulation::Region ); - // particles - Render_particles(); - // precipitation; done at the end, only before cab render - Render_precipitation(); - // cab render - if( false == FreeFlyModeFlag ) { -#ifdef EU07_DISABLECABREFLECTIONS - switch_units( true, true, false ); -#endif - setup_shadow_map( m_cabshadowtexture, m_cabshadowtexturematrix ); - // cache shadow colour in case we need to account for cab light - auto const shadowcolor{ m_shadowcolor }; - auto *vehicle { simulation::Train->Dynamic() }; - if( vehicle->InteriorLightLevel > 0.f ) { - setup_shadow_color( glm::min( colors::white, shadowcolor + glm::vec4( vehicle->InteriorLight * vehicle->InteriorLightLevel, 1.f ) ) ); - } - if( Global.Overcast > 1.f ) { - // with active precipitation draw the opaque cab parts here to mask rain/snow placed 'inside' the cab - setup_drawing( false ); - Render_cab( vehicle, vehicle->InteriorLightLevel, false ); - Render_interior( false); - setup_drawing( true ); - Render_interior( true ); - } - Render_cab( vehicle, vehicle->InteriorLightLevel, true ); - if( vehicle->InteriorLightLevel > 0.f ) { - setup_shadow_color( shadowcolor ); - } - // with the cab in place we can (finally) safely draw translucent part of the occupied vehicle - Render_Alpha( vehicle ); + Render_cab( vehicle, vehicle->InteriorLightLevel, true ); + if( vehicle->InteriorLightLevel > 0.f ) { + setup_shadow_color( shadowcolor ); } + // with the cab in place we can (finally) safely draw translucent part of the occupied vehicle + Render_Alpha( vehicle ); + } - if( m_environmentcubetexturesupport ) { - // restore default texture matrix for reflections cube map - select_unit( m_helpertextureunit ); - ::glMatrixMode( GL_TEXTURE ); -// ::glPopMatrix(); - ::glLoadIdentity(); - select_unit( m_diffusetextureunit ); - ::glMatrixMode( GL_MODELVIEW ); - } + if( m_environmentcubetexturesupport ) { + // restore default texture matrix for reflections cube map + select_unit( m_helpertextureunit ); + ::glMatrixMode( GL_TEXTURE ); +// ::glPopMatrix(); + ::glLoadIdentity(); + select_unit( m_diffusetextureunit ); + ::glMatrixMode( GL_MODELVIEW ); } // store draw stats m_colorpass.draw_stats = m_renderpass.draw_stats; diff --git a/shaders/postfx_chromaticaberration.frag b/shaders/postfx_chromaticaberration.frag new file mode 100644 index 00000000..c7f98d18 --- /dev/null +++ b/shaders/postfx_chromaticaberration.frag @@ -0,0 +1,21 @@ +in vec2 f_coords; + +layout(location = 0) out vec4 out_color; + +#texture (color_tex, 0, RGB) +uniform sampler2D iChannel0; + +void main() +{ + float amount = 0.001; + + vec2 uv = f_coords; + vec3 col; + col.r = texture( iChannel0, vec2(uv.x+amount,uv.y) ).r; + col.g = texture( iChannel0, uv ).g; + col.b = texture( iChannel0, vec2(uv.x-amount,uv.y) ).b; + + col *= (1.0 - amount * 0.5); + + out_color = vec4(col,1.0); +}