16
0
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:
tmj-fstate
2017-08-01 03:15:19 +02:00
parent 01ef6b3887
commit c8a70e5280
13 changed files with 213 additions and 214 deletions

View File

@@ -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 },

View File

@@ -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

View File

@@ -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

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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 ) + ")";
}

View File

@@ -118,6 +118,7 @@ private:
void ResourceSweep();
TCamera Camera;
TCamera DebugCamera;
TGround Ground;
world_environment Environment;
TTrain *Train;

View File

@@ -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;

View File

@@ -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
};

View File

@@ -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; }

View File

@@ -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;

View File

@@ -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 } ); } );
}
//---------------------------------------------------------------------------

View File

@@ -1,5 +1,5 @@
#pragma once
#define VERSION_MAJOR 17
#define VERSION_MINOR 727
#define VERSION_MINOR 731
#define VERSION_REVISION 0