mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-19 07:39:19 +02:00
build 170424. basic shadow mapping implementation, multi texturing unit setup
This commit is contained in:
@@ -88,6 +88,7 @@ opengl_light Global::DayLight;
|
||||
int Global::DynamicLightCount { 3 };
|
||||
bool Global::ScaleSpecularValues { true };
|
||||
bool Global::RenderShadows { false };
|
||||
Global::shadowtune_t Global::shadowtune = { 2048, 200.0f, 150.0f, 100.0f };
|
||||
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
|
||||
@@ -550,6 +551,14 @@ void Global::ConfigParse(cParser &Parser)
|
||||
Parser.getTokens();
|
||||
Parser >> Global::RenderShadows;
|
||||
}
|
||||
else if( token == "shadowtune" ) {
|
||||
Parser.getTokens( 4, false );
|
||||
Parser
|
||||
>> Global::shadowtune.map_size
|
||||
>> Global::shadowtune.width
|
||||
>> Global::shadowtune.depth
|
||||
>> Global::shadowtune.distance;
|
||||
}
|
||||
else if (token == "smoothtraction")
|
||||
{
|
||||
// podwójna jasność ambient
|
||||
|
||||
@@ -227,6 +227,12 @@ class Global
|
||||
static int DynamicLightCount;
|
||||
static bool ScaleSpecularValues;
|
||||
static bool RenderShadows;
|
||||
static struct shadowtune_t {
|
||||
unsigned int map_size;
|
||||
float width;
|
||||
float depth;
|
||||
float distance;
|
||||
} shadowtune;
|
||||
|
||||
static int iSlowMotion;
|
||||
static TDynamicObject *changeDynObj;
|
||||
|
||||
@@ -98,6 +98,11 @@ std::string to_string( glm::tvec3<Type_, Precision_> const &Value ) {
|
||||
return to_string( Value.x, 2 ) + ", " + to_string( Value.y, 2 ) + ", " + to_string( Value.z, 2 );
|
||||
}
|
||||
|
||||
template <typename Type_, glm::precision Precision_ = glm::defaultp>
|
||||
std::string to_string( glm::tvec4<Type_, Precision_> const &Value, int const Width = 2 ) {
|
||||
return to_string( Value.x, Width ) + ", " + to_string( Value.y, Width ) + ", " + to_string( Value.z, Width ) + ", " + to_string( Value.w, Width );
|
||||
}
|
||||
|
||||
int stol_def(const std::string & str, const int & DefaultValue);
|
||||
|
||||
std::string ToLower(std::string const &text);
|
||||
|
||||
11
World.cpp
11
World.cpp
@@ -32,6 +32,8 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "uilayer.h"
|
||||
#include "translation.h"
|
||||
|
||||
//#define EU07_USE_DEBUG_SHADOWMAP
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
TDynamicObject *Controlled = NULL; // pojazd, który prowadzimy
|
||||
@@ -632,8 +634,13 @@ void TWorld::OnKeyDown(int cKey)
|
||||
break;
|
||||
}
|
||||
case GLFW_KEY_F8: {
|
||||
#ifdef EU07_USE_DEBUG_SHADOWMAP
|
||||
if( Global::iTextMode == cKey ) { ++Global::iScreenMode[ cKey - GLFW_KEY_F1 ]; }
|
||||
if( Global::iScreenMode[ cKey - GLFW_KEY_F1 ] > 1 ) {
|
||||
Global::iScreenMode[ cKey - GLFW_KEY_F1 ] = 0;
|
||||
}
|
||||
#endif
|
||||
Global::iTextMode = cKey;
|
||||
// FPS
|
||||
break;
|
||||
}
|
||||
case GLFW_KEY_F9: {
|
||||
@@ -1693,7 +1700,7 @@ TWorld::Update_UI() {
|
||||
std::to_string( int( tmp->MoverParameters->Im ) ) )
|
||||
+ "; U=" + to_string( int( tmp->MoverParameters->RunningTraction.TractionVoltage + 0.5 ) )
|
||||
+ "; R=" +
|
||||
( tmp->MoverParameters->RunningShape.R > 100000.0 ?
|
||||
( std::abs( tmp->MoverParameters->RunningShape.R ) > 10000.0 ?
|
||||
"~0.0" :
|
||||
to_string( tmp->MoverParameters->RunningShape.R, 1 ) )
|
||||
+ " An=" + to_string( tmp->MoverParameters->AccN, 2 ); // przyspieszenie poprzeczne
|
||||
|
||||
@@ -55,6 +55,10 @@ public:
|
||||
multiply( glm::mat4 const &Matrix ) {
|
||||
m_stack.top() *= Matrix;
|
||||
upload(); }
|
||||
void
|
||||
ortho( float const Left, float const Right, float const Bottom, float const Top, float const Znear, float const Zfar ) {
|
||||
m_stack.top() *= glm::ortho( Left, Right, Bottom, Top, Znear, Zfar );
|
||||
upload(); }
|
||||
void
|
||||
perspective( float const Fovy, float const Aspect, float const Znear, float const Zfar ) {
|
||||
m_stack.top() *= glm::perspective( Fovy, Aspect, Znear, Zfar );
|
||||
@@ -132,10 +136,20 @@ public:
|
||||
m_stacks[ m_mode ].multiply(
|
||||
glm::make_mat4( Matrix ) ); }
|
||||
template <typename Type_>
|
||||
void
|
||||
ortho( Type_ const Left, Type_ const Right, Type_ const Bottom, Type_ const Top, Type_ const Znear, Type_ const Zfar ) {
|
||||
m_stacks[ m_mode ].ortho(
|
||||
static_cast<float>( Left ),
|
||||
static_cast<float>( Right ),
|
||||
static_cast<float>( Bottom ),
|
||||
static_cast<float>( Top ),
|
||||
static_cast<float>( Znear ),
|
||||
static_cast<float>( Zfar ) ); }
|
||||
template <typename Type_>
|
||||
void
|
||||
perspective( Type_ const Fovy, Type_ const Aspect, Type_ const Znear, Type_ const Zfar ) {
|
||||
m_stacks[ m_mode ].perspective(
|
||||
static_cast<float>(Fovy) * 0.0174532925f, // deg2rad
|
||||
static_cast<float>( glm::radians( Fovy ) ),
|
||||
static_cast<float>( Aspect ),
|
||||
static_cast<float>( Znear ),
|
||||
static_cast<float>( Zfar ) ); }
|
||||
@@ -177,6 +191,7 @@ extern opengl_matrices OpenGLMatrices;
|
||||
// NOTE: no scale override as we aren't using it anywhere
|
||||
#define glMultMatrixd OpenGLMatrices.multiply
|
||||
#define glMultMatrixf OpenGLMatrices.multiply
|
||||
#define glOrtho OpenGLMatrices.ortho
|
||||
#define gluPerspective OpenGLMatrices.perspective
|
||||
#define gluLookAt OpenGLMatrices.look_at
|
||||
|
||||
|
||||
642
renderer.cpp
642
renderer.cpp
@@ -25,9 +25,12 @@ http://mozilla.org/MPL/2.0/.
|
||||
opengl_renderer GfxRenderer;
|
||||
extern TWorld World;
|
||||
|
||||
//#define EU07_USE_ORTHO_SHADOWS
|
||||
|
||||
namespace colors {
|
||||
|
||||
glm::vec4 const none { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
glm::vec4 const none { 0.f, 0.f, 0.f, 1.f };
|
||||
glm::vec4 const white{ 1.f, 1.f, 1.f, 1.f };
|
||||
|
||||
} // namespace colors
|
||||
|
||||
@@ -67,6 +70,10 @@ opengl_renderer::Init( GLFWwindow *Window ) {
|
||||
glEnable( GL_CULL_FACE ); // Cull back-facing triangles
|
||||
glShadeModel( GL_SMOOTH ); // Enable Smooth Shading
|
||||
|
||||
glActiveTexture( m_diffusetextureunit );
|
||||
glClientActiveTexture( m_diffusetextureunit );
|
||||
UILayer.set_unit( m_diffusetextureunit );
|
||||
|
||||
glEnable( GL_DEPTH_TEST );
|
||||
glAlphaFunc( GL_GREATER, 0.04f );
|
||||
glEnable( GL_ALPHA_TEST );
|
||||
@@ -152,22 +159,41 @@ opengl_renderer::Init( GLFWwindow *Window ) {
|
||||
::glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); // switch back to primary render target for now
|
||||
}
|
||||
#endif
|
||||
|
||||
::glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
|
||||
// preload some common textures
|
||||
WriteLog( "Loading common gfx data..." );
|
||||
m_glaretexture = Fetch_Texture( "fx\\lightglare" );
|
||||
m_suntexture = Fetch_Texture( "fx\\sun" );
|
||||
m_moontexture = Fetch_Texture( "fx\\moon" );
|
||||
if( m_helpertextureunit >= 0 ) {
|
||||
m_reflectiontexture = Fetch_Texture( "fx\\reflections" );
|
||||
}
|
||||
WriteLog( "...gfx data pre-loading done" );
|
||||
|
||||
// shadowmap resources
|
||||
if( ( true == Global::RenderShadows )
|
||||
&& ( true == m_framebuffersupport ) ) {
|
||||
// texture:
|
||||
::glGenTextures( 1, &m_shadowtexture );
|
||||
::glBindTexture( GL_TEXTURE_2D, m_shadowtexture );
|
||||
// allocate memory
|
||||
::glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, m_shadowbuffersize, m_shadowbuffersize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL );
|
||||
// setup parameters
|
||||
::glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
|
||||
::glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
|
||||
::glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
|
||||
::glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
|
||||
::glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
|
||||
::glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
||||
// enable shadow comparison: true (ie not in shadow) if r<=texture...
|
||||
::glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE );
|
||||
::glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL );
|
||||
// ...shadow comparison should generate an INTENSITY result
|
||||
::glTexParameteri( GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY );
|
||||
::glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, m_shadowbuffersize, m_shadowbuffersize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL );
|
||||
::glTexParameteri( GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE );
|
||||
// eye_linear is the default, so we could probably skip it
|
||||
::glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
|
||||
::glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
|
||||
::glTexGeni( GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
|
||||
::glTexGeni( GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
|
||||
::glBindTexture( GL_TEXTURE_2D, 0 );
|
||||
// create and assemble the framebuffer
|
||||
::glGenFramebuffersEXT( 1, &m_shadowframebuffer );
|
||||
::glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, m_shadowframebuffer );
|
||||
@@ -187,13 +213,6 @@ opengl_renderer::Init( GLFWwindow *Window ) {
|
||||
::glDrawBuffer( GL_BACK );
|
||||
}
|
||||
|
||||
::glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
|
||||
// preload some common textures
|
||||
WriteLog( "Loading common gfx data..." );
|
||||
m_glaretexture = Fetch_Texture( "fx\\lightglare" );
|
||||
m_suntexture = Fetch_Texture( "fx\\sun" );
|
||||
m_moontexture = Fetch_Texture( "fx\\moon" );
|
||||
WriteLog( "...gfx data pre-loading done" );
|
||||
// prepare basic geometry chunks
|
||||
auto const geometrybank = m_geometry.create_bank();
|
||||
float const size = 2.5f;
|
||||
@@ -217,6 +236,7 @@ opengl_renderer::Render() {
|
||||
|
||||
auto const drawstart = std::chrono::steady_clock::now();
|
||||
|
||||
m_renderpass.draw_mode = rendermode::none; // force setup anew
|
||||
Render_pass( rendermode::color );
|
||||
glfwSwapBuffers( m_window );
|
||||
|
||||
@@ -248,7 +268,15 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
|
||||
::glDrawBuffer( GL_BACK );
|
||||
}
|
||||
|
||||
::glViewport( 0, 0, Global::ScreenWidth, Global::ScreenHeight );
|
||||
if( ( Global::iTextMode == GLFW_KEY_F8 ) && ( Global::iScreenMode[ GLFW_KEY_F8 - GLFW_KEY_F1 ] == 1 ) ) {
|
||||
// debug shadowmap
|
||||
::glViewport( 0, 0, Global::ScreenHeight, Global::ScreenHeight );
|
||||
m_renderpass.draw_range = 1250.f; // 1.0km square centered around camera
|
||||
}
|
||||
else {
|
||||
::glViewport( 0, 0, Global::ScreenWidth, Global::ScreenHeight );
|
||||
m_renderpass.draw_range = 2500.0f; // arbitrary base draw range
|
||||
}
|
||||
|
||||
if( World.InitPerformed() ) {
|
||||
auto const skydomecolour = World.Environment.m_skydome.GetAverageColor();
|
||||
@@ -261,19 +289,22 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
|
||||
|
||||
if( World.InitPerformed() ) {
|
||||
// setup
|
||||
m_renderpass.draw_range = 2500.0f; // arbitrary base draw range
|
||||
Render_projection();
|
||||
Render_camera();
|
||||
setup_projection();
|
||||
setup_camera();
|
||||
::glDepthFunc( GL_LEQUAL );
|
||||
// render
|
||||
Render_setup( true );
|
||||
setup_drawing( true );
|
||||
setup_units( true, false, false );
|
||||
Render( &World.Environment );
|
||||
// opaque parts...
|
||||
Render_setup();
|
||||
setup_drawing( false );
|
||||
setup_units( true, true, true );
|
||||
Render( &World.Ground );
|
||||
// ...translucent parts
|
||||
Render_setup( true );
|
||||
setup_drawing( true );
|
||||
Render_Alpha( &World.Ground );
|
||||
// cab render is performed without shadows, due to low resolution and number of models without windows :|
|
||||
toggle_units( true, false, false );
|
||||
// cab render is done in translucent phase to deal with badly configured vehicles
|
||||
if( World.Train != nullptr ) { Render_cab( World.Train->Dynamic() ); }
|
||||
}
|
||||
@@ -283,21 +314,34 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
|
||||
|
||||
case rendermode::shadows: {
|
||||
|
||||
::glViewport( 0, 0, m_shadowbuffersize, m_shadowbuffersize );
|
||||
|
||||
::glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
|
||||
::glClear( GL_DEPTH_BUFFER_BIT );
|
||||
|
||||
if( World.InitPerformed() ) {
|
||||
// setup
|
||||
m_renderpass.draw_range = 500.0f; // 1.0km square centered around camera
|
||||
Render_projection();
|
||||
Render_camera();
|
||||
::glViewport( 0, 0, m_shadowbuffersize, m_shadowbuffersize );
|
||||
|
||||
::glClear( GL_DEPTH_BUFFER_BIT );
|
||||
::glScissor( 1, 1, m_shadowbuffersize - 2, m_shadowbuffersize - 2 );
|
||||
::glEnable( GL_SCISSOR_TEST );
|
||||
|
||||
m_renderpass.draw_range = 1250.f; // 1.0km square centered around camera
|
||||
m_shadowtexturematrix =
|
||||
glm::mat4{
|
||||
0.5f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.5f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.5f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f }; //bias from [-1, 1] to [0, 1] };
|
||||
setup_projection();
|
||||
setup_camera();
|
||||
::glDepthFunc( GL_LEQUAL );
|
||||
::glEnable( GL_POLYGON_OFFSET_FILL ); // alleviate depth-fighting
|
||||
::glPolygonOffset( 4.f, 8.f );
|
||||
// render
|
||||
// opaque parts...
|
||||
Render_setup();
|
||||
setup_drawing( false );
|
||||
setup_units( false, false, false );
|
||||
Render( &World.Ground );
|
||||
// post-render restore
|
||||
::glDisable( GL_POLYGON_OFFSET_FILL );
|
||||
::glDisable( GL_SCISSOR_TEST );
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -307,19 +351,20 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
|
||||
#ifdef EU07_USE_PICKING_FRAMEBUFFER
|
||||
::glViewport( 0, 0, m_pickbuffersize, m_pickbuffersize );
|
||||
#endif
|
||||
::glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
|
||||
::glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||
|
||||
if( World.InitPerformed() ) {
|
||||
// setup
|
||||
::glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
|
||||
::glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||
|
||||
m_pickcontrolsitems.clear();
|
||||
m_renderpass.draw_range = 50.0f; // doesn't really matter for control picking
|
||||
Render_projection();
|
||||
Render_camera();
|
||||
setup_projection();
|
||||
setup_camera();
|
||||
::glDepthFunc( GL_LEQUAL );
|
||||
// render
|
||||
// opaque parts...
|
||||
Render_setup();
|
||||
setup_drawing( false );
|
||||
setup_units( false, false, false );
|
||||
// cab render skips translucent parts, so we can do it here
|
||||
if( World.Train != nullptr ) { Render_cab( World.Train->Dynamic() ); }
|
||||
}
|
||||
@@ -332,19 +377,20 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
|
||||
#ifdef EU07_USE_PICKING_FRAMEBUFFER
|
||||
::glViewport( 0, 0, m_pickbuffersize, m_pickbuffersize );
|
||||
#endif
|
||||
::glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
|
||||
::glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||
|
||||
if( World.InitPerformed() ) {
|
||||
// setup
|
||||
::glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
|
||||
::glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||
|
||||
m_picksceneryitems.clear();
|
||||
m_renderpass.draw_range = 1000.0f; // scenery picking is likely to focus on nearby nodes
|
||||
Render_projection();
|
||||
Render_camera();
|
||||
setup_projection();
|
||||
setup_camera();
|
||||
::glDepthFunc( GL_LEQUAL );
|
||||
// render
|
||||
// opaque parts...
|
||||
Render_setup();
|
||||
setup_drawing( false );
|
||||
setup_units( false, false, false );
|
||||
Render( &World.Ground );
|
||||
}
|
||||
break;
|
||||
@@ -354,12 +400,11 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// configures projection matrix for the current render pass
|
||||
void
|
||||
opengl_renderer::Render_projection() {
|
||||
opengl_renderer::setup_projection() {
|
||||
|
||||
::glMatrixMode( GL_PROJECTION );
|
||||
::glLoadIdentity();
|
||||
@@ -371,11 +416,17 @@ opengl_renderer::Render_projection() {
|
||||
case rendermode::pickscenery:
|
||||
#endif
|
||||
case rendermode::color: {
|
||||
::gluPerspective(
|
||||
Global::FieldOfView / Global::ZoomFactor,
|
||||
std::max( 1.0f, (float)Global::ScreenWidth ) / std::max( 1.0f, (float)Global::ScreenHeight ),
|
||||
0.1f * Global::ZoomFactor,
|
||||
m_renderpass.draw_range * Global::fDistanceFactor );
|
||||
if( ( Global::iTextMode == GLFW_KEY_F8 ) && ( Global::iScreenMode[ GLFW_KEY_F8 - GLFW_KEY_F1 ] == 1 ) ) {
|
||||
// debug shadowmap
|
||||
#ifdef EU07_USE_ORTHO_SHADOWS
|
||||
setup_projection_light_ortho();
|
||||
#else
|
||||
setup_projection_light_perspective();
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
setup_projection_world();
|
||||
}
|
||||
break;
|
||||
}
|
||||
#ifdef EU07_USE_PICKING_FRAMEBUFFER
|
||||
@@ -393,13 +444,12 @@ opengl_renderer::Render_projection() {
|
||||
}
|
||||
#endif
|
||||
case rendermode::shadows: {
|
||||
// TODO: set parallel projection
|
||||
::gluPerspective(
|
||||
Global::FieldOfView,
|
||||
1.f,
|
||||
// std::max( 1.0f, (float)Global::ScreenWidth ) / std::max( 1.0f, (float)Global::ScreenHeight ),
|
||||
2.f,
|
||||
m_renderpass.draw_range * Global::fDistanceFactor );
|
||||
#ifdef EU07_USE_ORTHO_SHADOWS
|
||||
setup_projection_light_ortho();
|
||||
#else
|
||||
setup_projection_light_perspective();
|
||||
#endif
|
||||
m_shadowtexturematrix *= OpenGLMatrices.data( GL_PROJECTION );
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -409,9 +459,38 @@ opengl_renderer::Render_projection() {
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
opengl_renderer::setup_projection_world() {
|
||||
|
||||
::gluPerspective(
|
||||
Global::FieldOfView / Global::ZoomFactor,
|
||||
std::max( 1.f, (float)Global::ScreenWidth ) / std::max( 1.f, (float)Global::ScreenHeight ),
|
||||
0.1f * Global::ZoomFactor,
|
||||
m_renderpass.draw_range * Global::fDistanceFactor );
|
||||
}
|
||||
|
||||
void
|
||||
opengl_renderer::setup_projection_light_ortho() {
|
||||
|
||||
::glOrtho(
|
||||
-250, 250,
|
||||
-250, 250,
|
||||
-2500, 2500 );
|
||||
}
|
||||
|
||||
void
|
||||
opengl_renderer::setup_projection_light_perspective() {
|
||||
|
||||
::gluPerspective(
|
||||
45.f,
|
||||
1.f,
|
||||
100.f, // light source is pulled back far enough we won't likely have anything too close to it, can get some z-range here
|
||||
m_renderpass.draw_range * Global::fDistanceFactor );
|
||||
}
|
||||
|
||||
// configures modelview matrix for the current render pass
|
||||
void
|
||||
opengl_renderer::Render_camera() {
|
||||
opengl_renderer::setup_camera() {
|
||||
|
||||
::glMatrixMode( GL_MODELVIEW ); // Select The Modelview Matrix
|
||||
::glLoadIdentity();
|
||||
@@ -422,17 +501,29 @@ opengl_renderer::Render_camera() {
|
||||
case rendermode::color:
|
||||
case rendermode::pickcontrols:
|
||||
case rendermode::pickscenery: {
|
||||
World.Camera.SetMatrix( viewmatrix );
|
||||
m_renderpass.camera.position() = Global::pCameraPosition;
|
||||
if( ( Global::iTextMode == GLFW_KEY_F8 ) && ( Global::iScreenMode[ GLFW_KEY_F8 - GLFW_KEY_F1 ] == 1 ) ) {
|
||||
#ifdef EU07_USE_ORTHO_SHADOWS
|
||||
setup_camera_light_ortho( viewmatrix );
|
||||
#else
|
||||
setup_camera_light_perspective( viewmatrix );
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
setup_camera_world( viewmatrix );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case rendermode::shadows: {
|
||||
m_renderpass.camera.position() = Global::pCameraPosition - glm::dvec3{ Global::DayLight.direction * 250.f };
|
||||
m_renderpass.camera.position().y = std::max( 50.0, m_renderpass.camera.position().y ); // prevent shadow source from dipping too low
|
||||
viewmatrix = glm::lookAt(
|
||||
m_renderpass.camera.position(),
|
||||
glm::dvec3{ Global::pCameraPosition.x, 0.0, Global::pCameraPosition.z },
|
||||
glm::dvec3{ 0.f, 1.f, 0.f } );
|
||||
#ifdef EU07_USE_ORTHO_SHADOWS
|
||||
setup_camera_light_ortho( viewmatrix );
|
||||
#else
|
||||
setup_camera_light_perspective( viewmatrix );
|
||||
#endif
|
||||
// during colour pass coordinates are moved from camera-centric to light-centric, essentially the difference between these two origins
|
||||
m_shadowtexturematrix *=
|
||||
glm::translate(
|
||||
glm::mat4{ glm::dmat3{ viewmatrix } },
|
||||
glm::vec3{ glm::dvec3{ Global::pCameraPosition } - m_renderpass.camera.position() } );
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@@ -445,7 +536,45 @@ opengl_renderer::Render_camera() {
|
||||
}
|
||||
|
||||
void
|
||||
opengl_renderer::Render_setup( bool const Alpha ) {
|
||||
opengl_renderer::setup_camera_world( glm::dmat4 &Viewmatrix ) {
|
||||
|
||||
World.Camera.SetMatrix( Viewmatrix );
|
||||
m_renderpass.camera.position() = Global::pCameraPosition;
|
||||
}
|
||||
|
||||
void
|
||||
opengl_renderer::setup_camera_light_ortho( glm::dmat4 &Viewmatrix ) {
|
||||
/*
|
||||
m_renderpass.camera.position() = Global::pCameraPosition - glm::dvec3{ Global::DayLight.direction * 250.f };
|
||||
m_renderpass.camera.position().y = std::max( 75.0, m_renderpass.camera.position().y ); // prevent shadow source from dipping too low
|
||||
Viewmatrix = glm::lookAt(
|
||||
m_renderpass.camera.position(),
|
||||
glm::dvec3{ Global::pCameraPosition.x, 0.0, Global::pCameraPosition.z },
|
||||
glm::dvec3{ 0.f, 1.f, 0.f } );
|
||||
*/
|
||||
m_renderpass.camera.position() = Global::pCameraPosition - glm::dvec3{ Global::DayLight.direction };
|
||||
if( m_renderpass.camera.position().y - Global::pCameraPosition.y < 0.15 ) {
|
||||
m_renderpass.camera.position().y = Global::pCameraPosition.y + 0.15;
|
||||
}
|
||||
Viewmatrix = glm::lookAt(
|
||||
m_renderpass.camera.position(),
|
||||
glm::dvec3{ Global::pCameraPosition },
|
||||
glm::dvec3{ 0.f, 1.f, 0.f } );
|
||||
}
|
||||
|
||||
void
|
||||
opengl_renderer::setup_camera_light_perspective( glm::dmat4 &Viewmatrix ) {
|
||||
|
||||
m_renderpass.camera.position() = Global::pCameraPosition - glm::dvec3{ Global::DayLight.direction * m_renderpass.draw_range * 0.5f };
|
||||
m_renderpass.camera.position().y = std::max( 75.0, m_renderpass.camera.position().y ); // prevent shadow source from dipping too low
|
||||
Viewmatrix = glm::lookAt(
|
||||
m_renderpass.camera.position(),
|
||||
glm::dvec3{ Global::pCameraPosition.x, 0.0, Global::pCameraPosition.z },
|
||||
glm::dvec3{ 0.f, 1.f, 0.f } );
|
||||
}
|
||||
|
||||
void
|
||||
opengl_renderer::setup_drawing( bool const Alpha ) {
|
||||
|
||||
if( true == Alpha ) {
|
||||
|
||||
@@ -473,19 +602,6 @@ opengl_renderer::Render_setup( bool const Alpha ) {
|
||||
}
|
||||
else { ::glDisable( GL_FOG ); }
|
||||
|
||||
if( m_texenvmode != m_renderpass.draw_mode ) {
|
||||
// texture colour and alpha
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE );
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE );
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR );
|
||||
/*
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE );
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE );
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA );
|
||||
*/
|
||||
m_texenvmode = m_renderpass.draw_mode;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case rendermode::shadows:
|
||||
@@ -498,19 +614,6 @@ opengl_renderer::Render_setup( bool const Alpha ) {
|
||||
}
|
||||
::glDisable( GL_FOG );
|
||||
|
||||
if( m_texenvmode != m_renderpass.draw_mode ) {
|
||||
// solid colour with texture alpha
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE );
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR ); // or GL_PREVIOUS
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR );
|
||||
/*
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE );
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE );
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA );
|
||||
*/
|
||||
m_texenvmode = m_renderpass.draw_mode;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@@ -519,6 +622,169 @@ opengl_renderer::Render_setup( bool const Alpha ) {
|
||||
}
|
||||
}
|
||||
|
||||
// configures, enables and disables specified texture units
|
||||
void
|
||||
opengl_renderer::setup_units( bool const Diffuse, bool const Shadows, bool const Reflections ) {
|
||||
// helper texture unit.
|
||||
// darkens previous stage, preparing data for the shadow texture unit to select from
|
||||
if( m_helpertextureunit >= 0 ) {
|
||||
if( ( true == Global::RenderShadows ) && ( true == Shadows ) ) {
|
||||
// setup reflection texture unit
|
||||
::glActiveTexture( m_helpertextureunit );
|
||||
::glBindTexture( GL_TEXTURE_2D, m_reflectiontexture ); // TODO: move to reflection unit setup
|
||||
::glEnable( GL_TEXTURE_2D );
|
||||
/*
|
||||
glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
|
||||
glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
|
||||
glEnable( GL_TEXTURE_GEN_S );
|
||||
glEnable( GL_TEXTURE_GEN_T );
|
||||
*/
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
|
||||
::glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, glm::value_ptr( m_shadowcolor ) ); // TODO: dynamically calculated shadow colour, based on sun height
|
||||
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE ); // darken the previous stage
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS );
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR );
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT );
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR );
|
||||
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE ); // simply copy alpha from diffuse stage
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS );
|
||||
}
|
||||
else {
|
||||
::glActiveTexture( m_helpertextureunit );
|
||||
::glDisable( GL_TEXTURE_2D );
|
||||
/*
|
||||
::glDisable( GL_TEXTURE_GEN_S );
|
||||
::glDisable( GL_TEXTURE_GEN_T );
|
||||
::glDisable( GL_TEXTURE_GEN_R );
|
||||
::glDisable( GL_TEXTURE_GEN_Q );
|
||||
*/
|
||||
}
|
||||
}
|
||||
// shadow texture unit.
|
||||
// interpolates between primary colour and the previous unit, which should hold darkened variant of the primary colour
|
||||
if( m_shadowtextureunit >= 0 ) {
|
||||
if( ( true == Global::RenderShadows ) && ( true == Shadows ) ) {
|
||||
|
||||
::glActiveTexture( m_shadowtextureunit );
|
||||
::glBindTexture( GL_TEXTURE_2D, m_shadowtexture );
|
||||
::glEnable( GL_TEXTURE_2D );
|
||||
// s
|
||||
::glTexGenfv( GL_S, GL_EYE_PLANE, glm::value_ptr( glm::row( m_shadowtexturematrix, 0 ) ) );
|
||||
::glEnable( GL_TEXTURE_GEN_S );
|
||||
// t
|
||||
::glTexGenfv( GL_T, GL_EYE_PLANE, glm::value_ptr( glm::row( m_shadowtexturematrix, 1 ) ) );
|
||||
::glEnable( GL_TEXTURE_GEN_T );
|
||||
// r
|
||||
::glTexGenfv( GL_R, GL_EYE_PLANE, glm::value_ptr( glm::row( m_shadowtexturematrix, 2 ) ) );
|
||||
::glEnable( GL_TEXTURE_GEN_R );
|
||||
// q
|
||||
::glTexGenfv( GL_Q, GL_EYE_PLANE, glm::value_ptr( glm::row( m_shadowtexturematrix, 3 ) ) );
|
||||
::glEnable( GL_TEXTURE_GEN_Q );
|
||||
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE ); // choose between lit and lit * shadow colour, based on depth test
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR );
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR );
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS );
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR );
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_TEXTURE );
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR );
|
||||
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE ); // simply copy alpha from diffuse stage
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS );
|
||||
}
|
||||
else {
|
||||
// turn off shadow map tests
|
||||
::glActiveTexture( m_shadowtextureunit );
|
||||
|
||||
::glDisable( GL_TEXTURE_2D );
|
||||
::glDisable( GL_TEXTURE_GEN_S );
|
||||
::glDisable( GL_TEXTURE_GEN_T );
|
||||
::glDisable( GL_TEXTURE_GEN_R );
|
||||
::glDisable( GL_TEXTURE_GEN_Q );
|
||||
}
|
||||
}
|
||||
// diffuse texture unit.
|
||||
// NOTE: diffuse texture mapping is never fully disabled, alpha channel information is always included
|
||||
::glActiveTexture( m_diffusetextureunit );
|
||||
if( true == Diffuse ) {
|
||||
// default behaviour, modulate with previous stage
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE );
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE );
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR );
|
||||
/*
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE );
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE );
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA );
|
||||
*/
|
||||
}
|
||||
else {
|
||||
// solid colour with texture alpha
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE );
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS );
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR );
|
||||
/*
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE );
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE );
|
||||
::glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA );
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
// enables and disables specified texture units
|
||||
void
|
||||
opengl_renderer::toggle_units( bool const Diffuse, bool const Shadows, bool const Reflections ) {
|
||||
// helper texture unit.
|
||||
if( m_helpertextureunit >= 0 ) {
|
||||
if( ( true == Global::RenderShadows ) && ( true == Shadows ) ) {
|
||||
::glActiveTexture( m_helpertextureunit );
|
||||
::glEnable( GL_TEXTURE_2D );
|
||||
}
|
||||
else {
|
||||
::glActiveTexture( m_helpertextureunit );
|
||||
::glDisable( GL_TEXTURE_2D );
|
||||
}
|
||||
}
|
||||
// shadow texture unit.
|
||||
if( m_shadowtextureunit >= 0 ) {
|
||||
if( ( true == Global::RenderShadows ) && ( true == Shadows ) ) {
|
||||
|
||||
::glActiveTexture( m_shadowtextureunit );
|
||||
::glEnable( GL_TEXTURE_2D );
|
||||
}
|
||||
else {
|
||||
|
||||
::glActiveTexture( m_shadowtextureunit );
|
||||
::glDisable( GL_TEXTURE_2D );
|
||||
}
|
||||
}
|
||||
// diffuse texture unit.
|
||||
// NOTE: toggle actually disables diffuse texture mapping, unlike setup counterpart
|
||||
if( true == Diffuse ) {
|
||||
|
||||
::glActiveTexture( m_diffusetextureunit );
|
||||
::glEnable( GL_TEXTURE_2D );
|
||||
}
|
||||
else {
|
||||
|
||||
::glActiveTexture( m_diffusetextureunit );
|
||||
::glDisable( GL_TEXTURE_2D );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
opengl_renderer::setup_shadow_color( glm::vec4 const &Shadowcolor ) {
|
||||
|
||||
::glActiveTexture( m_helpertextureunit );
|
||||
::glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, glm::value_ptr( Shadowcolor ) ); // in-shadow colour multiplier
|
||||
::glActiveTexture( m_diffusetextureunit );
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
opengl_renderer::Render( world_environment *Environment ) {
|
||||
|
||||
@@ -587,10 +853,10 @@ opengl_renderer::Render( world_environment *Environment ) {
|
||||
|
||||
float const size = 0.045f;
|
||||
::glBegin( GL_TRIANGLE_STRIP );
|
||||
::glTexCoord2f( 1.0f, 1.0f ); ::glVertex3f( -size, size, 0.0f );
|
||||
::glTexCoord2f( 1.0f, 0.0f ); ::glVertex3f( -size, -size, 0.0f );
|
||||
::glTexCoord2f( 0.0f, 1.0f ); ::glVertex3f( size, size, 0.0f );
|
||||
::glTexCoord2f( 0.0f, 0.0f ); ::glVertex3f( size, -size, 0.0f );
|
||||
::glMultiTexCoord2f( m_diffusetextureunit, 1.f, 1.f ); ::glVertex3f( -size, size, 0.f );
|
||||
::glMultiTexCoord2f( m_diffusetextureunit, 1.f, 0.f ); ::glVertex3f( -size, -size, 0.f );
|
||||
::glMultiTexCoord2f( m_diffusetextureunit, 0.f, 1.f ); ::glVertex3f( size, size, 0.f );
|
||||
::glMultiTexCoord2f( m_diffusetextureunit, 0.f, 0.f ); ::glVertex3f( size, -size, 0.f );
|
||||
::glEnd();
|
||||
|
||||
::glPopMatrix();
|
||||
@@ -623,10 +889,10 @@ opengl_renderer::Render( world_environment *Environment ) {
|
||||
else { moonv = 1.0f - 0.0f; moonu = 0.0f; }
|
||||
|
||||
::glBegin( GL_TRIANGLE_STRIP );
|
||||
::glTexCoord2f( moonu, moonv ); ::glVertex3f( -size, size, 0.0f );
|
||||
::glTexCoord2f( moonu, moonv - 0.333f ); ::glVertex3f( -size, -size, 0.0f );
|
||||
::glTexCoord2f( moonu + 0.333f, moonv ); ::glVertex3f( size, size, 0.0f );
|
||||
::glTexCoord2f( moonu + 0.333f, moonv - 0.333f ); ::glVertex3f( size, -size, 0.0f );
|
||||
::glMultiTexCoord2f( m_diffusetextureunit, moonu, moonv ); ::glVertex3f( -size, size, 0.0f );
|
||||
::glMultiTexCoord2f( m_diffusetextureunit, moonu, moonv - 0.333f ); ::glVertex3f( -size, -size, 0.0f );
|
||||
::glMultiTexCoord2f( m_diffusetextureunit, moonu + 0.333f, moonv ); ::glVertex3f( size, size, 0.0f );
|
||||
::glMultiTexCoord2f( m_diffusetextureunit, moonu + 0.333f, moonv - 0.333f ); ::glVertex3f( size, -size, 0.0f );
|
||||
::glEnd();
|
||||
|
||||
::glPopMatrix();
|
||||
@@ -831,21 +1097,23 @@ opengl_renderer::Render( TGroundRect *Groundcell ) {
|
||||
case rendermode::pickscenery: {
|
||||
// non-interactive scenery elements get neutral colour
|
||||
::glColor3fv( glm::value_ptr( colors::none ) );
|
||||
break;
|
||||
}
|
||||
case rendermode::shadows:
|
||||
case rendermode::color:
|
||||
case rendermode::color: {
|
||||
if( Groundcell->nRenderRect != nullptr ) {
|
||||
// nieprzezroczyste trójkąty kwadratu kilometrowego
|
||||
for( TGroundNode *node = Groundcell->nRenderRect; node != nullptr; node = node->nNext3 ) {
|
||||
Render( node );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case rendermode::pickcontrols:
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( Groundcell->nRenderRect != nullptr ) {
|
||||
// nieprzezroczyste trójkąty kwadratu kilometrowego
|
||||
for( TGroundNode *node = Groundcell->nRenderRect; node != nullptr; node = node->nNext3 ) {
|
||||
Render( node );
|
||||
}
|
||||
}
|
||||
|
||||
if( Groundcell->nTerrain ) {
|
||||
|
||||
Render( Groundcell->nTerrain );
|
||||
@@ -969,7 +1237,18 @@ opengl_renderer::Render( TGroundNode *Node ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
double const distancesquared = SquareMagnitude( ( Node->pCenter - m_renderpass.camera.position() ) / Global::ZoomFactor );
|
||||
double distancesquared;
|
||||
switch( m_renderpass.draw_mode ) {
|
||||
case rendermode::shadows: {
|
||||
// 'camera' for the light pass is the light source, but we need distance from actual camera
|
||||
distancesquared = SquareMagnitude( ( Node->pCenter - Global::pCameraPosition ) / Global::ZoomFactor );
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
distancesquared = SquareMagnitude( ( Node->pCenter - m_renderpass.camera.position() ) / Global::ZoomFactor );
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( ( distancesquared > ( Node->fSquareRadius * Global::fDistanceFactor ) )
|
||||
|| ( distancesquared < ( Node->fSquareMinRadius / Global::fDistanceFactor ) ) ) {
|
||||
return false;
|
||||
@@ -1015,8 +1294,30 @@ opengl_renderer::Render( TGroundNode *Node ) {
|
||||
#else
|
||||
Node->Model->RaAnimate(); // jednorazowe przeliczenie animacji
|
||||
Node->Model->RaPrepare();
|
||||
if( Node->Model->pModel ) // renderowanie rekurencyjne submodeli
|
||||
Render( Node->Model->pModel, Node->Model->Material(), Node->pCenter - m_renderpass.camera.position(), Node->Model->vAngle );
|
||||
if( Node->Model->pModel ) {
|
||||
// renderowanie rekurencyjne submodeli
|
||||
switch( m_renderpass.draw_mode ) {
|
||||
case rendermode::shadows: {
|
||||
Render(
|
||||
Node->Model->pModel,
|
||||
Node->Model->Material(),
|
||||
SquareMagnitude( Node->pCenter - Global::pCameraPosition ),
|
||||
Node->pCenter - m_renderpass.camera.position(),
|
||||
Node->Model->vAngle );
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
auto const position = Node->pCenter - m_renderpass.camera.position();
|
||||
Render(
|
||||
Node->Model->pModel,
|
||||
Node->Model->Material(),
|
||||
SquareMagnitude( position ),
|
||||
position,
|
||||
Node->Model->vAngle );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
@@ -1154,11 +1455,20 @@ opengl_renderer::Render( TDynamicObject *Dynamic ) {
|
||||
if( false == Dynamic->renderme ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// setup
|
||||
TSubModel::iInstance = ( size_t )this; //żeby nie robić cudzych animacji
|
||||
auto const originoffset = Dynamic->vPosition - m_renderpass.camera.position();
|
||||
double const squaredistance = SquareMagnitude( originoffset / Global::ZoomFactor );
|
||||
double squaredistance;
|
||||
switch( m_renderpass.draw_mode ) {
|
||||
case rendermode::shadows: {
|
||||
squaredistance = SquareMagnitude( ( Dynamic->vPosition - Global::pCameraPosition ) / Global::ZoomFactor );
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
squaredistance = SquareMagnitude( originoffset / Global::ZoomFactor );
|
||||
break;
|
||||
}
|
||||
}
|
||||
Dynamic->ABuLittleUpdate( squaredistance ); // ustawianie zmiennych submodeli dla wspólnego modelu
|
||||
::glPushMatrix();
|
||||
|
||||
@@ -1342,7 +1652,7 @@ opengl_renderer::Render( TModel3d *Model, material_data const *Material, double
|
||||
}
|
||||
|
||||
bool
|
||||
opengl_renderer::Render( TModel3d *Model, material_data const *Material, Math3D::vector3 const &Position, Math3D::vector3 const &Angle ) {
|
||||
opengl_renderer::Render( TModel3d *Model, material_data const *Material, double const Squaredistance, Math3D::vector3 const &Position, Math3D::vector3 const &Angle ) {
|
||||
|
||||
::glPushMatrix();
|
||||
::glTranslated( Position.x, Position.y, Position.z );
|
||||
@@ -1353,7 +1663,7 @@ opengl_renderer::Render( TModel3d *Model, material_data const *Material, Math3D:
|
||||
if( Angle.z != 0.0 )
|
||||
::glRotated( Angle.z, 0.0, 0.0, 1.0 );
|
||||
|
||||
auto const result = Render( Model, Material, SquareMagnitude( Position ) ); // position is effectively camera offset
|
||||
auto const result = Render( Model, Material, Squaredistance );
|
||||
|
||||
::glPopMatrix();
|
||||
|
||||
@@ -1417,6 +1727,8 @@ opengl_renderer::Render( TSubModel *Submodel ) {
|
||||
if( Global::fLuminance < Submodel->fLight ) {
|
||||
// zeby swiecilo na kolorowo
|
||||
::glMaterialfv( GL_FRONT, GL_EMISSION, glm::value_ptr( Submodel->f4Diffuse * Submodel->f4Emision.a ) );
|
||||
// disable shadows so they don't obstruct self-lit items
|
||||
setup_shadow_color( colors::white );
|
||||
}
|
||||
|
||||
// main draw call
|
||||
@@ -1429,6 +1741,7 @@ opengl_renderer::Render( TSubModel *Submodel ) {
|
||||
if( Global::fLuminance < Submodel->fLight ) {
|
||||
// restore default (lack of) brightness
|
||||
::glMaterialfv( GL_FRONT, GL_EMISSION, glm::value_ptr( colors::none ) );
|
||||
setup_shadow_color( m_shadowcolor );
|
||||
}
|
||||
#ifdef EU07_USE_OPTIMIZED_NORMALIZATION
|
||||
switch( Submodel->m_normalizenormals ) {
|
||||
@@ -1524,10 +1837,14 @@ opengl_renderer::Render( TSubModel *Submodel ) {
|
||||
::glLoadIdentity();
|
||||
::glTranslatef( lightcenter.x, lightcenter.y, lightcenter.z ); // początek układu zostaje bez zmian
|
||||
|
||||
setup_shadow_color( colors::white );
|
||||
|
||||
// main draw call
|
||||
m_geometry.draw( Submodel->m_geometry );
|
||||
|
||||
// post-draw reset
|
||||
// re-enable shadows
|
||||
setup_shadow_color( m_shadowcolor );
|
||||
::glPopMatrix();
|
||||
::glPopAttrib();
|
||||
}
|
||||
@@ -1709,7 +2026,18 @@ opengl_renderer::Render_Alpha( TSubRect *Groundsubcell ) {
|
||||
bool
|
||||
opengl_renderer::Render_Alpha( TGroundNode *Node ) {
|
||||
|
||||
double const distancesquared = SquareMagnitude( ( Node->pCenter - m_renderpass.camera.position() ) / Global::ZoomFactor );
|
||||
double distancesquared;
|
||||
switch( m_renderpass.draw_mode ) {
|
||||
case rendermode::shadows: {
|
||||
// 'camera' for the light pass is the light source, but we need distance from actual camera
|
||||
distancesquared = SquareMagnitude( ( Node->pCenter - Global::pCameraPosition ) / Global::ZoomFactor );
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
distancesquared = SquareMagnitude( ( Node->pCenter - m_renderpass.camera.position() ) / Global::ZoomFactor );
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( ( distancesquared > ( Node->fSquareRadius * Global::fDistanceFactor ) )
|
||||
|| ( distancesquared < ( Node->fSquareMinRadius / Global::fDistanceFactor ) ) ) {
|
||||
return false;
|
||||
@@ -1766,8 +2094,30 @@ opengl_renderer::Render_Alpha( TGroundNode *Node ) {
|
||||
Node->Model->RenderAlpha( Node->pCenter - m_renderpass.camera.position() );
|
||||
#else
|
||||
Node->Model->RaPrepare();
|
||||
if( Node->Model->pModel ) // renderowanie rekurencyjne submodeli
|
||||
Render_Alpha( Node->Model->pModel, Node->Model->Material(), Node->pCenter - m_renderpass.camera.position(), Node->Model->vAngle );
|
||||
if( Node->Model->pModel ) {
|
||||
// renderowanie rekurencyjne submodeli
|
||||
switch( m_renderpass.draw_mode ) {
|
||||
case rendermode::shadows: {
|
||||
Render_Alpha(
|
||||
Node->Model->pModel,
|
||||
Node->Model->Material(),
|
||||
SquareMagnitude( Node->pCenter - Global::pCameraPosition ),
|
||||
Node->pCenter - m_renderpass.camera.position(),
|
||||
Node->Model->vAngle );
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
auto const position = Node->pCenter - m_renderpass.camera.position();
|
||||
Render_Alpha(
|
||||
Node->Model->pModel,
|
||||
Node->Model->Material(),
|
||||
SquareMagnitude( position ),
|
||||
position,
|
||||
Node->Model->vAngle );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
@@ -1848,7 +2198,17 @@ opengl_renderer::Render_Alpha( TDynamicObject *Dynamic ) {
|
||||
// setup
|
||||
TSubModel::iInstance = ( size_t )this; //żeby nie robić cudzych animacji
|
||||
auto const originoffset = Dynamic->vPosition - m_renderpass.camera.position();
|
||||
double const squaredistance = SquareMagnitude( originoffset / Global::ZoomFactor );
|
||||
double squaredistance;
|
||||
switch( m_renderpass.draw_mode ) {
|
||||
case rendermode::shadows: {
|
||||
squaredistance = SquareMagnitude( ( Dynamic->vPosition - Global::pCameraPosition ) / Global::ZoomFactor );
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
squaredistance = SquareMagnitude( originoffset / Global::ZoomFactor );
|
||||
break;
|
||||
}
|
||||
}
|
||||
Dynamic->ABuLittleUpdate( squaredistance ); // ustawianie zmiennych submodeli dla wspólnego modelu
|
||||
::glPushMatrix();
|
||||
|
||||
@@ -1936,7 +2296,7 @@ opengl_renderer::Render_Alpha( TModel3d *Model, material_data const *Material, d
|
||||
}
|
||||
|
||||
bool
|
||||
opengl_renderer::Render_Alpha( TModel3d *Model, material_data const *Material, Math3D::vector3 const &Position, Math3D::vector3 const &Angle ) {
|
||||
opengl_renderer::Render_Alpha( TModel3d *Model, material_data const *Material, double const Squaredistance, Math3D::vector3 const &Position, Math3D::vector3 const &Angle ) {
|
||||
|
||||
::glPushMatrix();
|
||||
::glTranslated( Position.x, Position.y, Position.z );
|
||||
@@ -1947,7 +2307,7 @@ opengl_renderer::Render_Alpha( TModel3d *Model, material_data const *Material, M
|
||||
if( Angle.z != 0.0 )
|
||||
::glRotated( Angle.z, 0.0, 0.0, 1.0 );
|
||||
|
||||
auto const result = Render_Alpha( Model, Material, SquareMagnitude( Position ) ); // position is effectively camera offset
|
||||
auto const result = Render_Alpha( Model, Material, Squaredistance ); // position is effectively camera offset
|
||||
|
||||
::glPopMatrix();
|
||||
|
||||
@@ -2006,6 +2366,8 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) {
|
||||
if( Global::fLuminance < Submodel->fLight ) {
|
||||
// zeby swiecilo na kolorowo
|
||||
::glMaterialfv( GL_FRONT, GL_EMISSION, glm::value_ptr( Submodel->f4Diffuse * Submodel->f4Emision.a ) );
|
||||
// disable shadows so they don't obstruct self-lit items
|
||||
setup_shadow_color( colors::white );
|
||||
}
|
||||
|
||||
// main draw call
|
||||
@@ -2018,6 +2380,7 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) {
|
||||
if( Global::fLuminance < Submodel->fLight ) {
|
||||
// restore default (lack of) brightness
|
||||
::glMaterialfv( GL_FRONT, GL_EMISSION, glm::value_ptr( colors::none ) );
|
||||
setup_shadow_color( m_shadowcolor );
|
||||
}
|
||||
#ifdef EU07_USE_OPTIMIZED_NORMALIZATION
|
||||
switch( Submodel->m_normalizenormals ) {
|
||||
@@ -2068,6 +2431,8 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) {
|
||||
::glLoadIdentity(); // macierz jedynkowa
|
||||
::glTranslatef( lightcenter.x, lightcenter.y, lightcenter.z ); // początek układu zostaje bez zmian
|
||||
::glRotated( std::atan2( lightcenter.x, lightcenter.z ) * 180.0 / M_PI, 0.0, 1.0, 0.0 ); // jedynie obracamy w pionie o kąt
|
||||
// disable shadows so they don't obstruct self-lit items
|
||||
setup_shadow_color( colors::white );
|
||||
|
||||
// main draw call
|
||||
m_geometry.draw( m_billboardgeometry );
|
||||
@@ -2080,6 +2445,8 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) {
|
||||
// ...etc instead IF we had easy access to camera's forward and right vectors. TODO: check if Camera matrix is accessible
|
||||
*/
|
||||
// post-render cleanup
|
||||
setup_shadow_color( m_shadowcolor );
|
||||
|
||||
::glPopMatrix();
|
||||
::glPopAttrib();
|
||||
}
|
||||
@@ -2293,7 +2660,7 @@ opengl_renderer::Update( double const Deltatime ) {
|
||||
};
|
||||
|
||||
// debug performance string
|
||||
std::string const &
|
||||
std::string
|
||||
opengl_renderer::Info() const {
|
||||
|
||||
return m_debuginfo;
|
||||
@@ -2397,15 +2764,36 @@ opengl_renderer::Init_caps() {
|
||||
else {
|
||||
WriteLog( "Framebuffer objects not supported, resorting to back buffer rendering where possible" );
|
||||
}
|
||||
if( Global::iMultisampling )
|
||||
WriteLog( "Using multisampling x" + std::to_string( 1 << Global::iMultisampling ) );
|
||||
// ograniczenie maksymalnego rozmiaru tekstur - parametr dla skalowania tekstur
|
||||
{
|
||||
GLint i;
|
||||
glGetIntegerv( GL_MAX_TEXTURE_SIZE, &i );
|
||||
if( i < Global::iMaxTextureSize )
|
||||
Global::iMaxTextureSize = i;
|
||||
GLint texturesize;
|
||||
::glGetIntegerv( GL_MAX_TEXTURE_SIZE, &texturesize );
|
||||
Global::iMaxTextureSize = std::min( Global::iMaxTextureSize, texturesize );
|
||||
WriteLog( "Texture sizes capped at " + std::to_string( Global::iMaxTextureSize ) + " pixels" );
|
||||
m_shadowbuffersize = Global::shadowtune.map_size;
|
||||
m_shadowbuffersize = std::min( m_shadowbuffersize, texturesize );
|
||||
WriteLog( "Shadows map size capped at " + std::to_string( m_shadowbuffersize ) + " pixels" );
|
||||
}
|
||||
// cap the number of supported lights based on hardware
|
||||
{
|
||||
GLint maxlights;
|
||||
::glGetIntegerv( GL_MAX_LIGHTS, &maxlights );
|
||||
Global::DynamicLightCount = std::min( Global::DynamicLightCount, maxlights - 1 );
|
||||
WriteLog( "Dynamic light amount capped at " + std::to_string( Global::DynamicLightCount ) + " (" + std::to_string(maxlights) + " lights total supported by the gfx card)" );
|
||||
}
|
||||
{
|
||||
GLint maxtextureunits;
|
||||
::glGetIntegerv( GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxtextureunits );
|
||||
if( maxtextureunits < 4 ) {
|
||||
WriteLog( "Less than 4 texture units, shadow and reflection mapping will be disabled" );
|
||||
Global::RenderShadows = false;
|
||||
m_diffusetextureunit = GL_TEXTURE0;
|
||||
m_shadowtextureunit = -1;
|
||||
m_helpertextureunit = -1;
|
||||
}
|
||||
}
|
||||
if( Global::iMultisampling ) {
|
||||
WriteLog( "Using multisampling x" + std::to_string( 1 << Global::iMultisampling ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
41
renderer.h
41
renderer.h
@@ -159,7 +159,7 @@ public:
|
||||
TGroundNode const *
|
||||
Update_Pick_Node();
|
||||
// debug performance string
|
||||
std::string const &
|
||||
std::string
|
||||
Info() const;
|
||||
|
||||
// members
|
||||
@@ -169,6 +169,7 @@ public:
|
||||
private:
|
||||
// types
|
||||
enum class rendermode {
|
||||
none,
|
||||
color,
|
||||
shadows,
|
||||
pickcontrols,
|
||||
@@ -194,12 +195,30 @@ private:
|
||||
Render_pass( rendermode const Mode );
|
||||
// configures projection matrix for the current render pass
|
||||
void
|
||||
Render_projection();
|
||||
setup_projection();
|
||||
void
|
||||
setup_projection_world();
|
||||
void
|
||||
setup_projection_light_ortho();
|
||||
void
|
||||
setup_projection_light_perspective();
|
||||
// configures camera for the current render pass
|
||||
void
|
||||
Render_camera();
|
||||
setup_camera();
|
||||
void
|
||||
Render_setup( bool const Alpha = false );
|
||||
setup_camera_world( glm::dmat4 &Viewmatrix );
|
||||
void
|
||||
setup_camera_light_ortho( glm::dmat4 &Viewmatrix );
|
||||
void
|
||||
setup_camera_light_perspective( glm::dmat4 &Viewmatrix );
|
||||
void
|
||||
setup_drawing( bool const Alpha = false );
|
||||
void
|
||||
setup_units( bool const Diffuse, bool const Shadows, bool const Reflections );
|
||||
void
|
||||
setup_shadow_color( glm::vec4 const &Shadowcolor );
|
||||
void
|
||||
toggle_units( bool const Diffuse, bool const Shadows, bool const Reflections );
|
||||
bool
|
||||
Render( world_environment *Environment );
|
||||
bool
|
||||
@@ -213,7 +232,7 @@ private:
|
||||
bool
|
||||
Render( TDynamicObject *Dynamic );
|
||||
bool
|
||||
Render( TModel3d *Model, material_data const *Material, Math3D::vector3 const &Position, Math3D::vector3 const &Angle );
|
||||
Render( TModel3d *Model, material_data const *Material, double const Squaredistance, Math3D::vector3 const &Position, Math3D::vector3 const &Angle );
|
||||
bool
|
||||
Render( TModel3d *Model, material_data const *Material, double const Squaredistance );
|
||||
void
|
||||
@@ -233,7 +252,7 @@ private:
|
||||
bool
|
||||
Render_Alpha( TDynamicObject *Dynamic );
|
||||
bool
|
||||
Render_Alpha( TModel3d *Model, material_data const *Material, Math3D::vector3 const &Position, Math3D::vector3 const &Angle );
|
||||
Render_Alpha( TModel3d *Model, material_data const *Material, double const Squaredistance, Math3D::vector3 const &Position, Math3D::vector3 const &Angle );
|
||||
bool
|
||||
Render_Alpha( TModel3d *Model, material_data const *Material, double const Squaredistance );
|
||||
void
|
||||
@@ -257,13 +276,19 @@ private:
|
||||
#endif
|
||||
GLuint m_shadowframebuffer { 0 };
|
||||
GLuint m_shadowtexture { 0 };
|
||||
int m_shadowbuffersize { 2048 };
|
||||
int m_shadowbuffersize { 4096 };
|
||||
glm::mat4 m_shadowtexturematrix;
|
||||
glm::vec4 m_shadowcolor{ 0.5f, 0.5f, 0.5f, 1.f };
|
||||
GLUquadricObj *m_quadric { nullptr }; // helper object for drawing debug mode scene elements
|
||||
int m_shadowtextureunit { GL_TEXTURE1 };
|
||||
int m_helpertextureunit { GL_TEXTURE0 };
|
||||
int m_diffusetextureunit { GL_TEXTURE2 };
|
||||
|
||||
geometry_handle m_billboardgeometry { 0, 0 };
|
||||
texture_handle m_glaretexture { -1 };
|
||||
texture_handle m_suntexture { -1 };
|
||||
texture_handle m_moontexture { -1 };
|
||||
texture_handle m_reflectiontexture { -1 };
|
||||
|
||||
float m_drawtime { 1000.0f / 30.0f * 20.0f }; // start with presumed 'neutral' average of 30 fps
|
||||
double m_updateaccumulator { 0.0 };
|
||||
@@ -274,9 +299,7 @@ private:
|
||||
float m_speculartranslucentscalefactor { 1.0f };
|
||||
|
||||
bool m_framebuffersupport { false };
|
||||
rendermode m_texenvmode { rendermode::color }; // last configured texture environment
|
||||
renderpass_config m_renderpass;
|
||||
// std::stack<renderpass_config> m_renderpasses;
|
||||
bool m_renderspecular { false }; // controls whether to include specular component in the calculations
|
||||
std::vector<TGroundNode const *> m_picksceneryitems;
|
||||
std::vector<TSubModel const *> m_pickcontrolsitems;
|
||||
|
||||
10
uilayer.cpp
10
uilayer.cpp
@@ -65,7 +65,7 @@ ui_layer::render() {
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho( 0.f, Global::ScreenWidth, Global::ScreenHeight, 0.f, -1.f, 1.f );
|
||||
glOrtho( 0, Global::ScreenWidth, Global::ScreenHeight, 0, -1, 1 );
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
@@ -272,10 +272,10 @@ ui_layer::quad( float4 const &Coordinates, float4 const &Color ) {
|
||||
|
||||
glBegin( GL_TRIANGLE_STRIP );
|
||||
|
||||
glTexCoord2f( 0.f, 1.f ); glVertex2f( 0.5f * ( Global::iWindowWidth - width ) + Coordinates.x * heightratio, 0.5f * ( Global::iWindowHeight - height ) + Coordinates.y * heightratio );
|
||||
glTexCoord2f( 0.f, 0.f ); glVertex2f( 0.5f * ( Global::iWindowWidth - width ) + Coordinates.x * heightratio, 0.5f * ( Global::iWindowHeight - height ) + Coordinates.w * heightratio );
|
||||
glTexCoord2f( 1.f, 1.f ); glVertex2f( 0.5f * ( Global::iWindowWidth - width ) + Coordinates.z * heightratio, 0.5f * ( Global::iWindowHeight - height ) + Coordinates.y * heightratio );
|
||||
glTexCoord2f( 1.f, 0.f ); glVertex2f( 0.5f * ( Global::iWindowWidth - width ) + Coordinates.z * heightratio, 0.5f * ( Global::iWindowHeight - height ) + Coordinates.w * heightratio );
|
||||
glMultiTexCoord2f( m_textureunit, 0.f, 1.f ); glVertex2f( 0.5f * ( Global::iWindowWidth - width ) + Coordinates.x * heightratio, 0.5f * ( Global::iWindowHeight - height ) + Coordinates.y * heightratio );
|
||||
glMultiTexCoord2f( m_textureunit, 0.f, 0.f ); glVertex2f( 0.5f * ( Global::iWindowWidth - width ) + Coordinates.x * heightratio, 0.5f * ( Global::iWindowHeight - height ) + Coordinates.w * heightratio );
|
||||
glMultiTexCoord2f( m_textureunit, 1.f, 1.f ); glVertex2f( 0.5f * ( Global::iWindowWidth - width ) + Coordinates.z * heightratio, 0.5f * ( Global::iWindowHeight - height ) + Coordinates.y * heightratio );
|
||||
glMultiTexCoord2f( m_textureunit, 1.f, 0.f ); glVertex2f( 0.5f * ( Global::iWindowWidth - width ) + Coordinates.z * heightratio, 0.5f * ( Global::iWindowHeight - height ) + Coordinates.w * heightratio );
|
||||
|
||||
glEnd();
|
||||
}
|
||||
|
||||
@@ -41,6 +41,8 @@ public:
|
||||
// methods:
|
||||
bool
|
||||
init( GLFWwindow *Window );
|
||||
void
|
||||
set_unit( GLint const Textureunit ) { m_textureunit = Textureunit; }
|
||||
// draws requested UI elements
|
||||
void
|
||||
render();
|
||||
@@ -83,6 +85,7 @@ private:
|
||||
|
||||
// members:
|
||||
GLFWwindow *m_window { nullptr };
|
||||
GLint m_textureunit{ GL_TEXTURE0 };
|
||||
GLuint m_fontbase { (GLuint)-1 }; // numer DL dla znaków w napisach
|
||||
|
||||
// progress bar config. TODO: put these together into an object
|
||||
|
||||
Reference in New Issue
Block a user