mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-17 03:59:19 +02:00
perf(reflections): environment map drawn one face per frame from the place the update began at, the first update in one go; cells beyond the range of reflected instances left out; time of the reflection pass in the renderer statistics; tracks skipped in shadow passes no longer counted as drawn
This commit is contained in:
@@ -635,12 +635,16 @@ void opengl33_renderer::SwapBuffers()
|
|||||||
|
|
||||||
m_debugtimestext.clear();
|
m_debugtimestext.clear();
|
||||||
m_debugtimestext =
|
m_debugtimestext =
|
||||||
"cpu frame total: " + to_string( Timer::subsystem.gfx_color.average() + Timer::subsystem.gfx_shadows.average() + Timer::subsystem.gfx_swap.average(), 2 ) + " ms\n"
|
"cpu frame total: " + to_string( Timer::subsystem.gfx_color.average() + Timer::subsystem.gfx_shadows.average() + ( Global.gfx_envmap_enabled ? Timer::subsystem.gfx_reflections.average() : 0.f ) + Timer::subsystem.gfx_swap.average(), 2 ) + " ms\n"
|
||||||
+ " color: " + to_string( Timer::subsystem.gfx_color.average(), 2 ) + " ms (" + std::to_string( m_cellqueue.size() ) + " sectors)\n";
|
+ " color: " + to_string( Timer::subsystem.gfx_color.average(), 2 ) + " ms (" + std::to_string( m_cellqueue.size() ) + " sectors)\n";
|
||||||
if( Global.gfx_shadowmap_enabled ) {
|
if( Global.gfx_shadowmap_enabled ) {
|
||||||
m_debugtimestext +=
|
m_debugtimestext +=
|
||||||
" shadows: " + to_string( Timer::subsystem.gfx_shadows.average(), 2 ) + " ms\n";
|
" shadows: " + to_string( Timer::subsystem.gfx_shadows.average(), 2 ) + " ms\n";
|
||||||
}
|
}
|
||||||
|
if( Global.gfx_envmap_enabled ) {
|
||||||
|
m_debugtimestext +=
|
||||||
|
" reflections: " + to_string( Timer::subsystem.gfx_reflections.average(), 2 ) + " ms\n";
|
||||||
|
}
|
||||||
m_debugtimestext += " swap: " + to_string( Timer::subsystem.gfx_swap.average(), 2 ) + " ms\n";
|
m_debugtimestext += " swap: " + to_string( Timer::subsystem.gfx_swap.average(), 2 ) + " ms\n";
|
||||||
if( !Global.gfx_usegles ) {
|
if( !Global.gfx_usegles ) {
|
||||||
if (m_gllasttime)
|
if (m_gllasttime)
|
||||||
@@ -825,8 +829,10 @@ void opengl33_renderer::Render_pass(viewport_config &vp, rendermode const Mode)
|
|||||||
{
|
{
|
||||||
// potentially update environmental cube map
|
// potentially update environmental cube map
|
||||||
m_renderpass.draw_stats = {};
|
m_renderpass.draw_stats = {};
|
||||||
|
Timer::subsystem.gfx_reflections.start();
|
||||||
if (Render_reflections(vp))
|
if (Render_reflections(vp))
|
||||||
m_renderpass = m_colorpass; // restore color pass settings
|
m_renderpass = m_colorpass; // restore color pass settings
|
||||||
|
Timer::subsystem.gfx_reflections.stop();
|
||||||
setup_env_map(m_env_tex.get());
|
setup_env_map(m_env_tex.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1385,23 +1391,36 @@ bool opengl33_renderer::Render_reflections(viewport_config &vp)
|
|||||||
{
|
{
|
||||||
if( Global.reflectiontune.update_interval == 0 ) { return false; }
|
if( Global.reflectiontune.update_interval == 0 ) { return false; }
|
||||||
|
|
||||||
auto const timestamp{ Timer::GetRenderTime() };
|
if( m_environmentupdateface >= 6 ) {
|
||||||
if( ( timestamp - m_environmentupdatetime < Global.reflectiontune.update_interval )
|
// no update in progress, check whether it's time for another one
|
||||||
&& ( glm::length2( m_renderpass.pass_camera.position() - m_environmentupdatelocation ) < sq(1000.0)) ) // length2 is better than length for comparing because it does not require sqrt function
|
auto const timestamp{ Timer::GetRenderTime() };
|
||||||
{
|
if( ( timestamp - m_environmentupdatetime < Global.reflectiontune.update_interval )
|
||||||
// run update every 5+ mins of simulation time, or at least 1km from the last location
|
&& ( glm::length2( m_renderpass.pass_camera.position() - m_environmentupdatelocation ) < sq(1000.0)) ) // length2 is better than length for comparing because it does not require sqrt function
|
||||||
return false;
|
{
|
||||||
|
// run update every 5+ mins of simulation time, or at least 1km from the last location
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_environmentupdatetime = timestamp;
|
||||||
|
m_environmentupdatelocation = m_renderpass.pass_camera.position();
|
||||||
|
m_environmentupdateface = 0;
|
||||||
}
|
}
|
||||||
m_environmentupdatetime = timestamp;
|
// an update draws the scene six times, which is too much for a single frame. its cost is spread
|
||||||
m_environmentupdatelocation = m_renderpass.pass_camera.position();
|
// by drawing one face of the map per frame, all of them as seen from the place the update began at.
|
||||||
|
// the first update is done in one go, as there's nothing to show in the meantime
|
||||||
|
auto const lastface{ m_environmentready ? m_environmentupdateface : 5 };
|
||||||
glViewport(0, 0, gl::ENVMAP_SIZE, gl::ENVMAP_SIZE);
|
glViewport(0, 0, gl::ENVMAP_SIZE, gl::ENVMAP_SIZE);
|
||||||
for (m_environmentcubetextureface = 0; m_environmentcubetextureface < 6; ++m_environmentcubetextureface)
|
for (; m_environmentupdateface <= lastface; ++m_environmentupdateface)
|
||||||
{
|
{
|
||||||
|
m_environmentcubetextureface = m_environmentupdateface;
|
||||||
m_env_fb->attach(*m_env_tex, m_environmentcubetextureface, GL_COLOR_ATTACHMENT0);
|
m_env_fb->attach(*m_env_tex, m_environmentcubetextureface, GL_COLOR_ATTACHMENT0);
|
||||||
if (m_env_fb->is_complete())
|
if (m_env_fb->is_complete())
|
||||||
Render_pass(vp, rendermode::reflections);
|
Render_pass(vp, rendermode::reflections);
|
||||||
}
|
}
|
||||||
m_env_tex->generate_mipmaps();
|
if (m_environmentupdateface >= 6)
|
||||||
|
{
|
||||||
|
m_env_tex->generate_mipmaps();
|
||||||
|
m_environmentready = true;
|
||||||
|
}
|
||||||
m_env_fb->detach(GL_COLOR_ATTACHMENT0);
|
m_env_fb->detach(GL_COLOR_ATTACHMENT0);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -1712,7 +1731,9 @@ void opengl33_renderer::setup_pass(viewport_config &Viewport, renderpass_config
|
|||||||
case rendermode::reflections:
|
case rendermode::reflections:
|
||||||
{
|
{
|
||||||
// modelview
|
// modelview
|
||||||
camera.position() = (((true == DebugCameraFlag) && (false == Ignoredebug)) ? Global.pDebugCamera.Pos : Global.pCamera.Pos);
|
// the faces of the map are drawn over a few frames. each is drawn from the place the camera was at
|
||||||
|
// when the update began, so they fit together along the edges when the camera moves in the meantime
|
||||||
|
camera.position() = m_environmentupdatelocation;
|
||||||
glm::dvec3 const cubefacetargetvectors[6] = {{1.0, 0.0, 0.0}, {-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 0.0, -1.0}};
|
glm::dvec3 const cubefacetargetvectors[6] = {{1.0, 0.0, 0.0}, {-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 0.0, -1.0}};
|
||||||
glm::dvec3 const cubefaceupvectors[6] = {{0.0, -1.0, 0.0}, {0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 0.0, -1.0}, {0.0, -1.0, 0.0}, {0.0, -1.0, 0.0}};
|
glm::dvec3 const cubefaceupvectors[6] = {{0.0, -1.0, 0.0}, {0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 0.0, -1.0}, {0.0, -1.0, 0.0}, {0.0, -1.0, 0.0}};
|
||||||
auto const cubefaceindex = m_environmentcubetextureface;
|
auto const cubefaceindex = m_environmentcubetextureface;
|
||||||
@@ -2768,7 +2789,13 @@ void opengl33_renderer::Render(cell_sequence::iterator First, cell_sequence::ite
|
|||||||
}
|
}
|
||||||
case rendermode::reflections:
|
case rendermode::reflections:
|
||||||
{
|
{
|
||||||
if( Global.reflectiontune.fidelity >= 1 ) {
|
// a cell lying whole beyond the range the reflections draw model instances at is left out, as each
|
||||||
|
// of its instances would fail the range test done for it in Render_Instanced() and Render( TAnimModel * ).
|
||||||
|
// like the cull of the regular passes above, the test goes by the nearest point of the bounding sphere
|
||||||
|
// of the cell, which holds the locations of all its instances
|
||||||
|
auto const cellnearestdistance { std::max( 0.0, glm::length( cell->m_area.center - m_renderpass.pass_camera.position() ) - cell->m_area.radius ) };
|
||||||
|
if( ( Global.reflectiontune.fidelity >= 1 )
|
||||||
|
&& ( cellnearestdistance <= Global.reflectiontune.range_instances ) ) {
|
||||||
// opaque parts of instanced models -- accumulate into the
|
// opaque parts of instanced models -- accumulate into the
|
||||||
// frame-level map; flushed once per unique model after the loop.
|
// frame-level map; flushed once per unique model after the loop.
|
||||||
for( auto const &bucket : cell->m_instancebuckets_opaque ) {
|
for( auto const &bucket : cell->m_instancebuckets_opaque ) {
|
||||||
@@ -4001,10 +4028,14 @@ void opengl33_renderer::Render(scene::basic_cell::path_sequence::const_iterator
|
|||||||
if ((std::abs(track->fTexHeight1) < 0.35f) || (track->iCategoryFlag != 2))
|
if ((std::abs(track->fTexHeight1) < 0.35f) || (track->iCategoryFlag != 2))
|
||||||
{
|
{
|
||||||
// shadows are only calculated for high enough roads, typically meaning track platforms
|
// shadows are only calculated for high enough roads, typically meaning track platforms
|
||||||
|
--m_renderpass.draw_stats.paths;
|
||||||
|
--m_renderpass.draw_stats.drawcalls;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if( Material( track->m_material1 ).shadow_rank > Global.gfx_shadow_rank_cutoff ) {
|
if( Material( track->m_material1 ).shadow_rank > Global.gfx_shadow_rank_cutoff ) {
|
||||||
// skip if the shadow caster rank is too low for currently set threshold
|
// skip if the shadow caster rank is too low for currently set threshold
|
||||||
|
--m_renderpass.draw_stats.paths;
|
||||||
|
--m_renderpass.draw_stats.drawcalls;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Bind_Material_Shadow(track->m_material1);
|
Bind_Material_Shadow(track->m_material1);
|
||||||
|
|||||||
@@ -346,6 +346,8 @@ class opengl33_renderer : public gfx_renderer {
|
|||||||
glm::mat4 m_shadowtexturematrix; // conversion from camera-centric world space to light-centric clip space
|
glm::mat4 m_shadowtexturematrix; // conversion from camera-centric world space to light-centric clip space
|
||||||
|
|
||||||
int m_environmentcubetextureface{0}; // helper, currently processed cube map face
|
int m_environmentcubetextureface{0}; // helper, currently processed cube map face
|
||||||
|
int m_environmentupdateface{6}; // cube map face the environment map update in progress draws next; 6: no update in progress
|
||||||
|
bool m_environmentready{false}; // the environment map was drawn whole at least once
|
||||||
double m_environmentupdatetime{0}; // time of the most recent environment map update
|
double m_environmentupdatetime{0}; // time of the most recent environment map update
|
||||||
glm::dvec3 m_environmentupdatelocation; // coordinates of most recent environment map update
|
glm::dvec3 m_environmentupdatelocation; // coordinates of most recent environment map update
|
||||||
opengl33_skydome m_skydomerenderer;
|
opengl33_skydome m_skydomerenderer;
|
||||||
|
|||||||
Reference in New Issue
Block a user