mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-18 00:49:19 +02:00
reflection map fidelity level
This commit is contained in:
10
Globals.cpp
10
Globals.cpp
@@ -447,7 +447,12 @@ global_settings::ConfigParse(cParser &Parser) {
|
|||||||
else if( token == "gfx.reflections.framerate" ) {
|
else if( token == "gfx.reflections.framerate" ) {
|
||||||
|
|
||||||
auto const updatespersecond { std::abs( Parser.getToken<double>() ) };
|
auto const updatespersecond { std::abs( Parser.getToken<double>() ) };
|
||||||
ReflectionUpdateInterval = 1.0 / updatespersecond;
|
reflectiontune.update_interval = 1.0 / updatespersecond;
|
||||||
|
}
|
||||||
|
else if( token == "gfx.reflections.fidelity" ) {
|
||||||
|
Parser.getTokens( 1, false );
|
||||||
|
Parser >> reflectiontune.fidelity;
|
||||||
|
reflectiontune.fidelity = clamp( reflectiontune.fidelity, 0, 2 );
|
||||||
}
|
}
|
||||||
else if( token == "timespeed" ) {
|
else if( token == "timespeed" ) {
|
||||||
// przyspieszenie czasu, zmienna do testów
|
// przyspieszenie czasu, zmienna do testów
|
||||||
@@ -1032,7 +1037,8 @@ global_settings::export_as_text( std::ostream &Output ) const {
|
|||||||
export_as_text( Output, "createswitchtrackbeds", CreateSwitchTrackbeds );
|
export_as_text( Output, "createswitchtrackbeds", CreateSwitchTrackbeds );
|
||||||
export_as_text( Output, "gfx.resource.sweep", ResourceSweep );
|
export_as_text( Output, "gfx.resource.sweep", ResourceSweep );
|
||||||
export_as_text( Output, "gfx.resource.move", ResourceMove );
|
export_as_text( Output, "gfx.resource.move", ResourceMove );
|
||||||
export_as_text( Output, "gfx.reflections.framerate", 1.0 / ReflectionUpdateInterval );
|
export_as_text( Output, "gfx.reflections.framerate", 1.0 / reflectiontune.update_interval );
|
||||||
|
export_as_text( Output, "gfx.reflections.fidelity", reflectiontune.fidelity );
|
||||||
export_as_text( Output, "timespeed", fTimeSpeed );
|
export_as_text( Output, "timespeed", fTimeSpeed );
|
||||||
export_as_text( Output, "multisampling", iMultisampling );
|
export_as_text( Output, "multisampling", iMultisampling );
|
||||||
export_as_text( Output, "latitude", fLatitudeDeg );
|
export_as_text( Output, "latitude", fLatitudeDeg );
|
||||||
|
|||||||
@@ -127,7 +127,12 @@ struct global_settings {
|
|||||||
unsigned int map_size{ 2048 };
|
unsigned int map_size{ 2048 };
|
||||||
float range{ 250.f };
|
float range{ 250.f };
|
||||||
} shadowtune;
|
} shadowtune;
|
||||||
double ReflectionUpdateInterval{ 300.0 };
|
struct reflectiontune_t {
|
||||||
|
double update_interval{ 300.0 };
|
||||||
|
int fidelity{ 0 }; // 0: sections, 1: +static models, 2: +vehicles
|
||||||
|
float range_instances{ 750.f };
|
||||||
|
float range_vehicles{ 250.f };
|
||||||
|
} reflectiontune;
|
||||||
bool bUseVBO{ true }; // czy jest VBO w karcie graficznej (czy użyć)
|
bool bUseVBO{ true }; // czy jest VBO w karcie graficznej (czy użyć)
|
||||||
float AnisotropicFiltering{ 8.f }; // requested level of anisotropic filtering. TODO: move it to renderer object
|
float AnisotropicFiltering{ 8.f }; // requested level of anisotropic filtering. TODO: move it to renderer object
|
||||||
float FieldOfView{ 45.f }; // vertical field of view for the camera. TODO: move it to the renderer
|
float FieldOfView{ 45.f }; // vertical field of view for the camera. TODO: move it to the renderer
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ double fFPS{ 0.0f };
|
|||||||
double fLastTime{ 0.0f };
|
double fLastTime{ 0.0f };
|
||||||
DWORD dwFrames{ 0 };
|
DWORD dwFrames{ 0 };
|
||||||
double fSimulationTime{ 0.0 };
|
double fSimulationTime{ 0.0 };
|
||||||
|
double fRenderTime{ 0.0 };
|
||||||
double fSoundTimer{ 0.0 };
|
double fSoundTimer{ 0.0 };
|
||||||
double fSinceStart{ 0.0 };
|
double fSinceStart{ 0.0 };
|
||||||
double override_delta = -1.0f;
|
double override_delta = -1.0f;
|
||||||
@@ -29,6 +30,10 @@ double GetTime()
|
|||||||
return fSimulationTime;
|
return fSimulationTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double GetRenderTime() {
|
||||||
|
return fRenderTime;
|
||||||
|
}
|
||||||
|
|
||||||
double GetDeltaTime()
|
double GetDeltaTime()
|
||||||
{ // czas symulacji (stoi gdy pauza)
|
{ // czas symulacji (stoi gdy pauza)
|
||||||
if (override_delta != -1.0f)
|
if (override_delta != -1.0f)
|
||||||
@@ -67,6 +72,7 @@ void UpdateTimers(bool pause)
|
|||||||
fr = 1000000000;
|
fr = 1000000000;
|
||||||
#endif
|
#endif
|
||||||
DeltaRenderTime = double(count - oldCount) / double(fr);
|
DeltaRenderTime = double(count - oldCount) / double(fr);
|
||||||
|
fRenderTime += DeltaRenderTime;
|
||||||
if (!pause)
|
if (!pause)
|
||||||
{
|
{
|
||||||
DeltaTime = Global.fTimeSpeed * DeltaRenderTime;
|
DeltaTime = Global.fTimeSpeed * DeltaRenderTime;
|
||||||
|
|||||||
1
Timer.h
1
Timer.h
@@ -12,6 +12,7 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
namespace Timer {
|
namespace Timer {
|
||||||
|
|
||||||
double GetTime();
|
double GetTime();
|
||||||
|
double GetRenderTime();
|
||||||
|
|
||||||
double GetDeltaTime();
|
double GetDeltaTime();
|
||||||
double GetDeltaRenderTime();
|
double GetDeltaRenderTime();
|
||||||
|
|||||||
@@ -572,7 +572,10 @@ debug_panel::render() {
|
|||||||
ImGui::Checkbox( "Debug Traction", &DebugTractionFlag );
|
ImGui::Checkbox( "Debug Traction", &DebugTractionFlag );
|
||||||
}
|
}
|
||||||
render_section( "Camera", m_cameralines );
|
render_section( "Camera", m_cameralines );
|
||||||
render_section( "Gfx Renderer", m_rendererlines );
|
if( true == render_section( "Gfx Renderer", m_rendererlines ) ) {
|
||||||
|
// reflection fidelity
|
||||||
|
ImGui::SliderInt( ( to_string( Global.reflectiontune.fidelity ) + "###reflectionfidelity" ).c_str(), &Global.reflectiontune.fidelity, 0, 2, "Reflection fidelity" );
|
||||||
|
}
|
||||||
// toggles
|
// toggles
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
ImGui::Checkbox( "Debug Mode", &DebugModeFlag );
|
ImGui::Checkbox( "Debug Mode", &DebugModeFlag );
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "application.h"
|
#include "application.h"
|
||||||
#include "AnimModel.h"
|
#include "AnimModel.h"
|
||||||
|
|
||||||
int const EU07_PICKBUFFERSIZE{1024}; // size of (square) textures bound with the pick framebuffer
|
int const EU07_PICKBUFFERSIZE{ 1024 }; // size of (square) textures bound with the pick framebuffer
|
||||||
|
int const EU07_REFLECTIONFIDELITYOFFSET { 250 }; // artificial increase of range for reflection pass detail reduction
|
||||||
|
|
||||||
auto const gammacorrection { glm::vec3( 2.2f ) };
|
auto const gammacorrection { glm::vec3( 2.2f ) };
|
||||||
|
|
||||||
@@ -1110,12 +1111,12 @@ bool opengl33_renderer::Render_coupler_adapter( TDynamicObject *Dynamic, float c
|
|||||||
// creates dynamic environment cubemap
|
// creates dynamic environment cubemap
|
||||||
bool opengl33_renderer::Render_reflections(viewport_config &vp)
|
bool opengl33_renderer::Render_reflections(viewport_config &vp)
|
||||||
{
|
{
|
||||||
if( Global.ReflectionUpdateInterval == 0 ) { return false; }
|
if( Global.reflectiontune.update_interval == 0 ) { return false; }
|
||||||
|
|
||||||
auto const timestamp{ Timer::GetTime() };
|
auto const timestamp{ Timer::GetRenderTime() };
|
||||||
if( ( timestamp - m_environmentupdatetime < Global.ReflectionUpdateInterval )
|
if( ( timestamp - m_environmentupdatetime < Global.reflectiontune.update_interval )
|
||||||
&& ( glm::length( m_renderpass.pass_camera.position() - m_environmentupdatelocation ) < 1000.0 ) ) {
|
&& ( glm::length( m_renderpass.pass_camera.position() - m_environmentupdatelocation ) < 1000.0 ) ) {
|
||||||
// run update every 5+ mins of simulation time, or at least 1km from the last location
|
// run update every 5+ mins of simulation time, or at least 1km from the last location
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
m_environmentupdatetime = timestamp;
|
m_environmentupdatetime = timestamp;
|
||||||
@@ -2044,8 +2045,10 @@ void opengl33_renderer::Render(scene::basic_region *Region)
|
|||||||
}
|
}
|
||||||
case rendermode::reflections:
|
case rendermode::reflections:
|
||||||
{
|
{
|
||||||
// for the time being reflections render only terrain geometry
|
|
||||||
Render(std::begin(m_sectionqueue), std::end(m_sectionqueue));
|
Render(std::begin(m_sectionqueue), std::end(m_sectionqueue));
|
||||||
|
if( Global.reflectiontune.fidelity >= 1 ) {
|
||||||
|
Render(std::begin(m_cellqueue), std::end(m_cellqueue));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case rendermode::pickcontrols:
|
case rendermode::pickcontrols:
|
||||||
@@ -2120,6 +2123,7 @@ void opengl33_renderer::Render(section_sequence::iterator First, section_sequenc
|
|||||||
case rendermode::shadows:
|
case rendermode::shadows:
|
||||||
case rendermode::pickscenery:
|
case rendermode::pickscenery:
|
||||||
{
|
{
|
||||||
|
// TBD, TODO: refactor into a method to reuse below?
|
||||||
for (auto &cell : section->m_cells)
|
for (auto &cell : section->m_cells)
|
||||||
{
|
{
|
||||||
if ((true == cell.m_active) && (m_renderpass.pass_camera.visible(cell.m_area)))
|
if ((true == cell.m_active) && (m_renderpass.pass_camera.visible(cell.m_area)))
|
||||||
@@ -2131,6 +2135,19 @@ void opengl33_renderer::Render(section_sequence::iterator First, section_sequenc
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case rendermode::reflections:
|
case rendermode::reflections:
|
||||||
|
{
|
||||||
|
// we can skip filling the cell queue if reflections pass isn't going to use it
|
||||||
|
if( Global.reflectiontune.fidelity == 0 ) { break; }
|
||||||
|
for (auto &cell : section->m_cells)
|
||||||
|
{
|
||||||
|
if ((true == cell.m_active) && (m_renderpass.pass_camera.visible(cell.m_area)))
|
||||||
|
{
|
||||||
|
// store visible cells with content as well as their current distance, for sorting later
|
||||||
|
m_cellqueue.emplace_back(glm::length2(m_renderpass.pass_camera.position() - cell.m_area.center), &cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case rendermode::pickcontrols:
|
case rendermode::pickcontrols:
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
@@ -2190,6 +2207,23 @@ void opengl33_renderer::Render(cell_sequence::iterator First, cell_sequence::ite
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case rendermode::reflections:
|
||||||
|
{
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// post-render cleanup
|
||||||
|
::glPopMatrix();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case rendermode::shadows:
|
case rendermode::shadows:
|
||||||
{
|
{
|
||||||
// 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
|
||||||
@@ -2232,7 +2266,6 @@ void opengl33_renderer::Render(cell_sequence::iterator First, cell_sequence::ite
|
|||||||
::glPopMatrix();
|
::glPopMatrix();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case rendermode::reflections:
|
|
||||||
case rendermode::pickcontrols:
|
case rendermode::pickcontrols:
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
@@ -2251,8 +2284,9 @@ void opengl33_renderer::Render(cell_sequence::iterator First, cell_sequence::ite
|
|||||||
switch (m_renderpass.draw_mode)
|
switch (m_renderpass.draw_mode)
|
||||||
{
|
{
|
||||||
case rendermode::color:
|
case rendermode::color:
|
||||||
case rendermode::shadows:
|
case rendermode::shadows:
|
||||||
{
|
{
|
||||||
|
// TBD, TODO: refactor in to a method to reuse in branch below?
|
||||||
// opaque parts of instanced models
|
// opaque parts of instanced models
|
||||||
for (auto *instance : cell->m_instancesopaque)
|
for (auto *instance : cell->m_instancesopaque)
|
||||||
{
|
{
|
||||||
@@ -2268,7 +2302,25 @@ void opengl33_renderer::Render(cell_sequence::iterator First, cell_sequence::ite
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case rendermode::pickscenery:
|
case rendermode::reflections:
|
||||||
|
{
|
||||||
|
if( Global.reflectiontune.fidelity >= 1 ) {
|
||||||
|
// opaque parts of instanced models
|
||||||
|
for( auto *instance : cell->m_instancesopaque ) {
|
||||||
|
Render( instance );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( Global.reflectiontune.fidelity >= 2 ) {
|
||||||
|
// opaque parts of vehicles
|
||||||
|
for( auto *path : cell->m_paths ) {
|
||||||
|
for( auto *dynamic : path->Dynamics ) {
|
||||||
|
Render( dynamic );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case rendermode::pickscenery:
|
||||||
{
|
{
|
||||||
// opaque parts of instanced models
|
// opaque parts of instanced models
|
||||||
// same procedure like with regular render, but each node receives custom colour used for picking
|
// same procedure like with regular render, but each node receives custom colour used for picking
|
||||||
@@ -2280,7 +2332,6 @@ void opengl33_renderer::Render(cell_sequence::iterator First, cell_sequence::ite
|
|||||||
// vehicles aren't included in scenery picking for the time being
|
// vehicles aren't included in scenery picking for the time being
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case rendermode::reflections:
|
|
||||||
case rendermode::pickcontrols:
|
case rendermode::pickcontrols:
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
@@ -2333,6 +2384,19 @@ void opengl33_renderer::Render(scene::shape_node const &Shape, bool const Ignore
|
|||||||
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;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case rendermode::reflections:
|
||||||
|
{
|
||||||
|
// reflection mode draws simplified version of the shapes, by artificially increasing view range
|
||||||
|
distancesquared =
|
||||||
|
// TBD, TODO: bind offset value with setting variable?
|
||||||
|
( EU07_REFLECTIONFIDELITYOFFSET * EU07_REFLECTIONFIDELITYOFFSET )
|
||||||
|
+ glm::length2( ( data.area.center - m_renderpass.pass_camera.position() ) );
|
||||||
|
/*
|
||||||
|
// TBD: take into account distance multipliers?
|
||||||
|
/ Global.fDistanceFactor;
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
distancesquared = glm::length2((data.area.center - m_renderpass.pass_camera.position()) / (double)Global.ZoomFactor) / Global.fDistanceFactor;
|
distancesquared = glm::length2((data.area.center - m_renderpass.pass_camera.position()) / (double)Global.ZoomFactor) / Global.fDistanceFactor;
|
||||||
@@ -2385,6 +2449,20 @@ void opengl33_renderer::Render(TAnimModel *Instance)
|
|||||||
distancesquared = glm::length2((Instance->location() - m_renderpass.viewport_camera.position()) / (double)Global.ZoomFactor) / Global.fDistanceFactor;
|
distancesquared = glm::length2((Instance->location() - m_renderpass.viewport_camera.position()) / (double)Global.ZoomFactor) / Global.fDistanceFactor;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case rendermode::reflections:
|
||||||
|
{
|
||||||
|
// reflection mode draws simplified version of the shapes, by artificially increasing view range
|
||||||
|
// it also ignores zoom settings and distance multipliers
|
||||||
|
// TBD: take into account distance multipliers?
|
||||||
|
distancesquared = glm::length2((Instance->location() - m_renderpass.pass_camera.position())) /* / Global.fDistanceFactor */;
|
||||||
|
// NOTE: arbitrary draw range limit
|
||||||
|
if( distancesquared > Global.reflectiontune.range_instances * Global.reflectiontune.range_instances ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// TBD, TODO: bind offset value with setting variable?
|
||||||
|
distancesquared += ( EU07_REFLECTIONFIDELITYOFFSET * EU07_REFLECTIONFIDELITYOFFSET );
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
distancesquared = glm::length2((Instance->location() - m_renderpass.pass_camera.position()) / (double)Global.ZoomFactor) / Global.fDistanceFactor;
|
distancesquared = glm::length2((Instance->location() - m_renderpass.pass_camera.position()) / (double)Global.ZoomFactor) / Global.fDistanceFactor;
|
||||||
@@ -2460,6 +2538,24 @@ bool opengl33_renderer::Render(TDynamicObject *Dynamic)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case rendermode::reflections:
|
||||||
|
{
|
||||||
|
// reflection mode draws simplified version of the shapes, by artificially increasing view range
|
||||||
|
// it also ignores zoom settings and distance multipliers
|
||||||
|
squaredistance =
|
||||||
|
std::max(
|
||||||
|
100.f * 100.f,
|
||||||
|
// TBD: take into account distance multipliers?
|
||||||
|
glm::length2( glm::vec3{ originoffset } ) /* / Global.fDistanceFactor */ );
|
||||||
|
// NOTE: arbitrary draw range limit
|
||||||
|
if( squaredistance > Global.reflectiontune.range_vehicles * Global.reflectiontune.range_vehicles ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// TBD, TODO: bind offset value with setting variable?
|
||||||
|
// NOTE: combined 'squared' distance doesn't equal actual squared (distance + offset) but, eh
|
||||||
|
squaredistance += ( EU07_REFLECTIONFIDELITYOFFSET * EU07_REFLECTIONFIDELITYOFFSET );
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
squaredistance = glm::length2(glm::vec3{originoffset} / Global.ZoomFactor);
|
squaredistance = glm::length2(glm::vec3{originoffset} / Global.ZoomFactor);
|
||||||
@@ -2467,7 +2563,11 @@ bool opengl33_renderer::Render(TDynamicObject *Dynamic)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// crude way to reject early items too far to affect the output (mostly relevant for shadow and reflection passes)
|
||||||
|
auto const drawdistancethreshold{ m_renderpass.draw_range + 250 };
|
||||||
|
if( squaredistance > drawdistancethreshold * drawdistancethreshold ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// second stage visibility cull, reject vehicles too far away to be noticeable
|
// second stage visibility cull, reject vehicles too far away to be noticeable
|
||||||
auto const squareradius{ Dynamic->radius() * Dynamic->radius() };
|
auto const squareradius{ Dynamic->radius() * Dynamic->radius() };
|
||||||
Dynamic->renderme = ( squareradius * Global.ZoomFactor / squaredistance > 0.003 * 0.003 );
|
Dynamic->renderme = ( squareradius * Global.ZoomFactor / squaredistance > 0.003 * 0.003 );
|
||||||
@@ -2493,6 +2593,7 @@ bool opengl33_renderer::Render(TDynamicObject *Dynamic)
|
|||||||
{
|
{
|
||||||
|
|
||||||
case rendermode::color:
|
case rendermode::color:
|
||||||
|
case rendermode::reflections:
|
||||||
{
|
{
|
||||||
if (Dynamic->fShade > 0.0f)
|
if (Dynamic->fShade > 0.0f)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
|
|
||||||
int const EU07_PICKBUFFERSIZE { 1024 }; // size of (square) textures bound with the pick framebuffer
|
int const EU07_PICKBUFFERSIZE { 1024 }; // size of (square) textures bound with the pick framebuffer
|
||||||
int const EU07_ENVIRONMENTBUFFERSIZE { 256 }; // size of (square) environmental cube map texture
|
int const EU07_ENVIRONMENTBUFFERSIZE { 256 }; // size of (square) environmental cube map texture
|
||||||
|
int const EU07_REFLECTIONFIDELITYOFFSET { 250 }; // artificial increase of range for reflection pass detail reduction
|
||||||
|
|
||||||
float const EU07_OPACITYDEFAULT { 0.5f };
|
float const EU07_OPACITYDEFAULT { 0.5f };
|
||||||
|
|
||||||
@@ -871,10 +872,10 @@ bool opengl_renderer::Render_coupler_adapter( TDynamicObject *Dynamic, float con
|
|||||||
bool
|
bool
|
||||||
opengl_renderer::Render_reflections() {
|
opengl_renderer::Render_reflections() {
|
||||||
|
|
||||||
if( Global.ReflectionUpdateInterval == 0 ) { return false; }
|
if( Global.reflectiontune.update_interval == 0 ) { return false; }
|
||||||
|
|
||||||
auto const timestamp { Timer::GetTime() };
|
auto const timestamp { Timer::GetRenderTime() };
|
||||||
if( ( timestamp - m_environmentupdatetime < Global.ReflectionUpdateInterval )
|
if( ( timestamp - m_environmentupdatetime < Global.reflectiontune.update_interval )
|
||||||
&& ( glm::length( m_renderpass.camera.position() - m_environmentupdatelocation ) < 1000.0 ) ) {
|
&& ( glm::length( m_renderpass.camera.position() - m_environmentupdatelocation ) < 1000.0 ) ) {
|
||||||
// run update every 5+ mins of simulation time, or at least 1km from the last location
|
// run update every 5+ mins of simulation time, or at least 1km from the last location
|
||||||
return false;
|
return false;
|
||||||
@@ -1847,8 +1848,10 @@ opengl_renderer::Render( scene::basic_region *Region ) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case rendermode::reflections: {
|
case rendermode::reflections: {
|
||||||
// for the time being reflections render only terrain geometry
|
|
||||||
Render( std::begin( m_sectionqueue ), std::end( m_sectionqueue ) );
|
Render( std::begin( m_sectionqueue ), std::end( m_sectionqueue ) );
|
||||||
|
if( Global.reflectiontune.fidelity >= 1 ) {
|
||||||
|
Render(std::begin(m_cellqueue), std::end(m_cellqueue));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case rendermode::pickcontrols:
|
case rendermode::pickcontrols:
|
||||||
@@ -1918,6 +1921,7 @@ opengl_renderer::Render( section_sequence::iterator First, section_sequence::ite
|
|||||||
case rendermode::shadows:
|
case rendermode::shadows:
|
||||||
case rendermode::cabshadows:
|
case rendermode::cabshadows:
|
||||||
case rendermode::pickscenery: {
|
case rendermode::pickscenery: {
|
||||||
|
// TBD, TODO: refactor into a method to reuse below?
|
||||||
for( auto &cell : section->m_cells ) {
|
for( auto &cell : section->m_cells ) {
|
||||||
if( ( true == cell.m_active )
|
if( ( true == cell.m_active )
|
||||||
&& ( m_renderpass.camera.visible( cell.m_area ) ) ) {
|
&& ( m_renderpass.camera.visible( cell.m_area ) ) ) {
|
||||||
@@ -1929,7 +1933,17 @@ opengl_renderer::Render( section_sequence::iterator First, section_sequence::ite
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case rendermode::reflections:
|
case rendermode::reflections: {
|
||||||
|
// we can skip filling the cell queue if reflections pass isn't going to use it
|
||||||
|
if( Global.reflectiontune.fidelity == 0 ) { break; }
|
||||||
|
for( auto &cell : section->m_cells ) {
|
||||||
|
if( ( true == cell.m_active ) && ( m_renderpass.camera.visible( cell.m_area ) ) ) {
|
||||||
|
// store visible cells with content as well as their current distance, for sorting later
|
||||||
|
m_cellqueue.emplace_back( glm::length2( m_renderpass.camera.position() - cell.m_area.center ), &cell );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case rendermode::pickcontrols:
|
case rendermode::pickcontrols:
|
||||||
default: {
|
default: {
|
||||||
break;
|
break;
|
||||||
@@ -2011,6 +2025,22 @@ opengl_renderer::Render( cell_sequence::iterator First, cell_sequence::iterator
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case rendermode::reflections:
|
||||||
|
{
|
||||||
|
// 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 ); }
|
||||||
|
|
||||||
|
// post-render cleanup
|
||||||
|
::glPopMatrix();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case rendermode::shadows: {
|
case rendermode::shadows: {
|
||||||
// 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
|
||||||
::glPushMatrix();
|
::glPushMatrix();
|
||||||
@@ -2019,7 +2049,9 @@ opengl_renderer::Render( cell_sequence::iterator First, cell_sequence::iterator
|
|||||||
|
|
||||||
// render
|
// render
|
||||||
// opaque non-instanced shapes
|
// opaque non-instanced shapes
|
||||||
for( auto const &shape : cell->m_shapesopaque ) { Render( shape, false ); }
|
for( auto const &shape : cell->m_shapesopaque ) {
|
||||||
|
Render( shape, false );
|
||||||
|
}
|
||||||
// tracks
|
// tracks
|
||||||
Render( std::begin( cell->m_paths ), std::end( cell->m_paths ) );
|
Render( std::begin( cell->m_paths ), std::end( cell->m_paths ) );
|
||||||
|
|
||||||
@@ -2036,7 +2068,9 @@ opengl_renderer::Render( cell_sequence::iterator First, cell_sequence::iterator
|
|||||||
|
|
||||||
// render
|
// render
|
||||||
// opaque non-instanced shapes
|
// opaque non-instanced shapes
|
||||||
for( auto const &shape : cell->m_shapesopaque ) { Render( shape, false ); }
|
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
|
// NOTE: tracks aren't likely to cast shadows into the cab, so we skip them in this pass
|
||||||
|
|
||||||
// post-render cleanup
|
// post-render cleanup
|
||||||
@@ -2066,7 +2100,6 @@ opengl_renderer::Render( cell_sequence::iterator First, cell_sequence::iterator
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case rendermode::reflections:
|
|
||||||
case rendermode::pickcontrols:
|
case rendermode::pickcontrols:
|
||||||
default: {
|
default: {
|
||||||
break;
|
break;
|
||||||
@@ -2084,8 +2117,11 @@ opengl_renderer::Render( cell_sequence::iterator First, cell_sequence::iterator
|
|||||||
case rendermode::color:
|
case rendermode::color:
|
||||||
case rendermode::shadows:
|
case rendermode::shadows:
|
||||||
case rendermode::cabshadows: {
|
case rendermode::cabshadows: {
|
||||||
|
// TBD, TODO: refactor in to a method to reuse in branch below?
|
||||||
// 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
|
||||||
for( auto *path : cell->m_paths ) {
|
for( auto *path : cell->m_paths ) {
|
||||||
for( auto *dynamic : path->Dynamics ) {
|
for( auto *dynamic : path->Dynamics ) {
|
||||||
@@ -2105,6 +2141,23 @@ opengl_renderer::Render( cell_sequence::iterator First, cell_sequence::iterator
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case rendermode::reflections: {
|
||||||
|
if( Global.reflectiontune.fidelity >= 1 ) {
|
||||||
|
// opaque parts of instanced models
|
||||||
|
for( auto *instance : cell->m_instancesopaque ) {
|
||||||
|
Render( instance );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( Global.reflectiontune.fidelity >= 2 ) {
|
||||||
|
// opaque parts of vehicles
|
||||||
|
for( auto *path : cell->m_paths ) {
|
||||||
|
for( auto *dynamic : path->Dynamics ) {
|
||||||
|
Render( dynamic );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case rendermode::pickscenery: {
|
case rendermode::pickscenery: {
|
||||||
// opaque parts of instanced models
|
// opaque parts of instanced models
|
||||||
// same procedure like with regular render, but each node receives custom colour used for picking
|
// same procedure like with regular render, but each node receives custom colour used for picking
|
||||||
@@ -2123,7 +2176,6 @@ opengl_renderer::Render( cell_sequence::iterator First, cell_sequence::iterator
|
|||||||
// vehicles aren't included in scenery picking for the time being
|
// vehicles aren't included in scenery picking for the time being
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case rendermode::reflections:
|
|
||||||
case rendermode::pickcontrols:
|
case rendermode::pickcontrols:
|
||||||
default: {
|
default: {
|
||||||
break;
|
break;
|
||||||
@@ -2180,6 +2232,15 @@ opengl_renderer::Render( scene::shape_node const &Shape, bool const Ignorerange
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
case rendermode::reflections: {
|
||||||
|
// reflection mode draws simplified version of the shapes, by artificially increasing view range
|
||||||
|
distancesquared =
|
||||||
|
// TBD, TODO: bind offset value with setting variable?
|
||||||
|
( EU07_REFLECTIONFIDELITYOFFSET * EU07_REFLECTIONFIDELITYOFFSET )
|
||||||
|
// TBD: take into account distance multipliers?
|
||||||
|
+ glm::length2( ( data.area.center - m_renderpass.camera.position() ) ) /* / Global.fDistanceFactor */;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
distancesquared = glm::length2( ( data.area.center - m_renderpass.camera.position() ) / (double)Global.ZoomFactor ) / Global.fDistanceFactor;
|
distancesquared = glm::length2( ( data.area.center - m_renderpass.camera.position() ) / (double)Global.ZoomFactor ) / Global.fDistanceFactor;
|
||||||
break;
|
break;
|
||||||
@@ -2235,6 +2296,19 @@ opengl_renderer::Render( TAnimModel *Instance ) {
|
|||||||
distancesquared = glm::length2((Instance->location() - m_renderpass.camera.position()) / (double)Global.ZoomFactor) / Global.fDistanceFactor;
|
distancesquared = glm::length2((Instance->location() - m_renderpass.camera.position()) / (double)Global.ZoomFactor) / Global.fDistanceFactor;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case rendermode::reflections: {
|
||||||
|
// reflection mode draws simplified version of the shapes, by artificially increasing view range
|
||||||
|
// it also ignores zoom settings and distance multipliers
|
||||||
|
// TBD: take into account distance multipliers?
|
||||||
|
distancesquared = glm::length2( ( Instance->location() - m_renderpass.camera.position() ) ) /* / Global.fDistanceFactor */;
|
||||||
|
// NOTE: arbitrary draw range limit
|
||||||
|
if( distancesquared > Global.reflectiontune.range_instances * Global.reflectiontune.range_instances ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// TBD, TODO: bind offset value with setting variable?
|
||||||
|
distancesquared += ( EU07_REFLECTIONFIDELITYOFFSET * EU07_REFLECTIONFIDELITYOFFSET );
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
distancesquared = glm::length2((Instance->location() - m_renderpass.camera.position()) / (double)Global.ZoomFactor) / Global.fDistanceFactor;
|
distancesquared = glm::length2((Instance->location() - m_renderpass.camera.position()) / (double)Global.ZoomFactor) / Global.fDistanceFactor;
|
||||||
break;
|
break;
|
||||||
@@ -2308,13 +2382,34 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) {
|
|||||||
squaredistance = std::max( 100.f * 100.f, squaredistance );
|
squaredistance = std::max( 100.f * 100.f, squaredistance );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case rendermode::reflections: {
|
||||||
|
// reflection mode draws simplified version of the shapes, by artificially increasing view range
|
||||||
|
// it also ignores zoom settings and distance multipliers
|
||||||
|
squaredistance =
|
||||||
|
std::max(
|
||||||
|
100.f * 100.f,
|
||||||
|
// TBD: take into account distance multipliers?
|
||||||
|
glm::length2( glm::vec3{ originoffset } ) /* / Global.fDistanceFactor */ );
|
||||||
|
// NOTE: arbitrary draw range limit
|
||||||
|
if( squaredistance > Global.reflectiontune.range_vehicles * Global.reflectiontune.range_vehicles ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// TBD, TODO: bind offset value with setting variable?
|
||||||
|
// NOTE: combined 'squared' distance doesn't equal actual squared (distance + offset) but, eh
|
||||||
|
squaredistance += ( EU07_REFLECTIONFIDELITYOFFSET * EU07_REFLECTIONFIDELITYOFFSET );
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
squaredistance = glm::length2( glm::vec3{ originoffset } / Global.ZoomFactor );
|
squaredistance = glm::length2( glm::vec3{ originoffset } / Global.ZoomFactor );
|
||||||
// TODO: filter out small details based on fidelity setting
|
// TODO: filter out small details based on fidelity setting
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// crude way to reject early items too far to affect the output (mostly relevant for shadow and reflection passes)
|
||||||
|
auto const drawdistancethreshold{ m_renderpass.draw_range + 250 };
|
||||||
|
if( squaredistance > drawdistancethreshold * drawdistancethreshold ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// second stage visibility cull, reject vehicles too far away to be noticeable
|
// second stage visibility cull, reject vehicles too far away to be noticeable
|
||||||
Dynamic->renderme = ( Dynamic->radius() * Global.ZoomFactor / std::sqrt( squaredistance ) > 0.003 );
|
Dynamic->renderme = ( Dynamic->radius() * Global.ZoomFactor / std::sqrt( squaredistance ) > 0.003 );
|
||||||
if( false == Dynamic->renderme ) {
|
if( false == Dynamic->renderme ) {
|
||||||
|
|||||||
Reference in New Issue
Block a user