mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-18 22:39:18 +02:00
build 170731. cascade shadow maps stub, support for additional debug camera
This commit is contained in:
@@ -352,7 +352,8 @@ void TCamera::Update()
|
||||
}
|
||||
*/
|
||||
if( ( Type == tp_Free )
|
||||
|| ( false == Global::ctrlState ) ) {
|
||||
|| ( false == Global::ctrlState )
|
||||
|| ( true == DebugCameraFlag) ) {
|
||||
// ctrl is used for mirror view, so we ignore the controls when in vehicle if ctrl is pressed
|
||||
if( m_keys.up )
|
||||
Velocity.y = clamp( Velocity.y + m_moverate.y * 10.0 * deltatime, -m_moverate.y, m_moverate.y );
|
||||
@@ -371,7 +372,8 @@ void TCamera::Update()
|
||||
}
|
||||
#endif
|
||||
|
||||
if( Type == tp_Free ) {
|
||||
if( ( Type == tp_Free )
|
||||
|| ( true == DebugCameraFlag ) ) {
|
||||
// free movement position update is handled here, movement while in vehicle is handled by train update
|
||||
vector3 Vec = Velocity;
|
||||
Vec.RotateY( Yaw );
|
||||
@@ -390,7 +392,7 @@ bool TCamera::SetMatrix( glm::dmat4 &Matrix ) {
|
||||
Matrix = glm::rotate( Matrix, -Pitch, glm::dvec3( 1.0, 0.0, 0.0 ) );
|
||||
Matrix = glm::rotate( Matrix, -Yaw, glm::dvec3( 0.0, 1.0, 0.0 ) ); // w zewnętrznym widoku: kierunek patrzenia
|
||||
|
||||
if( Type == tp_Follow ) {
|
||||
if( ( Type == tp_Follow ) && ( false == DebugCameraFlag ) ) {
|
||||
|
||||
Matrix *= glm::lookAt(
|
||||
glm::dvec3{ Pos },
|
||||
|
||||
@@ -71,6 +71,7 @@ float4 Global::UITextColor = float4( 225.0 / 255.0f, 225.0f / 255.0f, 225.0f / 2
|
||||
|
||||
// parametry scenerii
|
||||
vector3 Global::pCameraPosition;
|
||||
vector3 Global::DebugCameraPosition;
|
||||
double Global::pCameraRotation;
|
||||
double Global::pCameraRotationDeg;
|
||||
std::vector<vector3> Global::FreeCameraInit;
|
||||
@@ -86,7 +87,7 @@ opengl_light Global::DayLight;
|
||||
int Global::DynamicLightCount { 3 };
|
||||
bool Global::ScaleSpecularValues { true };
|
||||
bool Global::RenderShadows { false };
|
||||
Global::shadowtune_t Global::shadowtune = { 2048, 250.f, 1250.f, 100.f };
|
||||
Global::shadowtune_t Global::shadowtune = { 2048, 250.f, 250.f, 500.f };
|
||||
bool Global::bRollFix = true; // czy wykonać przeliczanie przechyłki
|
||||
bool Global::bJoinEvents = false; // czy grupować eventy o tych samych nazwach
|
||||
int Global::iHiddenEvents = 1; // czy łączyć eventy z torami poprzez nazwę toru
|
||||
|
||||
@@ -170,6 +170,7 @@ class Global
|
||||
static int Keys[MaxKeys];
|
||||
static bool RealisticControlMode; // controls ability to steer the vehicle from outside views
|
||||
static Math3D::vector3 pCameraPosition; // pozycja kamery w świecie
|
||||
static Math3D::vector3 DebugCameraPosition; // pozycja kamery w świecie
|
||||
static double
|
||||
pCameraRotation; // kierunek bezwzględny kamery w świecie: 0=północ, 90°=zachód (-azymut)
|
||||
static double pCameraRotationDeg; // w stopniach, dla animacji billboard
|
||||
|
||||
@@ -19,6 +19,7 @@ Copyright (C) 2007-2014 Maciej Cierniak
|
||||
|
||||
bool DebugModeFlag = false;
|
||||
bool FreeFlyModeFlag = false;
|
||||
bool DebugCameraFlag = false;
|
||||
|
||||
double Max0R(double x1, double x2)
|
||||
{
|
||||
|
||||
@@ -20,6 +20,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
|
||||
extern bool DebugModeFlag;
|
||||
extern bool FreeFlyModeFlag;
|
||||
extern bool DebugCameraFlag;
|
||||
|
||||
/*funkcje matematyczne*/
|
||||
double Max0R(double x1, double x2);
|
||||
|
||||
57
World.cpp
57
World.cpp
@@ -288,24 +288,16 @@ bool TWorld::Init( GLFWwindow *Window ) {
|
||||
"ShaXbee, Oli_EU, youBy, KURS90, Ra, hunter, szociu, Stele, Q, firleju and others\n" );
|
||||
|
||||
UILayer.set_background( "logo" );
|
||||
/*
|
||||
std::shared_ptr<ui_panel> initpanel = std::make_shared<ui_panel>(85, 600);
|
||||
*/
|
||||
|
||||
TSoundsManager::Init( glfwGetWin32Window( window ) );
|
||||
WriteLog("Sound Init OK");
|
||||
TModelsManager::Init();
|
||||
WriteLog("Models init OK");
|
||||
/*
|
||||
initpanel->text_lines.emplace_back( "Loading scenery / Wczytywanie scenerii:", float4( 0.0f, 0.0f, 0.0f, 1.0f ) );
|
||||
initpanel->text_lines.emplace_back( Global::SceneryFile.substr(0, 40), float4( 0.0f, 0.0f, 0.0f, 1.0f ) );
|
||||
UILayer.push_back( initpanel );
|
||||
*/
|
||||
|
||||
glfwSetWindowTitle( window, ( Global::AppName + " (" + Global::SceneryFile + ")" ).c_str() ); // nazwa scenerii
|
||||
UILayer.set_progress(0.01);
|
||||
UILayer.set_progress( "Loading scenery / Wczytywanie scenerii" );
|
||||
|
||||
GfxRenderer.Render();
|
||||
|
||||
WriteLog( "Ground init" );
|
||||
if( true == Ground.Init( Global::SceneryFile ) ) {
|
||||
WriteLog( "Ground init OK" );
|
||||
@@ -315,13 +307,8 @@ bool TWorld::Init( GLFWwindow *Window ) {
|
||||
|
||||
Environment.init();
|
||||
Camera.Init(Global::FreeCameraInit[0], Global::FreeCameraInitAngle[0]);
|
||||
/*
|
||||
initpanel->text_lines.clear();
|
||||
initpanel->text_lines.emplace_back( "Preparing train / Przygotowanie kabiny:", float4( 0.0f, 0.0f, 0.0f, 1.0f ) );
|
||||
*/
|
||||
|
||||
UILayer.set_progress( "Preparing train / Przygotowanie kabiny" );
|
||||
GfxRenderer.Render();
|
||||
|
||||
WriteLog( "Player train init: " + Global::asHumanCtrlVehicle );
|
||||
|
||||
TGroundNode *nPlayerTrain = NULL;
|
||||
@@ -631,12 +618,18 @@ void TWorld::OnKeyDown(int cKey)
|
||||
break;
|
||||
}
|
||||
case GLFW_KEY_F8: {
|
||||
Global::iTextMode = cKey;
|
||||
if( Global::ctrlState
|
||||
&& Global::shiftState ) {
|
||||
DebugCameraFlag = !DebugCameraFlag; // taka opcjonalna funkcja, może się czasem przydać
|
||||
}
|
||||
else {
|
||||
Global::iTextMode = cKey;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GLFW_KEY_F9: {
|
||||
Global::iTextMode = cKey;
|
||||
// wersja, typ wyświetlania, błędy OpenGL
|
||||
// wersja
|
||||
break;
|
||||
}
|
||||
case GLFW_KEY_F10: {
|
||||
@@ -1074,8 +1067,9 @@ bool TWorld::Update()
|
||||
}
|
||||
|
||||
// fixed step part of the camera update
|
||||
if( (Train != nullptr)
|
||||
&& (Camera.Type == tp_Follow )) {
|
||||
if( ( Train != nullptr )
|
||||
&& ( Camera.Type == tp_Follow )
|
||||
&& ( false == DebugCameraFlag ) ) {
|
||||
// jeśli jazda w kabinie, przeliczyć trzeba parametry kamery
|
||||
Train->UpdateMechPosition( m_secondaryupdaterate );
|
||||
}
|
||||
@@ -1112,11 +1106,16 @@ bool TWorld::Update()
|
||||
while( fTime50Hz >= 1.0 / 50.0 ) {
|
||||
Console::Update(); // to i tak trzeba wywoływać
|
||||
Update_UI();
|
||||
|
||||
// decelerate camera
|
||||
Camera.Velocity *= 0.65;
|
||||
if( std::abs( Camera.Velocity.x ) < 0.01 ) { Camera.Velocity.x = 0.0; }
|
||||
if( std::abs( Camera.Velocity.y ) < 0.01 ) { Camera.Velocity.y = 0.0; }
|
||||
if( std::abs( Camera.Velocity.z ) < 0.01 ) { Camera.Velocity.z = 0.0; }
|
||||
// decelerate debug camera too
|
||||
DebugCamera.Velocity *= 0.65;
|
||||
if( std::abs( DebugCamera.Velocity.x ) < 0.01 ) { DebugCamera.Velocity.x = 0.0; }
|
||||
if( std::abs( DebugCamera.Velocity.y ) < 0.01 ) { DebugCamera.Velocity.y = 0.0; }
|
||||
if( std::abs( DebugCamera.Velocity.z ) < 0.01 ) { DebugCamera.Velocity.z = 0.0; }
|
||||
|
||||
fTime50Hz -= 1.0 / 50.0;
|
||||
}
|
||||
@@ -1177,10 +1176,12 @@ TWorld::Update_Camera( double const Deltatime ) {
|
||||
}
|
||||
}
|
||||
|
||||
Camera.Update(); // uwzględnienie ruchu wywołanego klawiszami
|
||||
if( DebugCameraFlag ) { DebugCamera.Update(); }
|
||||
else { Camera.Update(); } // uwzględnienie ruchu wywołanego klawiszami
|
||||
|
||||
if( (Train != nullptr)
|
||||
&& (Camera.Type == tp_Follow )) {
|
||||
if( ( Train != nullptr )
|
||||
&& ( Camera.Type == tp_Follow )
|
||||
&& ( false == DebugCameraFlag ) ) {
|
||||
// jeśli jazda w kabinie, przeliczyć trzeba parametry kamery
|
||||
vector3 tempangle = Controlled->VectorFront() * ( Controlled->MoverParameters->ActiveCab == -1 ? -1 : 1 );
|
||||
double modelrotate = atan2( -tempangle.x, tempangle.z );
|
||||
@@ -1243,7 +1244,8 @@ TWorld::Update_Camera( double const Deltatime ) {
|
||||
Global::SetCameraRotation( Camera.Yaw - M_PI );
|
||||
}
|
||||
// all done, update camera position to the new value
|
||||
Global::SetCameraPosition( Camera.Pos );
|
||||
Global::pCameraPosition = Camera.Pos;
|
||||
Global::DebugCameraPosition = DebugCamera.Pos;
|
||||
}
|
||||
|
||||
void TWorld::Update_Environment() {
|
||||
@@ -1597,8 +1599,9 @@ TWorld::Update_UI() {
|
||||
uitextline1 =
|
||||
"FoV: " + to_string( Global::FieldOfView / Global::ZoomFactor, 1 )
|
||||
+ ", Draw range x " + to_string( Global::fDistanceFactor, 1 )
|
||||
+ "; sectors: " + std::to_string( GfxRenderer.m_drawcount )
|
||||
+ ", FPS: " + to_string( Timer::GetFPS(), 2 );
|
||||
// + "; sectors: " + std::to_string( GfxRenderer.m_drawcount )
|
||||
// + ", FPS: " + to_string( Timer::GetFPS(), 2 );
|
||||
+ ", FPS: " + std::to_string( static_cast<int>(std::round(GfxRenderer.Framerate())) );
|
||||
if( Global::iSlowMotion ) {
|
||||
uitextline1 += " (slowmotion " + to_string( Global::iSlowMotion ) + ")";
|
||||
}
|
||||
|
||||
1
World.h
1
World.h
@@ -118,6 +118,7 @@ private:
|
||||
void ResourceSweep();
|
||||
|
||||
TCamera Camera;
|
||||
TCamera DebugCamera;
|
||||
TGround Ground;
|
||||
world_environment Environment;
|
||||
TTrain *Train;
|
||||
|
||||
10
frustum.cpp
10
frustum.cpp
@@ -10,10 +10,6 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "stdafx.h"
|
||||
#include "frustum.h"
|
||||
|
||||
std::vector<glm::vec4> ndcfrustumshapepoints = {
|
||||
{ -1, -1, -1, 1 }, { 1, -1, -1, 1 }, { 1, 1, -1, 1 }, { -1, 1, -1, 1 }, // z-near
|
||||
{ -1, -1, 1, 1 }, { 1, -1, 1, 1 }, { 1, 1, 1, 1 }, { -1, 1, 1, 1 } }; // z-far
|
||||
|
||||
void
|
||||
cFrustum::calculate() {
|
||||
|
||||
@@ -26,8 +22,8 @@ cFrustum::calculate() {
|
||||
void
|
||||
cFrustum::calculate( glm::mat4 const &Projection, glm::mat4 const &Modelview ) {
|
||||
|
||||
float const *proj = &Projection[ 0 ][ 0 ];
|
||||
float const *modl = &Modelview[ 0 ][ 0 ];
|
||||
float const *proj = glm::value_ptr( Projection );
|
||||
float const *modl = glm::value_ptr( Modelview );
|
||||
float clip[ 16 ];
|
||||
|
||||
// multiply the matrices to retrieve clipping planes
|
||||
@@ -88,7 +84,7 @@ cFrustum::calculate( glm::mat4 const &Projection, glm::mat4 const &Modelview ) {
|
||||
m_frustum[ side_FRONT ][ plane_D ] = clip[ 15 ] + clip[ 14 ];
|
||||
normalize_plane( side_FRONT );
|
||||
|
||||
m_inversetransformation = glm::inverse( Projection * Modelview );
|
||||
m_inversetransformation = glm::inverse( Projection * glm::mat4{ glm::mat3{ Modelview } } );
|
||||
|
||||
// calculate frustum corners
|
||||
m_frustumpoints = ndcfrustumshapepoints;
|
||||
|
||||
12
frustum.h
12
frustum.h
@@ -12,6 +12,10 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "float3d.h"
|
||||
#include "dumb3d.h"
|
||||
|
||||
std::vector<glm::vec4> const ndcfrustumshapepoints = {
|
||||
{ -1, -1, -1, 1 },{ 1, -1, -1, 1 },{ 1, 1, -1, 1 },{ -1, 1, -1, 1 }, // z-near
|
||||
{ -1, -1, 1, 1 },{ 1, -1, 1, 1 },{ 1, 1, 1, 1 },{ -1, 1, 1, 1 } }; // z-far
|
||||
|
||||
// generic frustum class. used to determine if objects are inside current view area
|
||||
|
||||
class cFrustum {
|
||||
@@ -64,7 +68,7 @@ public:
|
||||
// transforms provided set of clip space points to world space
|
||||
template <class Iterator_>
|
||||
void
|
||||
transform_to_world( Iterator_ First, Iterator_ Last ) {
|
||||
transform_to_world( Iterator_ First, Iterator_ Last ) const {
|
||||
std::for_each(
|
||||
First, Last,
|
||||
[this]( glm::vec4 &point ) {
|
||||
@@ -76,7 +80,10 @@ public:
|
||||
void
|
||||
draw( glm::vec3 const &Offset ) const;
|
||||
|
||||
protected:
|
||||
// members:
|
||||
std::vector<glm::vec4> m_frustumpoints; // coordinates of corners for defined frustum, in world space
|
||||
|
||||
private:
|
||||
// types:
|
||||
// planes of the frustum
|
||||
enum side { side_RIGHT = 0, side_LEFT = 1, side_BOTTOM = 2, side_TOP = 3, side_BACK = 4, side_FRONT = 5 };
|
||||
@@ -90,5 +97,4 @@ protected:
|
||||
// members:
|
||||
float m_frustum[6][4]; // holds the A B C and D values (normal & distance) for each side of the frustum.
|
||||
glm::mat4 m_inversetransformation; // cached inverse transformation matrix
|
||||
std::vector<glm::vec4> m_frustumpoints; // coordinates of corners for defined frustum, in world space
|
||||
};
|
||||
|
||||
282
renderer.cpp
282
renderer.cpp
@@ -25,8 +25,6 @@ http://mozilla.org/MPL/2.0/.
|
||||
opengl_renderer GfxRenderer;
|
||||
extern TWorld World;
|
||||
|
||||
//#define EU07_USE_ORTHO_SHADOWS
|
||||
|
||||
int const EU07_PICKBUFFERSIZE { 1024 }; // size of (square) textures bound with the pick framebuffer
|
||||
|
||||
namespace colors {
|
||||
@@ -212,6 +210,7 @@ opengl_renderer::Init( GLFWwindow *Window ) {
|
||||
::glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_shadowdebugtexture, 0 );
|
||||
#else
|
||||
::glDrawBuffer( GL_NONE ); // we won't be rendering colour data, so can skip the colour attachment
|
||||
::glReadBuffer( GL_NONE );
|
||||
#endif
|
||||
::glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, m_shadowtexture, 0 );
|
||||
// check if we got it working
|
||||
@@ -248,15 +247,21 @@ opengl_renderer::Init( GLFWwindow *Window ) {
|
||||
bool
|
||||
opengl_renderer::Render() {
|
||||
|
||||
auto const drawstart = std::chrono::steady_clock::now();
|
||||
if( m_drawstart != std::chrono::steady_clock::time_point() ) {
|
||||
m_drawtime = std::max( 20.f, 0.95f * m_drawtime + std::chrono::duration_cast<std::chrono::microseconds>( ( std::chrono::steady_clock::now() - m_drawstart ) ).count() / 1000.f );
|
||||
}
|
||||
m_drawstart = std::chrono::steady_clock::now();
|
||||
auto const drawstartcolor = m_drawstart;
|
||||
|
||||
m_renderpass.draw_mode = rendermode::none; // force setup anew
|
||||
Render_pass( rendermode::color );
|
||||
glfwSwapBuffers( m_window );
|
||||
|
||||
m_drawcount = m_drawqueue.size();
|
||||
// accumulate last 20 frames worth of render time (cap at 1000 fps to prevent calculations going awry)
|
||||
m_drawtime = std::max( 20.f, 0.95f * m_drawtime + std::chrono::duration_cast<std::chrono::milliseconds>( ( std::chrono::steady_clock::now() - drawstart ) ).count() );
|
||||
m_drawtimecolor = std::max( 20.f, 0.95f * m_drawtimecolor + std::chrono::duration_cast<std::chrono::microseconds>( ( std::chrono::steady_clock::now() - drawstartcolor ) ).count() / 1000.f );
|
||||
m_debuginfo += " frame total: " + to_string( m_drawtimecolor / 20.f, 2 ) + " msec (" + std::to_string( m_drawqueue.size() ) + " sectors)";
|
||||
|
||||
glfwSwapBuffers( m_window );
|
||||
|
||||
return true; // for now always succeed
|
||||
}
|
||||
@@ -265,12 +270,12 @@ opengl_renderer::Render() {
|
||||
void
|
||||
opengl_renderer::Render_pass( rendermode const Mode ) {
|
||||
|
||||
m_renderpass.setup( Mode );
|
||||
m_renderpass.setup( Mode, m_framebuffersupport );
|
||||
switch( m_renderpass.draw_mode ) {
|
||||
|
||||
case rendermode::color: {
|
||||
|
||||
opengl_camera shadowcamera;
|
||||
opengl_camera shadowcamera; // temporary helper, remove once ortho shadowmap code is done
|
||||
if( Global::RenderShadows && World.InitPerformed() ) {
|
||||
// run shadowmap pass before color
|
||||
Render_pass( rendermode::shadows );
|
||||
@@ -279,7 +284,20 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
|
||||
#endif
|
||||
shadowcamera = m_renderpass.camera; // cache shadow camera placement for visualization
|
||||
|
||||
m_renderpass.setup( rendermode::color ); // restore draw mode. TBD, TODO: render mode stack
|
||||
m_renderpass.setup( rendermode::color, m_framebuffersupport ); // restore draw mode. TBD, TODO: render mode stack
|
||||
#ifdef EU07_USE_DEBUG_CAMERA
|
||||
m_worldcamera.setup(
|
||||
rendermode::color,
|
||||
m_framebuffersupport,
|
||||
0.f,
|
||||
std::min(
|
||||
1.f,
|
||||
Global::shadowtune.depth / ( Global::BaseDrawRange * Global::fDistanceFactor )
|
||||
* std::max(
|
||||
1.f,
|
||||
Global::ZoomFactor * 0.5f ) ),
|
||||
true );
|
||||
#endif
|
||||
// setup shadowmap matrix
|
||||
m_shadowtexturematrix =
|
||||
//bias from [-1, 1] to [0, 1] };
|
||||
@@ -312,19 +330,23 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
|
||||
// opaque parts...
|
||||
setup_drawing( false );
|
||||
setup_units( true, true, true );
|
||||
|
||||
#ifdef EU07_USE_DEBUG_CAMERA
|
||||
if( DebugModeFlag ) {
|
||||
// draw light frustum
|
||||
::glLineWidth( 2.f );
|
||||
::glColor4f( 1.f, 0.9f, 0.8f, 1.f );
|
||||
::glDisable( GL_LIGHTING );
|
||||
::glDisable( GL_TEXTURE_2D );
|
||||
shadowcamera.frustum().draw( m_renderpass.camera.position() );
|
||||
shadowcamera.frustum().draw( m_renderpass.camera.position() - shadowcamera.position() );
|
||||
if( DebugCameraFlag ) {
|
||||
::glColor4f( 0.8f, 1.f, 0.9f, 1.f );
|
||||
m_worldcamera.camera.frustum().draw( m_renderpass.camera.position() - m_worldcamera.camera.position() );
|
||||
}
|
||||
::glLineWidth( 1.f );
|
||||
::glEnable( GL_LIGHTING );
|
||||
::glEnable( GL_TEXTURE_2D );
|
||||
}
|
||||
|
||||
#endif
|
||||
Render( &World.Ground );
|
||||
// ...translucent parts
|
||||
setup_drawing( true );
|
||||
@@ -342,6 +364,8 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
|
||||
|
||||
if( World.InitPerformed() ) {
|
||||
// setup
|
||||
auto const shadowdrawstart = std::chrono::steady_clock::now();
|
||||
|
||||
::glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, m_shadowframebuffer );
|
||||
|
||||
::glViewport( 0, 0, m_shadowbuffersize, m_shadowbuffersize );
|
||||
@@ -363,18 +387,6 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
|
||||
setup_drawing( false );
|
||||
#ifdef EU07_USE_DEBUG_SHADOWMAP
|
||||
setup_units( true, false, false );
|
||||
|
||||
if( DebugModeFlag ) {
|
||||
// draw camera frustum
|
||||
::glLineWidth( 2.f );
|
||||
::glColor4f( 1.f, 0.9f, 0.8f, 1.f );
|
||||
::glDisable( GL_LIGHTING );
|
||||
::glDisable( GL_TEXTURE_2D );
|
||||
worldcamera.frustum().draw( m_renderpass.camera.position() );
|
||||
::glLineWidth( 1.f );
|
||||
::glEnable( GL_LIGHTING );
|
||||
::glEnable( GL_TEXTURE_2D );
|
||||
}
|
||||
#else
|
||||
setup_units( false, false, false );
|
||||
#endif
|
||||
@@ -384,6 +396,9 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
|
||||
::glDisable( GL_SCISSOR_TEST );
|
||||
|
||||
::glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); // switch back to primary render target
|
||||
|
||||
m_drawtimeshadows = 0.95f * m_drawtimeshadows + std::chrono::duration_cast<std::chrono::microseconds>( ( std::chrono::steady_clock::now() - shadowdrawstart ) ).count() / 1000.f;
|
||||
m_debuginfo = "shadows: " + to_string( m_drawtimeshadows / 20.f, 2 ) + " msec (" + std::to_string( m_drawqueue.size() ) + " sectors)";
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -438,7 +453,7 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
|
||||
}
|
||||
|
||||
void
|
||||
opengl_renderer::renderpass_config::setup( rendermode const Mode ) {
|
||||
opengl_renderer::renderpass_config::setup( rendermode const Mode, bool const Framebuffersupport, float const Znear, float const Zfar, bool const Ignoredebug ) {
|
||||
|
||||
draw_mode = Mode;
|
||||
|
||||
@@ -446,159 +461,121 @@ opengl_renderer::renderpass_config::setup( rendermode const Mode ) {
|
||||
|
||||
switch( draw_mode ) {
|
||||
case rendermode::color: { draw_range = Global::BaseDrawRange; break; }
|
||||
case rendermode::shadows: { draw_range = Global::shadowtune.depth; break; }
|
||||
case rendermode::shadows: { draw_range = Global::BaseDrawRange * 0.5f; break; }
|
||||
case rendermode::pickcontrols: { draw_range = 50.f; break; }
|
||||
case rendermode::pickscenery: { draw_range = Global::BaseDrawRange * 0.5f; break; }
|
||||
default: { draw_range = 0.f; break; }
|
||||
}
|
||||
|
||||
setup_projection();
|
||||
setup_modelview();
|
||||
}
|
||||
|
||||
// configures projection matrix for the current render pass
|
||||
void
|
||||
opengl_renderer::renderpass_config::setup_projection() {
|
||||
|
||||
camera.projection() = glm::mat4( 1.f );
|
||||
glm::dmat4 viewmatrix( 1.0 );
|
||||
|
||||
switch( draw_mode ) {
|
||||
|
||||
#ifndef EU07_USE_PICKING_FRAMEBUFFER
|
||||
case rendermode::pickcontrols:
|
||||
case rendermode::pickscenery:
|
||||
#endif
|
||||
case rendermode::color: {
|
||||
setup_projection_world();
|
||||
break;
|
||||
}
|
||||
#ifdef EU07_USE_PICKING_FRAMEBUFFER
|
||||
case rendermode::pickcontrols:
|
||||
case rendermode::pickscenery: {
|
||||
// TODO: scissor test for pick modes
|
||||
auto const angle = Global::FieldOfView / Global::ZoomFactor;
|
||||
auto const height = std::max( 1.0f, (float)Global::iWindowWidth ) / std::max( 1.0f, (float)Global::iWindowHeight ) / ( Global::iWindowWidth / EU07_PICKBUFFERSIZE );
|
||||
// projection
|
||||
auto const zfar = draw_range * Global::fDistanceFactor * Zfar;
|
||||
auto const znear = (
|
||||
Znear > 0.f ?
|
||||
Znear * zfar :
|
||||
0.1f * Global::ZoomFactor );
|
||||
camera.projection() *=
|
||||
glm::perspective(
|
||||
glm::radians( Global::FieldOfView / Global::ZoomFactor ),
|
||||
std::max( 1.0f, (float)Global::iWindowWidth ) / std::max( 1.0f, (float)Global::iWindowHeight ) / ( Global::iWindowWidth / EU07_PICKBUFFERSIZE ),
|
||||
0.1f * Global::ZoomFactor,
|
||||
draw_range * Global::fDistanceFactor );
|
||||
std::max( 1.f, (float)Global::iWindowWidth ) / std::max( 1.f, (float)Global::iWindowHeight ),
|
||||
znear,
|
||||
zfar );
|
||||
// modelview
|
||||
if( ( false == DebugCameraFlag ) || ( true == Ignoredebug ) ) {
|
||||
camera.position() = Global::pCameraPosition;
|
||||
World.Camera.SetMatrix( viewmatrix );
|
||||
}
|
||||
else {
|
||||
camera.position() = Global::DebugCameraPosition;
|
||||
World.DebugCamera.SetMatrix( viewmatrix );
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case rendermode::shadows: {
|
||||
#ifdef EU07_USE_ORTHO_SHADOWS
|
||||
setup_projection_light_ortho();
|
||||
#else
|
||||
setup_projection_light_perspective();
|
||||
#endif
|
||||
// calculate lightview boundaries based on relevant area of the world camera frustum:
|
||||
// setup chunk of frustum we're interested in...
|
||||
auto const znear = 0.f;
|
||||
auto const zfar = std::min( 1.f, Global::shadowtune.depth / ( Global::BaseDrawRange * Global::fDistanceFactor ) * std::max( 1.f, Global::ZoomFactor * 0.5f ) );
|
||||
renderpass_config worldview;
|
||||
worldview.setup( rendermode::color, Framebuffersupport, znear, zfar, true );
|
||||
// ...transform frustum shape to camera-centric world space...
|
||||
auto frustumchunkshapepoints = ndcfrustumshapepoints;
|
||||
worldview.camera.frustum().transform_to_world( std::begin( frustumchunkshapepoints ), std::end( frustumchunkshapepoints ) );
|
||||
// ...determine the centre of frustum chunk in world space...
|
||||
glm::vec3 frustumchunkmin, frustumchunkmax;
|
||||
bounding_box( frustumchunkmin, frustumchunkmax, std::begin( frustumchunkshapepoints ), std::end( frustumchunkshapepoints ) );
|
||||
auto const frustumchunkcentre = ( frustumchunkmin + frustumchunkmax ) * 0.5f;
|
||||
auto const lighttarget = worldview.camera.position() + glm::dvec3{ frustumchunkcentre };
|
||||
|
||||
auto const lightvector =
|
||||
glm::normalize( glm::vec3{
|
||||
-Global::DayLight.direction.x,
|
||||
std::max( -Global::DayLight.direction.y, 0.15f ),
|
||||
-Global::DayLight.direction.z } );
|
||||
// ...place the light source at the calculated centre...
|
||||
camera.position() = lighttarget;// -glm::dvec3{ lightvector };
|
||||
// ...setup world space light view matrix...
|
||||
viewmatrix *= glm::lookAt(
|
||||
camera.position(),
|
||||
camera.position() - glm::dvec3{ lightvector },
|
||||
glm::dvec3{ 0.f, 1.f, 0.f } );
|
||||
// ...calculate boundaries of the frustum chunk in light space...
|
||||
auto const lightviewmatrix =
|
||||
glm::translate(
|
||||
glm::mat4{ glm::mat3{ viewmatrix } },
|
||||
-frustumchunkcentre );
|
||||
for( auto &point : frustumchunkshapepoints ) {
|
||||
point = lightviewmatrix * point;
|
||||
}
|
||||
bounding_box( frustumchunkmin, frustumchunkmax, std::begin( frustumchunkshapepoints ), std::end( frustumchunkshapepoints ) );
|
||||
// ...use the dimensions to set up light projection boundaries
|
||||
// NOTE: since we only have one cascade map stage, we extend the chunk forward/back to catch areas normally covered by other stages
|
||||
camera.projection() *=
|
||||
glm::ortho(
|
||||
frustumchunkmin.x, frustumchunkmax.x,
|
||||
frustumchunkmin.y, frustumchunkmax.y,
|
||||
frustumchunkmin.z - 500.f, frustumchunkmax.z + 500.f );
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
opengl_renderer::renderpass_config::setup_projection_world() {
|
||||
|
||||
camera.projection() *=
|
||||
glm::perspective(
|
||||
glm::radians( Global::FieldOfView / Global::ZoomFactor ),
|
||||
std::max( 1.f, (float)Global::iWindowWidth ) / std::max( 1.f, (float)Global::iWindowHeight ),
|
||||
0.1f * Global::ZoomFactor,
|
||||
draw_range * Global::fDistanceFactor );
|
||||
}
|
||||
|
||||
void
|
||||
opengl_renderer::renderpass_config::setup_projection_light_ortho() {
|
||||
// TODO: calculate lightview boundaries based on area of the world camera frustum
|
||||
camera.projection() *=
|
||||
glm::ortho(
|
||||
-Global::shadowtune.width, Global::shadowtune.width,
|
||||
-Global::shadowtune.width, Global::shadowtune.width,
|
||||
-Global::shadowtune.depth, Global::shadowtune.depth );
|
||||
}
|
||||
|
||||
void
|
||||
opengl_renderer::renderpass_config::setup_projection_light_perspective() {
|
||||
|
||||
camera.projection() *=
|
||||
glm::perspective(
|
||||
glm::radians( 45.f ),
|
||||
1.f,
|
||||
draw_range * 0.1f, // light source is pulled back far enough we won't likely have anything too close to it, can get some z-range here
|
||||
draw_range * Global::fDistanceFactor );
|
||||
}
|
||||
|
||||
// configures modelview matrix for the current render pass
|
||||
void
|
||||
opengl_renderer::renderpass_config::setup_modelview() {
|
||||
|
||||
camera.modelview() = glm::mat4( 1.f );
|
||||
|
||||
glm::dmat4 viewmatrix;
|
||||
|
||||
switch( draw_mode ) {
|
||||
case rendermode::color:
|
||||
case rendermode::pickcontrols:
|
||||
case rendermode::pickscenery: {
|
||||
setup_modelview_world( viewmatrix );
|
||||
break;
|
||||
}
|
||||
case rendermode::shadows: {
|
||||
#ifdef EU07_USE_ORTHO_SHADOWS
|
||||
setup_modelview_light_ortho( viewmatrix );
|
||||
#else
|
||||
setup_modelview_light_perspective( viewmatrix );
|
||||
#endif
|
||||
// TODO: scissor test for pick modes
|
||||
// projection
|
||||
if( true == Framebuffersupport ) {
|
||||
auto const angle = Global::FieldOfView / Global::ZoomFactor;
|
||||
auto const height = std::max( 1.0f, (float)Global::iWindowWidth ) / std::max( 1.0f, (float)Global::iWindowHeight ) / ( Global::iWindowWidth / EU07_PICKBUFFERSIZE );
|
||||
camera.projection() *=
|
||||
glm::perspective(
|
||||
glm::radians( Global::FieldOfView / Global::ZoomFactor ),
|
||||
std::max( 1.f, (float)Global::iWindowWidth ) / std::max( 1.0f, (float)Global::iWindowHeight ) / ( Global::iWindowWidth / EU07_PICKBUFFERSIZE ),
|
||||
0.1f * Global::ZoomFactor,
|
||||
draw_range * Global::fDistanceFactor );
|
||||
}
|
||||
else {
|
||||
camera.projection() *=
|
||||
glm::perspective(
|
||||
glm::radians( Global::FieldOfView / Global::ZoomFactor ),
|
||||
std::max( 1.f, (float)Global::iWindowWidth ) / std::max( 1.f, (float)Global::iWindowHeight ),
|
||||
0.1f * Global::ZoomFactor,
|
||||
draw_range * Global::fDistanceFactor );
|
||||
}
|
||||
// modelview
|
||||
camera.position() = Global::pCameraPosition;
|
||||
World.Camera.SetMatrix( viewmatrix );
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break; }
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef EU07_USE_ORTHO_SHADOWS
|
||||
m_renderpass.camera.update_frustum( OpenGLMatrices.data( GL_PROJECTION ), viewmatrix );
|
||||
// frustum tests are performed in 'world space' but after we set up frustum we no longer need camera translation, only rotation
|
||||
::glMultMatrixd( glm::value_ptr( glm::dmat4( glm::dmat3( viewmatrix ) ) ) );
|
||||
#else
|
||||
camera.modelview() = viewmatrix;
|
||||
camera.update_frustum();
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
opengl_renderer::renderpass_config::setup_modelview_world( glm::dmat4 &Viewmatrix ) {
|
||||
|
||||
camera.position() = Global::pCameraPosition;
|
||||
World.Camera.SetMatrix( Viewmatrix );
|
||||
}
|
||||
|
||||
void
|
||||
opengl_renderer::renderpass_config::setup_modelview_light_ortho( glm::dmat4 &Viewmatrix ) {
|
||||
|
||||
camera.position() = Global::pCameraPosition - glm::dvec3{ Global::DayLight.direction };
|
||||
if( camera.position().y - Global::pCameraPosition.y < 0.1 ) {
|
||||
camera.position().y = Global::pCameraPosition.y + 0.1;
|
||||
}
|
||||
Viewmatrix *= glm::lookAt(
|
||||
camera.position(),
|
||||
glm::dvec3{ Global::pCameraPosition },
|
||||
glm::dvec3{ 0.f, 1.f, 0.f } );
|
||||
}
|
||||
|
||||
void
|
||||
opengl_renderer::renderpass_config::setup_modelview_light_perspective( glm::dmat4 &Viewmatrix ) {
|
||||
|
||||
camera.position() = Global::pCameraPosition - glm::dvec3{ Global::DayLight.direction * draw_range * 0.5f };
|
||||
camera.position().y = std::max<double>( draw_range * 0.5f * 0.1f, camera.position().y ); // prevent shadow source from dipping too low
|
||||
Viewmatrix *= glm::lookAt(
|
||||
camera.position(),
|
||||
glm::dvec3{ Global::pCameraPosition },
|
||||
glm::dvec3{ 0.f, 1.f, 0.f } );
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2648,9 +2625,10 @@ opengl_renderer::Update( double const Deltatime ) {
|
||||
}
|
||||
|
||||
m_updateaccumulator = 0.0;
|
||||
m_framerate = 1000.f / ( m_drawtime / 20.f );
|
||||
|
||||
// adjust draw ranges etc, based on recent performance
|
||||
auto const framerate = 1000.0f / (m_drawtime / 20.0f);
|
||||
auto const framerate = 1000.0f / (m_drawtimecolor / 20.0f);
|
||||
|
||||
float targetfactor;
|
||||
if( framerate > 90.0 ) { targetfactor = 3.0f; }
|
||||
|
||||
34
renderer.h
34
renderer.h
@@ -20,6 +20,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#define EU07_USE_PICKING_FRAMEBUFFER
|
||||
//#define EU07_USE_DEBUG_SHADOWMAP
|
||||
//#define EU07_USE_DEBUG_CAMERA
|
||||
|
||||
struct opengl_light {
|
||||
|
||||
@@ -139,6 +140,9 @@ public:
|
||||
// main draw call. returns false on error
|
||||
bool
|
||||
Render();
|
||||
inline
|
||||
float
|
||||
Framerate() { return m_framerate; }
|
||||
// geometry methods
|
||||
// NOTE: hands-on geometry management is exposed as a temporary measure; ultimately all visualization data should be generated/handled automatically by the renderer itself
|
||||
// creates a new geometry bank. returns: handle to the bank or NULL
|
||||
@@ -199,31 +203,13 @@ private:
|
||||
typedef std::pair< double, TSubRect * > distancesubcell_pair;
|
||||
|
||||
struct renderpass_config {
|
||||
|
||||
opengl_camera camera;
|
||||
rendermode draw_mode { rendermode::none };
|
||||
float draw_range { 0.0f };
|
||||
|
||||
void
|
||||
setup( rendermode const Mode );
|
||||
private:
|
||||
// configures projection matrix for the current render pass
|
||||
void
|
||||
setup_projection();
|
||||
void
|
||||
setup_projection_world();
|
||||
void
|
||||
setup_projection_light_ortho();
|
||||
void
|
||||
setup_projection_light_perspective();
|
||||
// configures camera for the current render pass
|
||||
void
|
||||
setup_modelview();
|
||||
void
|
||||
setup_modelview_world( glm::dmat4 &Viewmatrix );
|
||||
void
|
||||
setup_modelview_light_ortho( glm::dmat4 &Viewmatrix );
|
||||
void
|
||||
setup_modelview_light_perspective( glm::dmat4 &Viewmatrix );
|
||||
setup( rendermode const Mode, bool const Framebuffersupport, float const Znear = 0.f, float const Zfar = 1.f, bool const Ignoredebug = false );
|
||||
};
|
||||
|
||||
typedef std::vector<opengl_light> opengllight_array;
|
||||
@@ -288,6 +274,7 @@ private:
|
||||
pick_color( std::size_t const Index );
|
||||
std::size_t
|
||||
pick_index( glm::ivec3 const &Color );
|
||||
|
||||
// members
|
||||
GLFWwindow *m_window { nullptr };
|
||||
geometrybank_manager m_geometry;
|
||||
@@ -320,6 +307,10 @@ private:
|
||||
int m_diffusetextureunit { GL_TEXTURE2 };
|
||||
|
||||
float m_drawtime { 1000.f / 30.f * 20.f }; // start with presumed 'neutral' average of 30 fps
|
||||
std::chrono::steady_clock::time_point m_drawstart; // cached start time of previous frame
|
||||
float m_framerate;
|
||||
float m_drawtimecolor { 1000.f / 30.f * 20.f };
|
||||
float m_drawtimeshadows { 0.f };
|
||||
double m_updateaccumulator { 0.0 };
|
||||
std::string m_debuginfo;
|
||||
|
||||
@@ -336,6 +327,9 @@ private:
|
||||
std::vector<TSubModel const *> m_pickcontrolsitems;
|
||||
TSubModel const *m_pickcontrolitem { nullptr };
|
||||
TGroundNode const *m_picksceneryitem { nullptr };
|
||||
#ifdef EU07_USE_DEBUG_CAMERA
|
||||
renderpass_config m_worldcamera; // debug item
|
||||
#endif
|
||||
};
|
||||
|
||||
extern opengl_renderer GfxRenderer;
|
||||
|
||||
15
usefull.h
15
usefull.h
@@ -80,4 +80,19 @@ degenerate( VecType_ const &Vertex1, VecType_ const &Vertex2, VecType_ const &Ve
|
||||
return ( glm::length2( glm::cross( Vertex2 - Vertex1, Vertex3 - Vertex1 ) ) == 0.0 );
|
||||
}
|
||||
|
||||
// calculates bounding box for provided set of points
|
||||
template <class Iterator_, class VecType_>
|
||||
void
|
||||
bounding_box( VecType_ &Mincorner, VecType_ &Maxcorner, Iterator_ First, Iterator_ Last ) {
|
||||
|
||||
Mincorner = VecType_( typename std::numeric_limits<VecType_::value_type>::max() );
|
||||
Maxcorner = VecType_( typename std::numeric_limits<VecType_::value_type>::min() );
|
||||
|
||||
std::for_each(
|
||||
First, Last,
|
||||
[&]( typename Iterator_::value_type &point ) {
|
||||
Mincorner = glm::min( Mincorner, VecType_{ point } );
|
||||
Maxcorner = glm::max( Maxcorner, VecType_{ point } ); } );
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user