mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-22 19:49:19 +02:00
gfx renderers standardization, bug fixes
This commit is contained in:
11
Globals.cpp
11
Globals.cpp
@@ -77,6 +77,7 @@ global_settings::ConfigParse(cParser &Parser) {
|
|||||||
{
|
{
|
||||||
Parser.getTokens(1, false);
|
Parser.getTokens(1, false);
|
||||||
Parser >> fDistanceFactor;
|
Parser >> fDistanceFactor;
|
||||||
|
fDistanceFactor = clamp( fDistanceFactor, 250.f, 10000.f ); // arbitrary limits to keep users from hurting themselves
|
||||||
}
|
}
|
||||||
else if (token == "targetfps")
|
else if (token == "targetfps")
|
||||||
{
|
{
|
||||||
@@ -93,6 +94,11 @@ global_settings::ConfigParse(cParser &Parser) {
|
|||||||
Parser.getTokens();
|
Parser.getTokens();
|
||||||
Parser >> bFullScreen;
|
Parser >> bFullScreen;
|
||||||
}
|
}
|
||||||
|
else if (token == "fullscreenmonitor")
|
||||||
|
{
|
||||||
|
Parser.getTokens(1, false);
|
||||||
|
Parser >> fullscreen_monitor;
|
||||||
|
}
|
||||||
else if( token == "vsync" ) {
|
else if( token == "vsync" ) {
|
||||||
|
|
||||||
Parser.getTokens();
|
Parser.getTokens();
|
||||||
@@ -734,6 +740,11 @@ global_settings::ConfigParse(cParser &Parser) {
|
|||||||
Parser.getTokens(1, false);
|
Parser.getTokens(1, false);
|
||||||
Parser >> gfx_framebuffer_height;
|
Parser >> gfx_framebuffer_height;
|
||||||
}
|
}
|
||||||
|
else if (token == "gfx.framebuffer.fidelity")
|
||||||
|
{
|
||||||
|
Parser.getTokens(1, false);
|
||||||
|
Parser >> gfx_framebuffer_fidelity;
|
||||||
|
}
|
||||||
else if (token == "gfx.shadowmap.enabled")
|
else if (token == "gfx.shadowmap.enabled")
|
||||||
{
|
{
|
||||||
Parser.getTokens(1);
|
Parser.getTokens(1);
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ struct global_settings {
|
|||||||
bool bLiveTraction{ true };
|
bool bLiveTraction{ true };
|
||||||
float Overcast{ 0.1f }; // NOTE: all this weather stuff should be moved elsewhere
|
float Overcast{ 0.1f }; // NOTE: all this weather stuff should be moved elsewhere
|
||||||
glm::vec3 FogColor = { 0.6f, 0.7f, 0.8f };
|
glm::vec3 FogColor = { 0.6f, 0.7f, 0.8f };
|
||||||
double fFogEnd{ 2000 };
|
double fFogEnd{ 7500 };
|
||||||
std::string Season{}; // season of the year, based on simulation date
|
std::string Season{}; // season of the year, based on simulation date
|
||||||
std::string Weather{ "cloudy:" }; // current weather
|
std::string Weather{ "cloudy:" }; // current weather
|
||||||
bool FullPhysics{ true }; // full calculations performed for each simulation step
|
bool FullPhysics{ true }; // full calculations performed for each simulation step
|
||||||
@@ -187,6 +187,7 @@ struct global_settings {
|
|||||||
bool render_cab = true;
|
bool render_cab = true;
|
||||||
int gfx_framebuffer_width = -1;
|
int gfx_framebuffer_width = -1;
|
||||||
int gfx_framebuffer_height = -1;
|
int gfx_framebuffer_height = -1;
|
||||||
|
int gfx_framebuffer_fidelity = -1;
|
||||||
bool gfx_shadowmap_enabled = true;
|
bool gfx_shadowmap_enabled = true;
|
||||||
bool gfx_envmap_enabled = true;
|
bool gfx_envmap_enabled = true;
|
||||||
bool gfx_postfx_motionblur_enabled = true;
|
bool gfx_postfx_motionblur_enabled = true;
|
||||||
@@ -198,6 +199,7 @@ struct global_settings {
|
|||||||
bool gfx_extraeffects = true;
|
bool gfx_extraeffects = true;
|
||||||
bool gfx_shadergamma = false;
|
bool gfx_shadergamma = false;
|
||||||
bool gfx_usegles = false;
|
bool gfx_usegles = false;
|
||||||
|
std::string fullscreen_monitor;
|
||||||
bool python_mipmaps = true;
|
bool python_mipmaps = true;
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
|
|||||||
@@ -160,7 +160,8 @@ auto python_taskqueue::insert( task_request const &Task ) -> bool {
|
|||||||
|
|
||||||
if( ( Task.renderer.empty() )
|
if( ( Task.renderer.empty() )
|
||||||
|| ( Task.input == nullptr )
|
|| ( Task.input == nullptr )
|
||||||
|| ( Task.target == 0 ) ) { return false; }
|
|| ( Task.target == 0 )
|
||||||
|
|| ( Task.target == (GLuint)-1 ) ) { return false; }
|
||||||
|
|
||||||
auto *renderer { fetch_renderer( Task.renderer ) };
|
auto *renderer { fetch_renderer( Task.renderer ) };
|
||||||
if( renderer == nullptr ) { return false; }
|
if( renderer == nullptr ) { return false; }
|
||||||
|
|||||||
@@ -316,7 +316,7 @@ eu07_application::on_scroll( double const Xoffset, double const Yoffset ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GLFWwindow *
|
GLFWwindow *
|
||||||
eu07_application::window( int const Windowindex ) {
|
eu07_application::window(int const Windowindex, bool visible, int width, int height, GLFWmonitor *monitor, bool keep_ownership , bool share_ctx) {
|
||||||
|
|
||||||
if( Windowindex >= 0 ) {
|
if( Windowindex >= 0 ) {
|
||||||
return (
|
return (
|
||||||
@@ -325,15 +325,51 @@ eu07_application::window( int const Windowindex ) {
|
|||||||
nullptr );
|
nullptr );
|
||||||
}
|
}
|
||||||
// for index -1 create a new child window
|
// for index -1 create a new child window
|
||||||
glfwWindowHint( GLFW_VISIBLE, GL_FALSE );
|
|
||||||
auto *childwindow = glfwCreateWindow( 1, 1, "eu07helper", nullptr, m_windows.front() );
|
auto const *vmode { glfwGetVideoMode( monitor ? monitor : glfwGetPrimaryMonitor() ) };
|
||||||
if( childwindow != nullptr ) {
|
|
||||||
|
glfwWindowHint( GLFW_RED_BITS, vmode->redBits );
|
||||||
|
glfwWindowHint( GLFW_GREEN_BITS, vmode->greenBits );
|
||||||
|
glfwWindowHint( GLFW_BLUE_BITS, vmode->blueBits );
|
||||||
|
glfwWindowHint( GLFW_REFRESH_RATE, vmode->refreshRate );
|
||||||
|
|
||||||
|
glfwWindowHint( GLFW_VISIBLE, visible );
|
||||||
|
|
||||||
|
auto *childwindow = glfwCreateWindow( width, height, "eu07window", monitor,
|
||||||
|
share_ctx ? m_windows.front() : nullptr);
|
||||||
|
if (!childwindow)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (keep_ownership)
|
||||||
m_windows.emplace_back( childwindow );
|
m_windows.emplace_back( childwindow );
|
||||||
}
|
|
||||||
|
glfwFocusWindow(m_windows.front()); // restore focus to main window
|
||||||
|
|
||||||
return childwindow;
|
return childwindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
// private:
|
// private:
|
||||||
|
GLFWmonitor* eu07_application::find_monitor(const std::string &str) const {
|
||||||
|
int monitor_count;
|
||||||
|
GLFWmonitor **monitors = glfwGetMonitors(&monitor_count);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < monitor_count; i++) {
|
||||||
|
if (describe_monitor(monitors[i]) == str)
|
||||||
|
return monitors[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string eu07_application::describe_monitor(GLFWmonitor *monitor) const {
|
||||||
|
std::string name(glfwGetMonitorName(monitor));
|
||||||
|
std::replace(std::begin(name), std::end(name), ' ', '_');
|
||||||
|
|
||||||
|
int x, y;
|
||||||
|
glfwGetMonitorPos(monitor, &x, &y);
|
||||||
|
|
||||||
|
return name + ":" + std::to_string(x) + "," + std::to_string(y);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
eu07_application::init_debug() {
|
eu07_application::init_debug() {
|
||||||
@@ -342,12 +378,10 @@ eu07_application::init_debug() {
|
|||||||
// memory leaks
|
// memory leaks
|
||||||
_CrtSetDbgFlag( _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG ) | _CRTDBG_LEAK_CHECK_DF );
|
_CrtSetDbgFlag( _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG ) | _CRTDBG_LEAK_CHECK_DF );
|
||||||
// floating point operation errors
|
// floating point operation errors
|
||||||
/*
|
|
||||||
auto state { _clearfp() };
|
auto state { _clearfp() };
|
||||||
state = _control87( 0, 0 );
|
state = _control87( 0, 0 );
|
||||||
// this will turn on FPE for #IND and zerodiv
|
// this will turn on FPE for #IND and zerodiv
|
||||||
state = _control87( state & ~( _EM_ZERODIVIDE | _EM_INVALID ), _MCW_EM );
|
state = _control87( state & ~( _EM_ZERODIVIDE | _EM_INVALID ), _MCW_EM );
|
||||||
*/
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
::SetUnhandledExceptionFilter( unhandled_handler );
|
::SetUnhandledExceptionFilter( unhandled_handler );
|
||||||
@@ -462,13 +496,19 @@ eu07_application::init_glfw() {
|
|||||||
}
|
}
|
||||||
// match requested video mode to current to allow for
|
// match requested video mode to current to allow for
|
||||||
// fullwindow creation when resolution is the same
|
// fullwindow creation when resolution is the same
|
||||||
auto *monitor { glfwGetPrimaryMonitor() };
|
{
|
||||||
auto const *vmode { glfwGetVideoMode( monitor ) };
|
int monitor_count;
|
||||||
|
GLFWmonitor **monitors = glfwGetMonitors(&monitor_count);
|
||||||
|
|
||||||
glfwWindowHint( GLFW_RED_BITS, vmode->redBits );
|
WriteLog("available monitors:");
|
||||||
glfwWindowHint( GLFW_GREEN_BITS, vmode->greenBits );
|
for (size_t i = 0; i < monitor_count; i++) {
|
||||||
glfwWindowHint( GLFW_BLUE_BITS, vmode->blueBits );
|
WriteLog(describe_monitor(monitors[i]));
|
||||||
glfwWindowHint( GLFW_REFRESH_RATE, vmode->refreshRate );
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto *monitor { find_monitor(Global.fullscreen_monitor) };
|
||||||
|
if (!monitor)
|
||||||
|
monitor = glfwGetPrimaryMonitor();
|
||||||
|
|
||||||
glfwWindowHint( GLFW_AUTO_ICONIFY, GLFW_FALSE );
|
glfwWindowHint( GLFW_AUTO_ICONIFY, GLFW_FALSE );
|
||||||
if( Global.iMultisampling > 0 ) {
|
if( Global.iMultisampling > 0 ) {
|
||||||
@@ -494,40 +534,24 @@ eu07_application::init_glfw() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glfwWindowHint( GLFW_AUTO_ICONIFY, GLFW_FALSE );
|
auto *mainwindow = window(
|
||||||
|
-1, true, Global.iWindowWidth, Global.iWindowHeight, Global.bFullScreen ? monitor : nullptr, true, false );
|
||||||
|
|
||||||
if( Global.bFullScreen ) {
|
if( mainwindow == nullptr ) {
|
||||||
// match screen dimensions with selected monitor, for 'borderless window' in fullscreen mode
|
|
||||||
Global.iWindowWidth = vmode->width;
|
|
||||||
Global.iWindowHeight = vmode->height;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto *window {
|
|
||||||
glfwCreateWindow(
|
|
||||||
Global.iWindowWidth,
|
|
||||||
Global.iWindowHeight,
|
|
||||||
Global.AppName.c_str(),
|
|
||||||
( Global.bFullScreen ?
|
|
||||||
monitor :
|
|
||||||
nullptr ),
|
|
||||||
nullptr ) };
|
|
||||||
|
|
||||||
if( window == nullptr ) {
|
|
||||||
ErrorLog( "Bad init: failed to create glfw window" );
|
ErrorLog( "Bad init: failed to create glfw window" );
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
glfwMakeContextCurrent( window );
|
glfwMakeContextCurrent( mainwindow );
|
||||||
glfwSwapInterval( Global.VSync ? 1 : 0 ); //vsync
|
glfwSwapInterval( Global.VSync ? 1 : 0 ); //vsync
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// setup wrapper for base glfw window proc, to handle copydata messages
|
// setup wrapper for base glfw window proc, to handle copydata messages
|
||||||
Hwnd = glfwGetWin32Window( window );
|
Hwnd = glfwGetWin32Window( mainwindow );
|
||||||
BaseWindowProc = ( WNDPROC )::SetWindowLongPtr( Hwnd, GWLP_WNDPROC, (LONG_PTR)WndProc );
|
BaseWindowProc = ( WNDPROC )::SetWindowLongPtr( Hwnd, GWLP_WNDPROC, (LONG_PTR)WndProc );
|
||||||
// switch off the topmost flag
|
// switch off the topmost flag
|
||||||
::SetWindowPos( Hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
|
::SetWindowPos( Hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
|
||||||
#endif
|
#endif
|
||||||
m_windows.emplace_back( window );
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ public:
|
|||||||
on_scroll( double const Xoffset, double const Yoffset );
|
on_scroll( double const Xoffset, double const Yoffset );
|
||||||
// gives access to specified window, creates a new window if index == -1
|
// gives access to specified window, creates a new window if index == -1
|
||||||
GLFWwindow *
|
GLFWwindow *
|
||||||
window( int const Windowindex = 0 );
|
window( int const Windowindex = 0, bool visible = false, int width = 1, int height = 1, GLFWmonitor *monitor = nullptr, bool keep_ownership = true, bool share_ctx = true );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// types
|
// types
|
||||||
@@ -88,6 +88,8 @@ private:
|
|||||||
int init_audio();
|
int init_audio();
|
||||||
int init_data();
|
int init_data();
|
||||||
int init_modes();
|
int init_modes();
|
||||||
|
GLFWmonitor * find_monitor( const std::string &str ) const;
|
||||||
|
std::string describe_monitor( GLFWmonitor *monitor ) const;
|
||||||
// members
|
// members
|
||||||
modeptr_array m_modes { nullptr }; // collection of available application behaviour modes
|
modeptr_array m_modes { nullptr }; // collection of available application behaviour modes
|
||||||
mode_stack m_modestack; // current behaviour mode
|
mode_stack m_modestack; // current behaviour mode
|
||||||
|
|||||||
2
color.h
2
color.h
@@ -4,7 +4,7 @@ namespace colors {
|
|||||||
|
|
||||||
glm::vec4 const none{ 0.f, 0.f, 0.f, 1.f };
|
glm::vec4 const none{ 0.f, 0.f, 0.f, 1.f };
|
||||||
glm::vec4 const white{ 1.f, 1.f, 1.f, 1.f };
|
glm::vec4 const white{ 1.f, 1.f, 1.f, 1.f };
|
||||||
glm::vec4 const shadow{ 0.65f, 0.65f, 0.65f, 1.f };
|
glm::vec4 const shadow{ 0.6f, 0.6f, 0.6f, 1.f };
|
||||||
|
|
||||||
inline
|
inline
|
||||||
glm::vec3
|
glm::vec3
|
||||||
|
|||||||
@@ -1092,7 +1092,7 @@ debug_panel::update_section_renderer( std::vector<text_line> &Output ) {
|
|||||||
// gfx renderer data
|
// gfx renderer data
|
||||||
auto textline =
|
auto textline =
|
||||||
"FoV: " + to_string( Global.FieldOfView / Global.ZoomFactor, 1 )
|
"FoV: " + to_string( Global.FieldOfView / Global.ZoomFactor, 1 )
|
||||||
+ ", Draw range x " + to_string( Global.fDistanceFactor, 1 )
|
+ ", Draw range: " + to_string( Global.BaseDrawRange * Global.fDistanceFactor, 0 ) + "m"
|
||||||
// + "; sectors: " + std::to_string( GfxRenderer->m_drawcount )
|
// + "; sectors: " + std::to_string( GfxRenderer->m_drawcount )
|
||||||
// + ", FPS: " + to_string( Timer::GetFPS(), 2 );
|
// + ", FPS: " + to_string( Timer::GetFPS(), 2 );
|
||||||
+ ", FPS: " + std::to_string( static_cast<int>(std::round(GfxRenderer->Framerate())) );
|
+ ", FPS: " + std::to_string( static_cast<int>(std::round(GfxRenderer->Framerate())) );
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ void gl::glsl_common_setup()
|
|||||||
float emission;
|
float emission;
|
||||||
float fog_density;
|
float fog_density;
|
||||||
float alpha_mult;
|
float alpha_mult;
|
||||||
|
float shadow_tone;
|
||||||
};
|
};
|
||||||
|
|
||||||
layout (std140) uniform scene_ubo
|
layout (std140) uniform scene_ubo
|
||||||
|
|||||||
3
gl/ubo.h
3
gl/ubo.h
@@ -56,6 +56,7 @@ namespace gl
|
|||||||
float emission;
|
float emission;
|
||||||
float fog_density;
|
float fog_density;
|
||||||
float alpha_mult;
|
float alpha_mult;
|
||||||
|
float shadow_tone;
|
||||||
UBS_PAD(4);
|
UBS_PAD(4);
|
||||||
|
|
||||||
void set_modelview(const glm::mat4 &mv)
|
void set_modelview(const glm::mat4 &mv)
|
||||||
@@ -65,7 +66,7 @@ namespace gl
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(model_ubs) == 196 + 16 * MAX_PARAMS, "bad size of ubs");
|
static_assert(sizeof(model_ubs) == 200 + 16 * MAX_PARAMS, "bad size of ubs");
|
||||||
|
|
||||||
struct light_element_ubs
|
struct light_element_ubs
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -125,8 +125,15 @@ bool opengl33_renderer::Init(GLFWwindow *Window)
|
|||||||
|
|
||||||
m_viewports.push_back(std::make_unique<viewport_config>());
|
m_viewports.push_back(std::make_unique<viewport_config>());
|
||||||
viewport_config &default_viewport = *m_viewports.front().get();
|
viewport_config &default_viewport = *m_viewports.front().get();
|
||||||
|
if( Global.gfx_framebuffer_fidelity >= 0 ) {
|
||||||
|
std::vector<int> resolutions = { 480, 720, 1080, 1440 };
|
||||||
|
default_viewport.height = resolutions[ clamp<int>( Global.gfx_framebuffer_fidelity, 0, resolutions.size() - 1 ) ];
|
||||||
|
default_viewport.width = quantize( Global.iWindowWidth * default_viewport.height / Global.iWindowHeight, 4 );
|
||||||
|
}
|
||||||
|
else {
|
||||||
default_viewport.width = Global.gfx_framebuffer_width;
|
default_viewport.width = Global.gfx_framebuffer_width;
|
||||||
default_viewport.height = Global.gfx_framebuffer_height;
|
default_viewport.height = Global.gfx_framebuffer_height;
|
||||||
|
}
|
||||||
default_viewport.main = true;
|
default_viewport.main = true;
|
||||||
default_viewport.window = m_window;
|
default_viewport.window = m_window;
|
||||||
default_viewport.draw_range = 1.0f;
|
default_viewport.draw_range = 1.0f;
|
||||||
@@ -612,11 +619,18 @@ void opengl33_renderer::Render_pass(viewport_config &vp, rendermode const Mode)
|
|||||||
if (!FreeFlyModeFlag && Global.Overcast <= 1.0f && Global.render_cab)
|
if (!FreeFlyModeFlag && Global.Overcast <= 1.0f && Global.render_cab)
|
||||||
{
|
{
|
||||||
glDebug("render cab opaque");
|
glDebug("render cab opaque");
|
||||||
if (Global.gfx_shadowmap_enabled)
|
if( Global.gfx_shadowmap_enabled ) {
|
||||||
setup_shadow_map( m_cabshadows_tex.get(), m_cabshadowpass );
|
setup_shadow_map( m_cabshadows_tex.get(), m_cabshadowpass );
|
||||||
|
}
|
||||||
auto const *vehicle = simulation::Train->Dynamic();
|
// cache shadow colour in case we need to account for cab light
|
||||||
|
auto const *vehicle{ simulation::Train->Dynamic() };
|
||||||
|
if( vehicle->InteriorLightLevel > 0.f ) {
|
||||||
|
setup_shadow_color( glm::min( colors::white, m_shadowcolor + glm::vec4( vehicle->InteriorLight * vehicle->InteriorLightLevel, 1.f ) ) );
|
||||||
|
}
|
||||||
Render_cab( vehicle, vehicle->InteriorLightLevel, false );
|
Render_cab( vehicle, vehicle->InteriorLightLevel, false );
|
||||||
|
if( vehicle->InteriorLightLevel > 0.f ) {
|
||||||
|
setup_shadow_color( m_shadowcolor );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glDebug("render opaque region");
|
glDebug("render opaque region");
|
||||||
@@ -644,10 +658,14 @@ void opengl33_renderer::Render_pass(viewport_config &vp, rendermode const Mode)
|
|||||||
{
|
{
|
||||||
glDebug("render translucent cab");
|
glDebug("render translucent cab");
|
||||||
model_ubs.future = glm::mat4();
|
model_ubs.future = glm::mat4();
|
||||||
if (Global.gfx_shadowmap_enabled)
|
if( Global.gfx_shadowmap_enabled ) {
|
||||||
setup_shadow_map( m_cabshadows_tex.get(), m_cabshadowpass );
|
setup_shadow_map( m_cabshadows_tex.get(), m_cabshadowpass );
|
||||||
|
}
|
||||||
// cache shadow colour in case we need to account for cab light
|
// cache shadow colour in case we need to account for cab light
|
||||||
auto const *vehicle{simulation::Train->Dynamic()};
|
auto *vehicle { simulation::Train->Dynamic() };
|
||||||
|
if( vehicle->InteriorLightLevel > 0.f ) {
|
||||||
|
setup_shadow_color( glm::min( colors::white, m_shadowcolor + glm::vec4( vehicle->InteriorLight * vehicle->InteriorLightLevel, 1.f ) ) );
|
||||||
|
}
|
||||||
if (Global.Overcast > 1.0f)
|
if (Global.Overcast > 1.0f)
|
||||||
{
|
{
|
||||||
// with active precipitation draw the opaque cab parts here to mask rain/snow placed 'inside' the cab
|
// with active precipitation draw the opaque cab parts here to mask rain/snow placed 'inside' the cab
|
||||||
@@ -656,6 +674,9 @@ void opengl33_renderer::Render_pass(viewport_config &vp, rendermode const Mode)
|
|||||||
setup_drawing(true);
|
setup_drawing(true);
|
||||||
}
|
}
|
||||||
Render_cab(vehicle, vehicle->InteriorLightLevel, true);
|
Render_cab(vehicle, vehicle->InteriorLightLevel, true);
|
||||||
|
if( vehicle->InteriorLightLevel > 0.f ) {
|
||||||
|
setup_shadow_color( m_shadowcolor );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer::subsystem.gfx_color.stop();
|
Timer::subsystem.gfx_color.stop();
|
||||||
@@ -731,8 +752,10 @@ void opengl33_renderer::Render_pass(viewport_config &vp, rendermode const Mode)
|
|||||||
|
|
||||||
scene_ubs.projection = OpenGLMatrices.data(GL_PROJECTION);
|
scene_ubs.projection = OpenGLMatrices.data(GL_PROJECTION);
|
||||||
scene_ubo->update(scene_ubs);
|
scene_ubo->update(scene_ubs);
|
||||||
Render(simulation::Region);
|
|
||||||
|
|
||||||
|
if( m_shadowcolor != colors::white ) {
|
||||||
|
Render( simulation::Region );
|
||||||
|
}
|
||||||
m_shadowpass = m_renderpass;
|
m_shadowpass = m_renderpass;
|
||||||
|
|
||||||
m_shadow_fb->unbind();
|
m_shadow_fb->unbind();
|
||||||
@@ -758,8 +781,13 @@ void opengl33_renderer::Render_pass(viewport_config &vp, rendermode const Mode)
|
|||||||
scene_ubs.projection = OpenGLMatrices.data(GL_PROJECTION);
|
scene_ubs.projection = OpenGLMatrices.data(GL_PROJECTION);
|
||||||
scene_ubo->update(scene_ubs);
|
scene_ubo->update(scene_ubs);
|
||||||
|
|
||||||
|
if( m_shadowcolor != colors::white ) {
|
||||||
|
if( Global.RenderCabShadowsRange > 0 ) {
|
||||||
|
Render( simulation::Region );
|
||||||
|
}
|
||||||
Render_cab( simulation::Train->Dynamic(), 0.0f, false );
|
Render_cab( simulation::Train->Dynamic(), 0.0f, false );
|
||||||
Render_cab( simulation::Train->Dynamic(), 0.0f, true );
|
Render_cab( simulation::Train->Dynamic(), 0.0f, true );
|
||||||
|
}
|
||||||
m_cabshadowpass = m_renderpass;
|
m_cabshadowpass = m_renderpass;
|
||||||
|
|
||||||
m_cabshadows_fb->unbind();
|
m_cabshadows_fb->unbind();
|
||||||
@@ -1086,7 +1114,7 @@ void opengl33_renderer::setup_pass(viewport_config &Viewport, renderpass_config
|
|||||||
camera.position() = Global.pCamera.Pos - glm::dvec3{lightvector};
|
camera.position() = Global.pCamera.Pos - glm::dvec3{lightvector};
|
||||||
viewmatrix *= glm::lookAt(camera.position(), glm::dvec3{Global.pCamera.Pos}, glm::dvec3{0.f, 1.f, 0.f});
|
viewmatrix *= glm::lookAt(camera.position(), glm::dvec3{Global.pCamera.Pos}, glm::dvec3{0.f, 1.f, 0.f});
|
||||||
// projection
|
// projection
|
||||||
auto const maphalfsize{Config.draw_range * 0.5f};
|
auto const maphalfsize { std::min( 10.f, Config.draw_range * 0.5f ) };
|
||||||
camera.projection() = ortho_projection(-maphalfsize, maphalfsize, -maphalfsize, maphalfsize, -Config.draw_range, Config.draw_range);
|
camera.projection() = ortho_projection(-maphalfsize, maphalfsize, -maphalfsize, maphalfsize, -Config.draw_range, Config.draw_range);
|
||||||
frustumtest_proj = ortho_frustumtest_projection(-maphalfsize, maphalfsize, -maphalfsize, maphalfsize, -Config.draw_range, Config.draw_range);
|
frustumtest_proj = ortho_frustumtest_projection(-maphalfsize, maphalfsize, -maphalfsize, maphalfsize, -Config.draw_range, Config.draw_range);
|
||||||
|
|
||||||
@@ -1221,19 +1249,28 @@ void opengl33_renderer::setup_shadow_map(opengl_texture *tex, renderpass_config
|
|||||||
0.5, 0.5, 0.5, 1.0 //
|
0.5, 0.5, 0.5, 1.0 //
|
||||||
);
|
);
|
||||||
glm::mat4 depthproj = conf.pass_camera.projection();
|
glm::mat4 depthproj = conf.pass_camera.projection();
|
||||||
glm::mat4 depthcam = conf.pass_camera.modelview();
|
// NOTE: we strip transformations from camera projections to remove jitter that occurs
|
||||||
glm::mat4 worldcam = m_renderpass.pass_camera.modelview();
|
// with large (and unneded as we only need the offset) transformations back and forth
|
||||||
|
auto const depthcam{ glm::mat3{ conf.pass_camera.modelview()} };
|
||||||
|
auto const worldcam{ glm::mat3{ m_renderpass.pass_camera.modelview()} };
|
||||||
|
|
||||||
scene_ubs.lightview =
|
scene_ubs.lightview =
|
||||||
coordmove
|
coordmove
|
||||||
* depthproj
|
* depthproj
|
||||||
* depthcam
|
* glm::translate(
|
||||||
* glm::inverse( worldcam );
|
glm::mat4{ depthcam },
|
||||||
|
glm::vec3{ m_renderpass.pass_camera.position() - conf.pass_camera.position() } )
|
||||||
|
* glm::mat4{ glm::inverse( worldcam ) };
|
||||||
|
|
||||||
scene_ubo->update(scene_ubs);
|
scene_ubo->update(scene_ubs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void opengl33_renderer::setup_shadow_color( glm::vec4 const &Shadowcolor ) {
|
||||||
|
|
||||||
|
model_ubs.shadow_tone = glm::pow( Shadowcolor.x, 2.2f );
|
||||||
|
}
|
||||||
|
|
||||||
void opengl33_renderer::setup_env_map(gl::cubemap *tex)
|
void opengl33_renderer::setup_env_map(gl::cubemap *tex)
|
||||||
{
|
{
|
||||||
if (tex)
|
if (tex)
|
||||||
@@ -1257,19 +1294,19 @@ void opengl33_renderer::setup_environment_light(TEnvironmentType const Environme
|
|||||||
{
|
{
|
||||||
case e_flat:
|
case e_flat:
|
||||||
{
|
{
|
||||||
m_sunlight.apply_intensity();
|
setup_sunlight_intensity();
|
||||||
// m_environment = Environment;
|
// m_environment = Environment;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case e_canyon:
|
case e_canyon:
|
||||||
{
|
{
|
||||||
m_sunlight.apply_intensity(0.4f);
|
setup_sunlight_intensity(0.4f);
|
||||||
// m_environment = Environment;
|
// m_environment = Environment;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case e_tunnel:
|
case e_tunnel:
|
||||||
{
|
{
|
||||||
m_sunlight.apply_intensity(0.2f);
|
setup_sunlight_intensity(0.2f);
|
||||||
// m_environment = Environment;
|
// m_environment = Environment;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1280,18 +1317,18 @@ void opengl33_renderer::setup_environment_light(TEnvironmentType const Environme
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void opengl33_renderer::setup_sunlight_intensity( float const Factor ) {
|
||||||
|
|
||||||
|
m_sunlight.apply_intensity( Factor );
|
||||||
|
light_ubs.lights[ 0 ].intensity = m_sunlight.factor;
|
||||||
|
light_ubs.ambient = m_sunlight.ambient * m_sunlight.factor;
|
||||||
|
light_ubo->update( light_ubs );
|
||||||
|
}
|
||||||
|
|
||||||
bool opengl33_renderer::Render(world_environment *Environment)
|
bool opengl33_renderer::Render(world_environment *Environment)
|
||||||
{
|
{
|
||||||
|
m_shadowcolor = colors::white; // prevent shadow from affecting sky
|
||||||
// calculate shadow tone, based on positions of celestial bodies
|
setup_shadow_color( m_shadowcolor );
|
||||||
m_shadowcolor = interpolate(glm::vec4{colors::shadow}, glm::vec4{colors::white}, clamp(-Environment->m_sun.getAngle(), 0.f, 6.f) / 6.f);
|
|
||||||
if ((Environment->m_sun.getAngle() < -18.f) && (Environment->m_moon.getAngle() > 0.f))
|
|
||||||
{
|
|
||||||
// turn on moon shadows after nautical twilight, if the moon is actually up
|
|
||||||
m_shadowcolor = colors::shadow;
|
|
||||||
}
|
|
||||||
// soften shadows depending on sky overcast factor
|
|
||||||
m_shadowcolor = glm::min(colors::white, m_shadowcolor + ((colors::white - colors::shadow) * Global.Overcast));
|
|
||||||
|
|
||||||
if (Global.bWireFrame)
|
if (Global.bWireFrame)
|
||||||
{
|
{
|
||||||
@@ -1303,19 +1340,20 @@ bool opengl33_renderer::Render(world_environment *Environment)
|
|||||||
::glDisable(GL_DEPTH_TEST);
|
::glDisable(GL_DEPTH_TEST);
|
||||||
::glPushMatrix();
|
::glPushMatrix();
|
||||||
|
|
||||||
model_ubs.set_modelview(OpenGLMatrices.data(GL_MODELVIEW));
|
|
||||||
model_ubo->update(model_ubs);
|
|
||||||
|
|
||||||
// skydome
|
// skydome
|
||||||
// drawn with 500m radius to blend in if the fog range is low
|
// drawn with 500m radius to blend in if the fog range is low
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
|
{
|
||||||
glScalef( 500.0f, 500.0f, 500.0f );
|
glScalef( 500.0f, 500.0f, 500.0f );
|
||||||
|
model_ubs.set_modelview( OpenGLMatrices.data( GL_MODELVIEW ) );
|
||||||
|
model_ubo->update( model_ubs );
|
||||||
|
|
||||||
m_skydomerenderer.update();
|
m_skydomerenderer.update();
|
||||||
m_skydomerenderer.render();
|
m_skydomerenderer.render();
|
||||||
glPopMatrix();
|
|
||||||
|
|
||||||
// skydome uses a custom vbo which could potentially confuse the main geometry system. hardly elegant but, eh
|
// skydome uses a custom vbo which could potentially confuse the main geometry system. hardly elegant but, eh
|
||||||
gfx::opengl_vbogeometrybank::reset();
|
gfx::opengl_vbogeometrybank::reset();
|
||||||
|
}
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
::glBlendFunc( GL_SRC_ALPHA, GL_ONE );
|
::glBlendFunc( GL_SRC_ALPHA, GL_ONE );
|
||||||
|
|
||||||
@@ -1328,7 +1366,9 @@ bool opengl33_renderer::Render(world_environment *Environment)
|
|||||||
::glRotatef(-std::fmod((float)Global.fTimeAngleDeg, 360.f), 0.f, 1.f, 0.f); // obrót dobowy osi OX
|
::glRotatef(-std::fmod((float)Global.fTimeAngleDeg, 360.f), 0.f, 1.f, 0.f); // obrót dobowy osi OX
|
||||||
|
|
||||||
// render
|
// render
|
||||||
|
m_pointsize = ( 4.f ); // smaller points for stars visualization
|
||||||
Render(Environment->m_stars.m_stars, nullptr, 1.0);
|
Render(Environment->m_stars.m_stars, nullptr, 1.0);
|
||||||
|
m_pointsize = ( 8.f ); // default point size
|
||||||
|
|
||||||
// post-render cleanup
|
// post-render cleanup
|
||||||
::glPopMatrix();
|
::glPopMatrix();
|
||||||
@@ -1461,6 +1501,18 @@ bool opengl33_renderer::Render(world_environment *Environment)
|
|||||||
m_sunlight.apply_angle();
|
m_sunlight.apply_angle();
|
||||||
m_sunlight.apply_intensity();
|
m_sunlight.apply_intensity();
|
||||||
|
|
||||||
|
// calculate shadow tone, based on positions of celestial bodies
|
||||||
|
m_shadowcolor = interpolate(glm::vec4{colors::shadow}, glm::vec4{colors::white}, clamp(-Environment->m_sun.getAngle(), 0.f, 6.f) / 6.f);
|
||||||
|
if ((Environment->m_sun.getAngle() < -18.f) && (Environment->m_moon.getAngle() > 0.f))
|
||||||
|
{
|
||||||
|
// turn on moon shadows after nautical twilight, if the moon is actually up
|
||||||
|
m_shadowcolor = colors::shadow;
|
||||||
|
}
|
||||||
|
// soften shadows depending on sky overcast factor
|
||||||
|
m_shadowcolor = glm::min(colors::white, m_shadowcolor + ((colors::white - colors::shadow) * Global.Overcast));
|
||||||
|
|
||||||
|
setup_shadow_color( m_shadowcolor);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1727,6 +1779,7 @@ void opengl33_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
|
||||||
@@ -1758,6 +1811,7 @@ void opengl33_renderer::Render(section_sequence::iterator First, section_sequenc
|
|||||||
{
|
{
|
||||||
case rendermode::color:
|
case rendermode::color:
|
||||||
case rendermode::reflections:
|
case rendermode::reflections:
|
||||||
|
case rendermode::cabshadows:
|
||||||
case rendermode::shadows:
|
case rendermode::shadows:
|
||||||
break;
|
break;
|
||||||
case rendermode::pickscenery:
|
case rendermode::pickscenery:
|
||||||
@@ -1782,6 +1836,7 @@ void opengl33_renderer::Render(section_sequence::iterator First, section_sequenc
|
|||||||
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())
|
||||||
@@ -1812,6 +1867,7 @@ void opengl33_renderer::Render(section_sequence::iterator First, section_sequenc
|
|||||||
{
|
{
|
||||||
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)
|
||||||
@@ -1838,6 +1894,7 @@ void opengl33_renderer::Render(section_sequence::iterator First, section_sequenc
|
|||||||
switch (m_renderpass.draw_mode)
|
switch (m_renderpass.draw_mode)
|
||||||
{
|
{
|
||||||
case rendermode::shadows:
|
case rendermode::shadows:
|
||||||
|
case rendermode::cabshadows:
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1903,6 +1960,24 @@ void opengl33_renderer::Render(cell_sequence::iterator First, cell_sequence::ite
|
|||||||
|
|
||||||
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.pass_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
|
||||||
@@ -1946,6 +2021,7 @@ void opengl33_renderer::Render(cell_sequence::iterator First, cell_sequence::ite
|
|||||||
{
|
{
|
||||||
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)
|
for (auto *instance : cell->m_instancesopaque)
|
||||||
@@ -2022,6 +2098,7 @@ void opengl33_renderer::Render(scene::shape_node const &Shape, bool const Ignore
|
|||||||
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 - m_renderpass.viewport_camera.position()) / (double)Global.ZoomFactor) / Global.fDistanceFactor;
|
distancesquared = Math3D::SquareMagnitude((data.area.center - m_renderpass.viewport_camera.position()) / (double)Global.ZoomFactor) / Global.fDistanceFactor;
|
||||||
@@ -2047,6 +2124,7 @@ void opengl33_renderer::Render(scene::shape_node const &Shape, bool const Ignore
|
|||||||
Bind_Material(data.material);
|
Bind_Material(data.material);
|
||||||
break;
|
break;
|
||||||
case rendermode::shadows:
|
case rendermode::shadows:
|
||||||
|
case rendermode::cabshadows:
|
||||||
Bind_Material_Shadow(data.material);
|
Bind_Material_Shadow(data.material);
|
||||||
break;
|
break;
|
||||||
case rendermode::pickscenery:
|
case rendermode::pickscenery:
|
||||||
@@ -2076,6 +2154,7 @@ void opengl33_renderer::Render(TAnimModel *Instance)
|
|||||||
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() - m_renderpass.viewport_camera.position()) / (double)Global.ZoomFactor) / Global.fDistanceFactor;
|
distancesquared = Math3D::SquareMagnitude((Instance->location() - m_renderpass.viewport_camera.position()) / (double)Global.ZoomFactor) / Global.fDistanceFactor;
|
||||||
@@ -2140,6 +2219,16 @@ bool opengl33_renderer::Render(TDynamicObject *Dynamic)
|
|||||||
case rendermode::shadows:
|
case rendermode::shadows:
|
||||||
{
|
{
|
||||||
squaredistance = glm::length2(glm::vec3{glm::dvec3{Dynamic->vPosition - m_renderpass.viewport_camera.position()}} / Global.ZoomFactor) / Global.fDistanceFactor;
|
squaredistance = glm::length2(glm::vec3{glm::dvec3{Dynamic->vPosition - m_renderpass.viewport_camera.position()}} / 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 - m_renderpass.viewport_camera.position() } } / Global.ZoomFactor ) / Global.fDistanceFactor;
|
||||||
|
// filter out small details
|
||||||
|
squaredistance = std::max( 100.f * 100.f, squaredistance );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -2167,39 +2256,73 @@ bool opengl33_renderer::Render(TDynamicObject *Dynamic)
|
|||||||
if (Dynamic->fShade > 0.0f)
|
if (Dynamic->fShade > 0.0f)
|
||||||
{
|
{
|
||||||
// change light level based on light level of the occupied track
|
// change light level based on light level of the occupied track
|
||||||
m_sunlight.apply_intensity(Dynamic->fShade);
|
setup_sunlight_intensity(Dynamic->fShade);
|
||||||
}
|
}
|
||||||
|
|
||||||
// render
|
// render
|
||||||
if (Dynamic->mdLowPolyInt)
|
if( Dynamic->mdLowPolyInt ) {
|
||||||
|
// low poly interior
|
||||||
|
// HACK: reduce light level for vehicle interior if there's strong global lighting source
|
||||||
|
auto const luminance { static_cast<float>( 0.5 * ( std::max( 0.3, Global.fLuminance - Global.Overcast ) ) ) };
|
||||||
|
setup_sunlight_intensity(
|
||||||
|
clamp( (
|
||||||
|
Dynamic->fShade > 0.f ?
|
||||||
|
Dynamic->fShade :
|
||||||
|
1.f )
|
||||||
|
- luminance,
|
||||||
|
0.f, 1.f ) );
|
||||||
Render( Dynamic->mdLowPolyInt, Dynamic->Material(), squaredistance );
|
Render( Dynamic->mdLowPolyInt, Dynamic->Material(), squaredistance );
|
||||||
|
// HACK: if the model has low poly interior, we presume the load is placed inside and also affected by reduced light level
|
||||||
if (Dynamic->mdModel)
|
if( Dynamic->mdLoad ) {
|
||||||
Render(Dynamic->mdModel, Dynamic->Material(), squaredistance);
|
// renderowanie nieprzezroczystego ładunku
|
||||||
|
|
||||||
if (Dynamic->mdLoad) // renderowanie nieprzezroczystego ładunku
|
|
||||||
Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} );
|
Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} );
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_sunlight_intensity( Dynamic->fShade > 0.f ? Dynamic->fShade : 1.f );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// HACK: if the model lacks low poly interior, we presume the load is placed outside
|
||||||
|
if( Dynamic->mdLoad ) {
|
||||||
|
// renderowanie nieprzezroczystego ładunku
|
||||||
|
Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( Dynamic->mdModel ) {
|
||||||
|
// main model
|
||||||
|
Render( Dynamic->mdModel, Dynamic->Material(), squaredistance );
|
||||||
|
}
|
||||||
|
// optional attached models
|
||||||
|
for( auto *attachment : Dynamic->mdAttachments ) {
|
||||||
|
Render( attachment, Dynamic->Material(), squaredistance );
|
||||||
|
}
|
||||||
|
|
||||||
// post-render cleanup
|
// post-render cleanup
|
||||||
|
|
||||||
if (Dynamic->fShade > 0.0f)
|
if (Dynamic->fShade > 0.0f)
|
||||||
{
|
{
|
||||||
// restore regular light level
|
// restore regular light level
|
||||||
m_sunlight.apply_intensity();
|
setup_sunlight_intensity();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case rendermode::shadows:
|
case rendermode::shadows:
|
||||||
|
case rendermode::cabshadows:
|
||||||
{
|
{
|
||||||
if (Dynamic->mdLowPolyInt)
|
if( Dynamic->mdLowPolyInt ) {
|
||||||
{
|
|
||||||
// low poly interior
|
// low poly interior
|
||||||
Render( Dynamic->mdLowPolyInt, Dynamic->Material(), squaredistance );
|
Render( Dynamic->mdLowPolyInt, Dynamic->Material(), squaredistance );
|
||||||
}
|
}
|
||||||
if (Dynamic->mdModel)
|
if( Dynamic->mdModel ) {
|
||||||
|
// main model
|
||||||
Render( Dynamic->mdModel, Dynamic->Material(), squaredistance );
|
Render( Dynamic->mdModel, Dynamic->Material(), squaredistance );
|
||||||
if (Dynamic->mdLoad) // renderowanie nieprzezroczystego ładunku
|
}
|
||||||
|
// optional attached models
|
||||||
|
for( auto *attachment : Dynamic->mdAttachments ) {
|
||||||
|
Render( attachment, Dynamic->Material(), squaredistance );
|
||||||
|
}
|
||||||
|
if( Dynamic->mdLoad ) {
|
||||||
|
// renderowanie nieprzezroczystego ładunku
|
||||||
Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} );
|
Render( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} );
|
||||||
|
}
|
||||||
// post-render cleanup
|
// post-render cleanup
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2265,7 +2388,7 @@ bool opengl33_renderer::Render_cab(TDynamicObject const *Dynamic, float const Li
|
|||||||
if (Dynamic->fShade > 0.0f)
|
if (Dynamic->fShade > 0.0f)
|
||||||
{
|
{
|
||||||
// change light level based on light level of the occupied track
|
// change light level based on light level of the occupied track
|
||||||
m_sunlight.apply_intensity(Dynamic->fShade);
|
setup_sunlight_intensity(Dynamic->fShade);
|
||||||
}
|
}
|
||||||
|
|
||||||
// crude way to light the cabin, until we have something more complete in place
|
// crude way to light the cabin, until we have something more complete in place
|
||||||
@@ -2288,7 +2411,7 @@ bool opengl33_renderer::Render_cab(TDynamicObject const *Dynamic, float const Li
|
|||||||
if (Dynamic->fShade > 0.0f)
|
if (Dynamic->fShade > 0.0f)
|
||||||
{
|
{
|
||||||
// change light level based on light level of the occupied track
|
// change light level based on light level of the occupied track
|
||||||
m_sunlight.apply_intensity();
|
setup_sunlight_intensity();
|
||||||
}
|
}
|
||||||
|
|
||||||
// restore ambient
|
// restore ambient
|
||||||
@@ -2490,7 +2613,7 @@ void opengl33_renderer::Render(TSubModel *Submodel)
|
|||||||
Bind_Material(Submodel->m_material, Submodel);
|
Bind_Material(Submodel->m_material, Submodel);
|
||||||
|
|
||||||
// main draw call
|
// main draw call
|
||||||
model_ubs.param[1].x = 2.0f * 2.0f;
|
model_ubs.param[1].x = m_pointsize;
|
||||||
|
|
||||||
draw(Submodel->m_geometry);
|
draw(Submodel->m_geometry);
|
||||||
}
|
}
|
||||||
@@ -2565,6 +2688,7 @@ void opengl33_renderer::Render(scene::basic_cell::path_sequence::const_iterator
|
|||||||
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);
|
||||||
@@ -2614,6 +2738,7 @@ void opengl33_renderer::Render(scene::basic_cell::path_sequence::const_iterator
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case rendermode::shadows:
|
case rendermode::shadows:
|
||||||
|
case rendermode::cabshadows:
|
||||||
{
|
{
|
||||||
if ((std::abs(track->fTexHeight1) < 0.35f) || (track->iCategoryFlag != 2))
|
if ((std::abs(track->fTexHeight1) < 0.35f) || (track->iCategoryFlag != 2))
|
||||||
{
|
{
|
||||||
@@ -2665,6 +2790,7 @@ void opengl33_renderer::Render(scene::basic_cell::path_sequence::const_iterator
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case rendermode::shadows:
|
case rendermode::shadows:
|
||||||
|
case rendermode::cabshadows:
|
||||||
{
|
{
|
||||||
if ((std::abs(track->fTexHeight1) < 0.35f) || ((track->iCategoryFlag == 1) && (track->eType != tt_Normal)))
|
if ((std::abs(track->fTexHeight1) < 0.35f) || ((track->iCategoryFlag == 1) && (track->eType != tt_Normal)))
|
||||||
{
|
{
|
||||||
@@ -2722,6 +2848,7 @@ void opengl33_renderer::Render(scene::basic_cell::path_sequence::const_iterator
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case rendermode::shadows:
|
case rendermode::shadows:
|
||||||
|
case rendermode::cabshadows:
|
||||||
{
|
{
|
||||||
if ((std::abs(track->fTexHeight1) < 0.35f) || ((track->iCategoryFlag == 1) && (track->eType != tt_Normal)))
|
if ((std::abs(track->fTexHeight1) < 0.35f) || ((track->iCategoryFlag == 1) && (track->eType != tt_Normal)))
|
||||||
{
|
{
|
||||||
@@ -2745,6 +2872,7 @@ void opengl33_renderer::Render(scene::basic_cell::path_sequence::const_iterator
|
|||||||
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);
|
||||||
@@ -2771,6 +2899,7 @@ void opengl33_renderer::Render(TMemCell *Memcell)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case rendermode::shadows:
|
case rendermode::shadows:
|
||||||
|
case rendermode::cabshadows:
|
||||||
case rendermode::pickscenery:
|
case rendermode::pickscenery:
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
@@ -3099,27 +3228,32 @@ bool opengl33_renderer::Render_Alpha(TDynamicObject *Dynamic)
|
|||||||
if (Dynamic->fShade > 0.0f)
|
if (Dynamic->fShade > 0.0f)
|
||||||
{
|
{
|
||||||
// change light level based on light level of the occupied track
|
// change light level based on light level of the occupied track
|
||||||
m_sunlight.apply_intensity(Dynamic->fShade);
|
setup_sunlight_intensity(Dynamic->fShade);
|
||||||
}
|
}
|
||||||
|
|
||||||
// render
|
// render
|
||||||
if (Dynamic->mdLowPolyInt)
|
if( Dynamic->mdLowPolyInt ) {
|
||||||
{
|
|
||||||
// low poly interior
|
// low poly interior
|
||||||
Render_Alpha( Dynamic->mdLowPolyInt, Dynamic->Material(), squaredistance );
|
Render_Alpha( Dynamic->mdLowPolyInt, Dynamic->Material(), squaredistance );
|
||||||
}
|
}
|
||||||
|
if( Dynamic->mdModel ) {
|
||||||
if (Dynamic->mdModel)
|
// main model
|
||||||
Render_Alpha( Dynamic->mdModel, Dynamic->Material(), squaredistance );
|
Render_Alpha( Dynamic->mdModel, Dynamic->Material(), squaredistance );
|
||||||
|
}
|
||||||
if (Dynamic->mdLoad) // renderowanie nieprzezroczystego ładunku
|
// optional attached models
|
||||||
Render_Alpha(Dynamic->mdLoad, Dynamic->Material(), squaredistance);
|
for( auto *attachment : Dynamic->mdAttachments ) {
|
||||||
|
Render_Alpha( attachment, Dynamic->Material(), squaredistance );
|
||||||
|
}
|
||||||
|
if( Dynamic->mdLoad ) {
|
||||||
|
// renderowanie nieprzezroczystego ładunku
|
||||||
|
Render_Alpha( Dynamic->mdLoad, Dynamic->Material(), squaredistance, { 0.f, Dynamic->LoadOffset, 0.f }, {} );
|
||||||
|
}
|
||||||
|
|
||||||
// post-render cleanup
|
// post-render cleanup
|
||||||
if (Dynamic->fShade > 0.0f)
|
if (Dynamic->fShade > 0.0f)
|
||||||
{
|
{
|
||||||
// restore regular light level
|
// restore regular light level
|
||||||
m_sunlight.apply_intensity();
|
setup_sunlight_intensity();
|
||||||
}
|
}
|
||||||
|
|
||||||
::glPopMatrix();
|
::glPopMatrix();
|
||||||
@@ -3365,12 +3499,12 @@ void opengl33_renderer::Render_Alpha(TSubModel *Submodel)
|
|||||||
{
|
{
|
||||||
// fake fog halo
|
// fake fog halo
|
||||||
float const fogfactor{interpolate(2.f, 1.f, clamp<float>(Global.fFogEnd / 2000, 0.f, 1.f)) * std::max(1.f, Global.Overcast)};
|
float const fogfactor{interpolate(2.f, 1.f, clamp<float>(Global.fFogEnd / 2000, 0.f, 1.f)) * std::max(1.f, Global.Overcast)};
|
||||||
model_ubs.param[1].x = pointsize * resolutionratio * fogfactor * 2.0f;
|
model_ubs.param[1].x = pointsize * resolutionratio * fogfactor * 3.0f;
|
||||||
model_ubs.param[0] = glm::vec4(glm::vec3(lightcolor), Submodel->fVisible * std::min(1.f, lightlevel) * 0.5f);
|
model_ubs.param[0] = glm::vec4(glm::vec3(lightcolor), Submodel->fVisible * std::min(1.f, lightlevel) * 0.5f);
|
||||||
|
|
||||||
draw(Submodel->m_geometry);
|
draw(Submodel->m_geometry);
|
||||||
}
|
}
|
||||||
model_ubs.param[1].x = pointsize * resolutionratio * 2.0f;
|
model_ubs.param[1].x = pointsize * resolutionratio * 3.0f;
|
||||||
model_ubs.param[0] = glm::vec4(glm::vec3(lightcolor), Submodel->fVisible * std::min(1.f, lightlevel));
|
model_ubs.param[0] = glm::vec4(glm::vec3(lightcolor), Submodel->fVisible * std::min(1.f, lightlevel));
|
||||||
|
|
||||||
if (!Submodel->occlusion_query)
|
if (!Submodel->occlusion_query)
|
||||||
@@ -3639,10 +3773,11 @@ void opengl33_renderer::Update(double const Deltatime)
|
|||||||
// TODO: it doesn't make much sense with vsync
|
// TODO: it doesn't make much sense with vsync
|
||||||
if( Global.targetfps == 0.0f ) {
|
if( Global.targetfps == 0.0f ) {
|
||||||
// automatic adjustment
|
// automatic adjustment
|
||||||
|
auto const framerate = 1000.f / Timer::subsystem.gfx_color.average();
|
||||||
float targetfactor;
|
float targetfactor;
|
||||||
if( m_framerate > 90.0 ) { targetfactor = 3.0f; }
|
if( framerate > 90.0 ) { targetfactor = 3.0f; }
|
||||||
else if( m_framerate > 60.0 ) { targetfactor = 1.5f; }
|
else if( framerate > 60.0 ) { targetfactor = 1.5f; }
|
||||||
else if( m_framerate > 30.0 ) { targetfactor = 1.25; }
|
else if( framerate > 30.0 ) { targetfactor = 1.25; }
|
||||||
else { targetfactor = 1.0f; }
|
else { targetfactor = 1.0f; }
|
||||||
if( targetfactor > Global.fDistanceFactor ) {
|
if( targetfactor > Global.fDistanceFactor ) {
|
||||||
Global.fDistanceFactor = std::min( targetfactor, Global.fDistanceFactor + 0.05f );
|
Global.fDistanceFactor = std::min( targetfactor, Global.fDistanceFactor + 0.05f );
|
||||||
@@ -3656,7 +3791,7 @@ void opengl33_renderer::Update(double const Deltatime)
|
|||||||
if( fps_diff > 0.5f ) {
|
if( fps_diff > 0.5f ) {
|
||||||
Global.fDistanceFactor = std::max( 1.0f, Global.fDistanceFactor - 0.05f );
|
Global.fDistanceFactor = std::max( 1.0f, Global.fDistanceFactor - 0.05f );
|
||||||
}
|
}
|
||||||
else if( fps_diff < 0.5f ) {
|
else if( fps_diff < 1.0f ) {
|
||||||
Global.fDistanceFactor = std::min( 3.0f, Global.fDistanceFactor + 0.05f );
|
Global.fDistanceFactor = std::min( 3.0f, Global.fDistanceFactor + 0.05f );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3807,21 +3942,24 @@ void opengl33_renderer::Update_Lights(light_array &Lights)
|
|||||||
|
|
||||||
bool opengl33_renderer::Init_caps()
|
bool opengl33_renderer::Init_caps()
|
||||||
{
|
{
|
||||||
WriteLog("MaSzyna OpenGL Renderer");
|
WriteLog(
|
||||||
WriteLog("Renderer: " + std::string((char *)glGetString(GL_RENDERER)));
|
"Gfx Renderer: " + std::string( (char *)glGetString(GL_RENDERER))
|
||||||
WriteLog("Vendor: " + std::string((char *)glGetString(GL_VENDOR)));
|
+ "\nVendor: " + std::string( (char *)glGetString(GL_VENDOR))
|
||||||
WriteLog("GL version: " + std::string((char *)glGetString(GL_VERSION)));
|
+ "\nOpenGL Version: " + std::string((char *)glGetString(GL_VERSION)) );
|
||||||
|
|
||||||
WriteLog("--------");
|
WriteLog("--------");
|
||||||
|
{
|
||||||
GLint extCount = 0;
|
GLint extCount = 0;
|
||||||
glGetIntegerv( GL_NUM_EXTENSIONS, &extCount );
|
glGetIntegerv( GL_NUM_EXTENSIONS, &extCount );
|
||||||
|
std::string extensions;
|
||||||
|
|
||||||
WriteLog( "Supported extensions:" );
|
WriteLog( "Supported extensions:" );
|
||||||
for (int i = 0; i < extCount; i++)
|
for( int i = 0; i < extCount; i++ ) {
|
||||||
{
|
|
||||||
const char *ext = (const char *)glGetStringi( GL_EXTENSIONS, i );
|
const char *ext = (const char *)glGetStringi( GL_EXTENSIONS, i );
|
||||||
WriteLog(ext);
|
extensions += ext;
|
||||||
|
extensions += " ";
|
||||||
|
}
|
||||||
|
WriteLog( extensions );
|
||||||
}
|
}
|
||||||
WriteLog("--------");
|
WriteLog("--------");
|
||||||
|
|
||||||
@@ -3860,20 +3998,20 @@ bool opengl33_renderer::Init_caps()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (GLAD_GL_EXT_texture_filter_anisotropic)
|
if (GLAD_GL_EXT_texture_filter_anisotropic)
|
||||||
WriteLog("EXT_texture_filter_anisotropic supported!");
|
WriteLog("EXT_texture_filter_anisotropic supported.");
|
||||||
|
|
||||||
if (GLAD_GL_EXT_clip_control)
|
if (GLAD_GL_EXT_clip_control)
|
||||||
WriteLog("EXT_clip_control supported!");
|
WriteLog("EXT_clip_control supported.");
|
||||||
|
|
||||||
if (GLAD_GL_EXT_geometry_shader)
|
if (GLAD_GL_EXT_geometry_shader)
|
||||||
WriteLog("EXT_geometry_shader supported!");
|
WriteLog("EXT_geometry_shader supported.");
|
||||||
}
|
}
|
||||||
|
|
||||||
glGetError();
|
glGetError();
|
||||||
glLineWidth(2.0f);
|
glLineWidth(2.0f);
|
||||||
if (!glGetError())
|
if (!glGetError())
|
||||||
{
|
{
|
||||||
WriteLog("wide lines supported!");
|
WriteLog("wide lines supported.");
|
||||||
m_widelines_supported = true;
|
m_widelines_supported = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -204,8 +204,10 @@ class opengl33_renderer : public gfx_renderer {
|
|||||||
void setup_matrices();
|
void setup_matrices();
|
||||||
void setup_drawing(bool const Alpha = false);
|
void setup_drawing(bool const Alpha = false);
|
||||||
void setup_shadow_map(opengl_texture *tex, renderpass_config conf);
|
void setup_shadow_map(opengl_texture *tex, renderpass_config conf);
|
||||||
|
void setup_shadow_color( glm::vec4 const &Shadowcolor );
|
||||||
void setup_env_map(gl::cubemap *tex);
|
void setup_env_map(gl::cubemap *tex);
|
||||||
void setup_environment_light(TEnvironmentType const Environment = e_flat);
|
void setup_environment_light(TEnvironmentType const Environment = e_flat);
|
||||||
|
void setup_sunlight_intensity( float const Factor = 1.f);
|
||||||
// runs jobs needed to generate graphics for specified render pass
|
// runs jobs needed to generate graphics for specified render pass
|
||||||
void Render_pass(viewport_config &vp, rendermode const Mode);
|
void Render_pass(viewport_config &vp, rendermode const Mode);
|
||||||
// creates dynamic environment cubemap
|
// creates dynamic environment cubemap
|
||||||
@@ -309,6 +311,7 @@ class opengl33_renderer : public gfx_renderer {
|
|||||||
GLuint64 m_gllasttime = 0;
|
GLuint64 m_gllasttime = 0;
|
||||||
|
|
||||||
double m_precipitationrotation;
|
double m_precipitationrotation;
|
||||||
|
float m_pointsize{ 8.f };
|
||||||
|
|
||||||
glm::mat4 perspective_projection(float fov, float aspect, float z_near, float z_far);
|
glm::mat4 perspective_projection(float fov, float aspect, float z_near, float z_far);
|
||||||
glm::mat4 perpsective_frustumtest_projection(float fov, float aspect, float z_near, float z_far);
|
glm::mat4 perpsective_frustumtest_projection(float fov, float aspect, float z_near, float z_far);
|
||||||
|
|||||||
@@ -895,7 +895,7 @@ opengl_renderer::setup_pass( renderpass_config &Config, rendermode const Mode, f
|
|||||||
glm::dvec3 { Global.pCamera.Pos },
|
glm::dvec3 { Global.pCamera.Pos },
|
||||||
glm::dvec3 { 0.f, 1.f, 0.f } );
|
glm::dvec3 { 0.f, 1.f, 0.f } );
|
||||||
// projection
|
// projection
|
||||||
auto const maphalfsize { Config.draw_range * 0.5f };
|
auto const maphalfsize { std::min( 10.f, Config.draw_range * 0.5f ) };
|
||||||
camera.projection() *=
|
camera.projection() *=
|
||||||
glm::ortho(
|
glm::ortho(
|
||||||
-maphalfsize, maphalfsize,
|
-maphalfsize, maphalfsize,
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ state_serializer::deserialize_atmo( cParser &Input, scene::scratch_data &Scratch
|
|||||||
Global.fFogEnd =
|
Global.fFogEnd =
|
||||||
clamp(
|
clamp(
|
||||||
Random( std::min( fograngestart, fograngeend ), std::max( fograngestart, fograngeend ) ),
|
Random( std::min( fograngestart, fograngeend ), std::max( fograngestart, fograngeend ) ),
|
||||||
10.0, 2000.0 );
|
10.0, 25000.0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string token { Input.getToken<std::string>() };
|
std::string token { Input.getToken<std::string>() };
|
||||||
|
|||||||
Reference in New Issue
Block a user