16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-23 19:09:18 +02:00

opengl 3.3 renderer integration, minor renderer tweaks

This commit is contained in:
tmj-fstate
2019-10-31 19:37:53 +01:00
parent 9dcaa1e339
commit ae3cecfa42
49 changed files with 1804 additions and 412 deletions

4
.gitignore vendored
View File

@@ -55,8 +55,8 @@ install_manifest.txt
*.opensdf *.opensdf
*.sdf *.sdf
*.sln *.sln
*.vcxproj #*.vcxproj
*.filters #*.filters
format_all_files.py format_all_files.py
*.suo *.suo
EU07.tds EU07.tds

View File

@@ -338,10 +338,9 @@ global_settings::ConfigParse(cParser &Parser) {
} }
else if( token == "gfxrenderer" ) { else if( token == "gfxrenderer" ) {
// shadow render toggle // shadow render toggle
std::string gfxrenderer;
Parser.getTokens(); Parser.getTokens();
Parser >> gfxrenderer; Parser >> GfxRenderer;
BasicRenderer = ( gfxrenderer == "simple" ); BasicRenderer = ( GfxRenderer == "simple" );
} }
else if( token == "shadows" ) { else if( token == "shadows" ) {
// shadow render toggle // shadow render toggle

View File

@@ -49,6 +49,7 @@ struct global_settings {
std::string asCurrentSceneryPath{ "scenery/" }; std::string asCurrentSceneryPath{ "scenery/" };
std::string asCurrentTexturePath{ szTexturePath }; std::string asCurrentTexturePath{ szTexturePath };
std::string asCurrentDynamicPath; std::string asCurrentDynamicPath;
bool GfxFramebufferSRGB { true };
// settings // settings
// filesystem // filesystem
bool bLoadTraction{ true }; bool bLoadTraction{ true };
@@ -107,6 +108,7 @@ struct global_settings {
float BaseDrawRange{ 2500.f }; float BaseDrawRange{ 2500.f };
int DynamicLightCount{ 3 }; int DynamicLightCount{ 3 };
bool ScaleSpecularValues{ true }; bool ScaleSpecularValues{ true };
std::string GfxRenderer{ "default" };
bool BasicRenderer{ false }; bool BasicRenderer{ false };
bool RenderShadows{ true }; bool RenderShadows{ true };
int RenderCabShadowsRange{ 0 }; int RenderCabShadowsRange{ 0 };

View File

@@ -90,6 +90,30 @@ TSubModel::SetDiffuseOverride( glm::vec3 const &Color, bool const Includechildre
} }
} }
std::optional<glm::vec3>
TSubModel::GetDiffuse(float Includesiblings) {
if (eType == TP_FREESPOTLIGHT) {
if (DiffuseOverride.x >= 0.0f)
return DiffuseOverride;
else
return glm::vec3(f4Diffuse);
}
if (Includesiblings) {
auto sibling = this;
while ((sibling = sibling->Next)) {
auto result = sibling->GetDiffuse(true);
if (result)
return result;
}
}
if (Child)
return Child->GetDiffuse(true);
return std::nullopt;
}
// sets visibility level (alpha component) to specified value // sets visibility level (alpha component) to specified value
void void
TSubModel::SetVisibilityLevel( float const Level, bool const Includechildren, bool const Includesiblings ) { TSubModel::SetVisibilityLevel( float const Level, bool const Includechildren, bool const Includesiblings ) {
@@ -335,7 +359,8 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
std::string material = parser.getToken<std::string>(); std::string material = parser.getToken<std::string>();
if (material == "none") if (material == "none")
{ // rysowanie podanym kolorem { // rysowanie podanym kolorem
m_material = null_handle; Name_Material( "colored" );
m_material = GfxRenderer->Fetch_Material( m_materialname );
iFlags |= 0x10; // rysowane w cyklu nieprzezroczystych iFlags |= 0x10; // rysowane w cyklu nieprzezroczystych
} }
else if (material.find("replacableskin") != material.npos) else if (material.find("replacableskin") != material.npos)
@@ -374,11 +399,18 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
m_material = GfxRenderer->Fetch_Material( material ); m_material = GfxRenderer->Fetch_Material( material );
// renderowanie w cyklu przezroczystych tylko jeśli: // renderowanie w cyklu przezroczystych tylko jeśli:
// 1. Opacity=0 (przejściowo <1, czy tam <100) oraz // 1. Opacity=0 (przejściowo <1, czy tam <100) oraz
iFlags |= ( // 2. tekstura ma przezroczystość
Opacity < 0.999f ? iFlags |= (
( ( Opacity < 0.01f )
&& ( ( m_material != null_handle )
&& ( GfxRenderer->Material( m_material ).is_translucent() ) ) ) ?
0x20 : 0x20 :
0x10 ); // 0x20-przezroczysta, 0x10-nieprzezroczysta 0x10 ); // 0x10-nieprzezroczysta, 0x20-przezroczysta
}; };
}
else if( eType == TP_STARS ) {
m_material = GfxRenderer->Fetch_Material( "stars" );
iFlags |= 0x10;
} }
else { else {
iFlags |= 0x10; iFlags |= 0x10;
@@ -387,17 +419,26 @@ int TSubModel::Load( cParser &parser, TModel3d *Model, /*int Pos,*/ bool dynamic
if (m_material > 0) if (m_material > 0)
{ {
opengl_material const &mat = GfxRenderer->Material(m_material); opengl_material const &mat = GfxRenderer->Material(m_material);
/*
// if material have opacity set, replace submodel opacity with it if( eType == TP_FREESPOTLIGHT ) {
if (!std::isnan(mat.opacity))
{
iFlags &= ~0x30; iFlags &= ~0x30;
if (mat.opacity == 0.0f) iFlags |= 0x20;
iFlags |= 0x20; // translucent }
else else
iFlags |= 0x10; // opaque */
{
// if material has opacity set, replace submodel opacity with it
auto const opacity { (
false == std::isnan( mat.opacity ) ?
mat.opacity :
Opacity ) };
iFlags &= ~0x30;
iFlags |= (
( ( opacity < 0.01f )
&& ( GfxRenderer->Material( m_material ).is_translucent() ) ) ?
0x20 :
0x10 ); // 0x10-nieprzezroczysta, 0x20-przezroczysta
} }
// and same thing with selfillum // and same thing with selfillum
if (!std::isnan(mat.selfillum)) if (!std::isnan(mat.selfillum))
fLight = mat.selfillum; fLight = mat.selfillum;
@@ -1802,25 +1843,25 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, std::vector<std::string> *t,
} }
*/ */
m_material = GfxRenderer->Fetch_Material( m_materialname ); m_material = GfxRenderer->Fetch_Material( m_materialname );
// if we don't have phase flags set for some reason, try to fix it // if we don't have phase flags set for some reason, try to fix it
if (!(iFlags & 0x30) && m_material != null_handle) if (!(iFlags & 0x30) && m_material != null_handle)
{ {
opengl_material const &mat = GfxRenderer->Material(m_material); /*
float opacity = mat.opacity; if( eType == TP_FREESPOTLIGHT ) {
iFlags &= ~0x30;
// if material don't have opacity set, try to guess it iFlags |= 0x20;
if (std::isnan(opacity)) }
opacity = mat.get_or_guess_opacity();
// set phase flag based on material opacity
if (opacity == 0.0f)
iFlags |= 0x20; // translucent
else else
iFlags |= 0x10; // opaque */
{
// texture-alpha based fallback if for some reason we don't have opacity flag set yet
iFlags |= (
GfxRenderer->Material( m_material ).is_translucent() ?
0x20 :
0x10 ); // 0x10-nieprzezroczysta, 0x20-przezroczysta
}
} }
if ( m_material != null_handle )
if (m_material > 0)
{ {
opengl_material const &mat = GfxRenderer->Material(m_material); opengl_material const &mat = GfxRenderer->Material(m_material);
@@ -1835,7 +1876,12 @@ void TSubModel::BinInit(TSubModel *s, float4x4 *m, std::vector<std::string> *t,
} }
} }
else else
m_material = iTexture; {
if( iTexture == 0 )
m_material = GfxRenderer->Fetch_Material( "colored" );
else
m_material = iTexture;
}
b_aAnim = b_Anim; // skopiowanie animacji do drugiego cyklu b_aAnim = b_Anim; // skopiowanie animacji do drugiego cyklu

View File

@@ -208,6 +208,8 @@ public:
void ColorsSet( glm::vec3 const &Ambient, glm::vec3 const &Diffuse, glm::vec3 const &Specular ); void ColorsSet( glm::vec3 const &Ambient, glm::vec3 const &Diffuse, glm::vec3 const &Specular );
// sets rgb components of diffuse color override to specified value // sets rgb components of diffuse color override to specified value
void SetDiffuseOverride( glm::vec3 const &Color, bool const Includechildren = false, bool const Includesiblings = false ); void SetDiffuseOverride( glm::vec3 const &Color, bool const Includechildren = false, bool const Includesiblings = false );
// gets rgb components of any freespot diffuse color (searches also in children)
std::optional<glm::vec3> GetDiffuse( float Includesiblings = false );
// sets visibility level (alpha component) to specified value // sets visibility level (alpha component) to specified value
void SetVisibilityLevel( float const Level, bool const Includechildren = false, bool const Includesiblings = false ); void SetVisibilityLevel( float const Level, bool const Includechildren = false, bool const Includesiblings = false );
// sets light level (alpha component of illumination color) to specified value // sets light level (alpha component of illumination color) to specified value

View File

@@ -47,7 +47,7 @@ void render_task::run() {
// build texture // build texture
::glTexImage2D( ::glTexImage2D(
GL_TEXTURE_2D, 0, GL_TEXTURE_2D, 0,
GL_RGBA8, ( Global.GfxFramebufferSRGB ? GL_SRGB8 : GL_RGBA8 ),
PyInt_AsLong( outputwidth ), PyInt_AsLong( outputheight ), 0, PyInt_AsLong( outputwidth ), PyInt_AsLong( outputheight ), 0,
GL_RGB, GL_UNSIGNED_BYTE, reinterpret_cast<GLubyte const *>( PyString_AsString( output ) ) ); GL_RGB, GL_UNSIGNED_BYTE, reinterpret_cast<GLubyte const *>( PyString_AsString( output ) ) );
::glFlush(); ::glFlush();

View File

@@ -31,12 +31,201 @@ http://mozilla.org/MPL/2.0/.
std::array<GLuint, gl::MAX_TEXTURES + 2> opengl_texture::units = { 0 }; std::array<GLuint, gl::MAX_TEXTURES + 2> opengl_texture::units = { 0 };
GLint opengl_texture::m_activeunit = -1; GLint opengl_texture::m_activeunit = -1;
std::unordered_map<GLint, int> opengl_texture::precompressed_formats =
{
{ GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 8 },
{ GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 16 },
{ GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 16 },
{ GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 8 },
{ GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 16 },
{ GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 16 },
};
std::unordered_map<GLint, GLint> opengl_texture::drivercompressed_formats =
{
{ GL_SRGB8_ALPHA8, GL_COMPRESSED_SRGB_ALPHA },
{ GL_SRGB8, GL_COMPRESSED_SRGB },
{ GL_RGBA8, GL_COMPRESSED_RGBA },
{ GL_RGB8, GL_COMPRESSED_RGB },
{ GL_RG8, GL_COMPRESSED_RG },
{ GL_R8, GL_COMPRESSED_RED },
};
std::unordered_map<GLint, std::unordered_map<GLint, GLint>> opengl_texture::mapping =
{
// image have, material wants, gl internalformat
{ GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, { { GL_SRGB_ALPHA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT },
{ GL_SRGB, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT },
{ GL_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT },
{ GL_RGB, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT },
{ GL_RG, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT },
{ GL_RED, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT } } },
{ GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, { { GL_SRGB_ALPHA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT },
{ GL_SRGB, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT },
{ GL_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT },
{ GL_RGB, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT },
{ GL_RG, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT },
{ GL_RED, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT } } },
{ GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, { { GL_SRGB_ALPHA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT },
{ GL_SRGB, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT },
{ GL_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT },
{ GL_RGB, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT },
{ GL_RG, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT },
{ GL_RED, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT } } },
{ GL_RGBA, { { GL_SRGB_ALPHA, GL_SRGB8_ALPHA8 },
{ GL_SRGB, GL_SRGB8 },
{ GL_RGBA, GL_RGBA8 },
{ GL_RGB, GL_RGB8 },
{ GL_RG, GL_RG8 },
{ GL_RED, GL_R8 } } },
{ GL_RGB, { { GL_SRGB_ALPHA, GL_SRGB8 }, // bad
{ GL_SRGB, GL_SRGB8 },
{ GL_RGBA, GL_RGB8 }, // bad
{ GL_RGB, GL_RGB8 },
{ GL_RG, GL_RG8 },
{ GL_RED, GL_R8 } } },
{ GL_RG, { { GL_SRGB_ALPHA, GL_SRGB8 }, // bad
{ GL_SRGB, GL_SRGB8 }, // bad
{ GL_RGBA, GL_RG8 }, // bad
{ GL_RGB, GL_RG8 }, // bad
{ GL_RG, GL_RG8 },
{ GL_RED, GL_R8 } } },
{ GL_RED, { { GL_SRGB_ALPHA, GL_SRGB8 }, // bad
{ GL_SRGB, GL_SRGB8 }, // bad
{ GL_RGBA, GL_R8 }, // bad
{ GL_RGB, GL_R8 }, // bad
{ GL_RG, GL_R8 }, // bad
{ GL_RED, GL_R8 } } },
};
texture_manager::texture_manager() { texture_manager::texture_manager() {
// since index 0 is used to indicate no texture, we put a blank entry in the first texture slot // since index 0 is used to indicate no texture, we put a blank entry in the first texture slot
m_textures.emplace_back( new opengl_texture(), std::chrono::steady_clock::time_point() ); m_textures.emplace_back( new opengl_texture(), std::chrono::steady_clock::time_point() );
} }
// convert image to format suitable for given internalformat
// required for GLES, on desktop GL it will be done by driver
void opengl_texture::gles_match_internalformat(GLuint internalformat)
{
// don't care about sRGB here
if (internalformat == GL_SRGB8)
internalformat = GL_RGB8;
if (internalformat == GL_SRGB8_ALPHA8)
internalformat = GL_RGBA8;
if (internalformat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT)
internalformat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
if (internalformat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT)
internalformat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
if (internalformat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT)
internalformat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
// ignore compressed formats (and hope that GLES driver will support it)
if (precompressed_formats.find(internalformat) != precompressed_formats.end())
return;
// we don't want BGR(A), reverse it
if (data_format == GL_BGR)
{
std::vector<unsigned char> reverse;
reverse.resize(data.size());
for (int y = 0; y < data_height; y++)
for (int x = 0; x < data_width; x++)
{
int offset = (y * data_width + x) * 3;
reverse[offset + 0] = data[offset + 2];
reverse[offset + 1] = data[offset + 1];
reverse[offset + 2] = data[offset + 0];
}
data_format = GL_RGB;
data = reverse;
}
else if (data_format == GL_BGRA)
{
std::vector<unsigned char> reverse;
reverse.resize(data.size());
for (int y = 0; y < data_height; y++)
for (int x = 0; x < data_width; x++)
{
int offset = (y * data_width + x) * 4;
reverse[offset + 0] = data[offset + 2];
reverse[offset + 1] = data[offset + 1];
reverse[offset + 2] = data[offset + 0];
reverse[offset + 3] = data[offset + 3];
}
data_format = GL_RGBA;
data = reverse;
}
// if format matches, we're done
if (data_format == GL_RGBA && internalformat == GL_RGBA8)
return;
if (data_format == GL_RGB && internalformat == GL_RGB8)
return;
if (data_format == GL_RG && internalformat == GL_RG8)
return;
if (data_format == GL_RED && internalformat == GL_R8)
return;
// do conversion
int in_c = 0;
if (data_format == GL_RGBA)
in_c = 4;
else if (data_format == GL_RGB)
in_c = 3;
else if (data_format == GL_RG)
in_c = 2;
else if (data_format == GL_RED)
in_c = 1;
int out_c = 0;
if (internalformat == GL_RGBA8)
out_c = 4;
else if (internalformat == GL_RGB8)
out_c = 3;
else if (internalformat == GL_RG8)
out_c = 2;
else if (internalformat == GL_R8)
out_c = 1;
if (!in_c || !out_c)
return; // conversion not supported
std::vector<unsigned char> out;
out.resize(data_width * data_height * out_c);
for (int y = 0; y < data_height; y++)
for (int x = 0; x < data_width; x++)
{
int pixel = (y * data_width + x);
int in_off = pixel * in_c;
int out_off = pixel * out_c;
for (int i = 0; i < out_c; i++)
{
if (i < in_c)
out[out_off + i] = data[in_off + i];
else
out[out_off + i] = 0xFF;
}
}
if (out_c == 4)
data_format = GL_RGBA;
else if (out_c == 3)
data_format = GL_RGB;
else if (out_c == 2)
data_format = GL_RG;
else if (out_c == 1)
data_format = GL_RED;
data = out;
}
// loads texture data from specified file // loads texture data from specified file
// TODO: wrap it in a workitem class, for the job system deferred loading // TODO: wrap it in a workitem class, for the job system deferred loading
void void
@@ -146,7 +335,7 @@ opengl_texture::load_BMP() {
} }
data.resize( datasize ); data.resize( datasize );
file.read( &data[0], datasize ); file.read((char *)&data[0], datasize);
// fill remaining data info // fill remaining data info
if( info.bmiHeader.biBitCount == 32 ) { if( info.bmiHeader.biBitCount == 32 ) {
@@ -600,8 +789,9 @@ opengl_texture::unbind(size_t unit)
bool bool
opengl_texture::create() { opengl_texture::create() {
if( data_state != resource_state::good ) { if( data_state != resource_state::good && !is_rendertarget ) {
// don't bother until we have useful texture data // don't bother until we have useful texture data
// and it isn't rendertarget texture without loaded data
return false; return false;
} }
@@ -610,73 +800,125 @@ opengl_texture::create() {
if( id == -1 ) { if( id == -1 ) {
::glGenTextures( 1, &id ); ::glGenTextures( 1, &id );
::glBindTexture( GL_TEXTURE_2D, id ); ::glBindTexture( target, id );
// analyze specified texture traits // analyze specified texture traits
bool wraps{ true };
bool wrapt{ true };
for( auto const &trait : traits ) { for( auto const &trait : traits ) {
switch( trait ) { switch( trait ) {
case 's': { wraps = false; break; } case 's': { wrap_mode_s = GL_CLAMP_TO_EDGE; break; }
case 't': { wrapt = false; break; } case 't': { wrap_mode_t = GL_CLAMP_TO_EDGE; break; }
} }
} }
::glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, ( wraps == true ? GL_REPEAT : GL_CLAMP_TO_EDGE ) );
::glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, ( wrapt == true ? GL_REPEAT : GL_CLAMP_TO_EDGE ) );
set_filtering();
if( data_mapcount == 1 ) {
// fill missing mipmaps if needed
::glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE );
}
// upload texture data // upload texture data
int dataoffset = 0, int dataoffset = 0,
datasize = 0, datasize = 0,
datawidth = data_width, datawidth = data_width,
dataheight = data_height; dataheight = data_height;
for( int maplevel = 0; maplevel < data_mapcount; ++maplevel ) { if (is_rendertarget)
{
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(target, GL_TEXTURE_WRAP_S, wrap_mode_s);
glTexParameteri(target, GL_TEXTURE_WRAP_T, wrap_mode_t);
if (data_components == GL_DEPTH_COMPONENT)
{
glTexParameteri(target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
float borderColor[] = { 0.0f, 0.0f, 0.0f, 0.0f };
glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, borderColor);
}
if( ( data_format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ) if (Global.gfx_usegles)
|| ( data_format == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT ) {
|| ( data_format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ) ) { if (target == GL_TEXTURE_2D || !glTexStorage2DMultisample)
// compressed dds formats glTexStorage2D(target, count_trailing_zeros(std::max(data_width, data_height)) + 1, data_format, data_width, data_height);
int const datablocksize = else if (target == GL_TEXTURE_2D_MULTISAMPLE)
( data_format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ? glTexStorage2DMultisample(target, samples, data_format, data_width, data_height, GL_FALSE);
8 :
16 );
datasize = ( ( std::max( datawidth, 4 ) + 3 ) / 4 ) * ( ( std::max( dataheight, 4 ) + 3 ) / 4 ) * datablocksize;
::glCompressedTexImage2D(
GL_TEXTURE_2D, maplevel, data_format,
datawidth, dataheight, 0,
datasize, (GLubyte *)&data[ dataoffset ] );
dataoffset += datasize;
datawidth = std::max( datawidth / 2, 1 );
dataheight = std::max( dataheight / 2, 1 );
} }
else { else
// uncompressed texture data. have the gfx card do the compression as it sees fit {
::glTexImage2D( if (target == GL_TEXTURE_2D)
GL_TEXTURE_2D, 0, glTexImage2D(target, 0, data_format, data_width, data_height, 0, data_components, GL_UNSIGNED_SHORT, nullptr);
( Global.compress_tex ? else if (target == GL_TEXTURE_2D_MULTISAMPLE)
GL_COMPRESSED_RGBA : glTexImage2DMultisample(target, samples, data_format, data_width, data_height, GL_FALSE);
GL_RGBA ),
data_width, data_height, 0,
data_format, GL_UNSIGNED_BYTE, (GLubyte *)&data[ 0 ] );
} }
} }
else
{
::glTexParameteri(target, GL_TEXTURE_WRAP_S, wrap_mode_s);
::glTexParameteri(target, GL_TEXTURE_WRAP_T, wrap_mode_t);
set_filtering();
if( ( true == Global.ResourceMove ) // data_format and data_type specifies how image is laid out in memory
|| ( false == Global.ResourceSweep ) ) { // data_components specifies what useful channels image contains
// if garbage collection is disabled we don't expect having to upload the texture more than once // components_hint specifies what format we want to load
data = std::vector<char>();
data_state = resource_state::none; // now map that mess into opengl internal format
GLint components = data_components;
auto f_it = precompressed_formats.find(data_format);
if (f_it != precompressed_formats.end())
components = data_format;
if (!components_hint)
components_hint = GL_SRGB_ALPHA;
GLint internal_format = mapping[components][components_hint];
if (Global.gfx_usegles)
{
// GLES cannot generate mipmaps on SRGB8
if (internal_format == GL_SRGB8)
internal_format = GL_SRGB8_ALPHA8;
gles_match_internalformat(internal_format);
}
auto blocksize_it = precompressed_formats.find(internal_format);
for( int maplevel = 0; maplevel < data_mapcount; ++maplevel ) {
if (blocksize_it != precompressed_formats.end())
{
// compressed dds formats
const int datablocksize = blocksize_it->second;
datasize = ( ( std::max( datawidth, 4 ) + 3 ) / 4 ) * ( ( std::max( dataheight, 4 ) + 3 ) / 4 ) * datablocksize;
::glCompressedTexImage2D(
target, maplevel, internal_format,
datawidth, dataheight, 0,
datasize, (GLubyte *)&data[ dataoffset ] );
dataoffset += datasize;
datawidth = std::max( datawidth / 2, 1 );
dataheight = std::max( dataheight / 2, 1 );
}
else {
GLint compressed_format = drivercompressed_formats[internal_format];
// uncompressed texture data. have the gfx card do the compression as it sees fit
::glTexImage2D(
target, 0,
Global.compress_tex ? compressed_format : internal_format,
data_width, data_height, 0,
data_format, data_type, (GLubyte *)&data[ 0 ] );
}
}
if( data_mapcount == 1 ) {
// fill missing mipmaps if needed
glGenerateMipmap(target);
}
if( ( true == Global.ResourceMove )
|| ( false == Global.ResourceSweep ) ) {
// if garbage collection is disabled we don't expect having to upload the texture more than once
data = std::vector<unsigned char>();
data_state = resource_state::none;
}
} }
if( type == "make:" ) { if( type == "make:" ) {

View File

@@ -73,11 +73,12 @@ private:
void set_filtering() const; void set_filtering() const;
void downsize( GLuint const Format ); void downsize( GLuint const Format );
void flip_vertical(); void flip_vertical();
void gles_match_internalformat( GLuint format );
// members // members
bool is_rendertarget = false; // is used as postfx rendertarget, without loaded data bool is_rendertarget = false; // is used as postfx rendertarget, without loaded data
int samples = 1; int samples = 1;
std::vector<char> data; // texture data (stored GL-style, bottom-left origin) std::vector<unsigned char> data; // texture data (stored GL-style, bottom-left origin)
resource_state data_state{ resource_state::none }; // current state of texture data resource_state data_state{ resource_state::none }; // current state of texture data
int data_width{ 0 }, int data_width{ 0 },
data_height{ 0 }, data_height{ 0 },
@@ -166,7 +167,7 @@ private:
// reduces provided data image to half of original size, using basic 2x2 average // reduces provided data image to half of original size, using basic 2x2 average
template <typename Colortype_> template <typename Colortype_>
void void
downsample( std::size_t const Width, std::size_t const Height, char *Imagedata ) { downsample( std::size_t const Width, std::size_t const Height, unsigned char *Imagedata ) {
Colortype_ *destination = reinterpret_cast<Colortype_*>( Imagedata ); Colortype_ *destination = reinterpret_cast<Colortype_*>( Imagedata );
Colortype_ *sampler = reinterpret_cast<Colortype_*>( Imagedata ); Colortype_ *sampler = reinterpret_cast<Colortype_*>( Imagedata );

View File

@@ -1140,7 +1140,7 @@ void TTrack::create_geometry( gfx::geometrybank_handle const &Bank ) {
} }
if( ( Bank == 0 ) && ( false == Geometry2.empty() ) ) { if( ( Bank == 0 ) && ( false == Geometry2.empty() ) ) {
// special variant, replace existing data for a turntable track // special variant, replace existing data for a turntable track
GfxRenderer->Replace( vertices, Geometry2[ 0 ] ); GfxRenderer->Replace( vertices, Geometry2[ 0 ], GL_TRIANGLE_STRIP );
} }
} }
if (m_material1) if (m_material1)
@@ -1158,10 +1158,10 @@ void TTrack::create_geometry( gfx::geometrybank_handle const &Bank ) {
if( ( Bank == 0 ) && ( false == Geometry1.empty() ) ) { if( ( Bank == 0 ) && ( false == Geometry1.empty() ) ) {
// special variant, replace existing data for a turntable track // special variant, replace existing data for a turntable track
Segment->RenderLoft( vertices, m_origin, rpts1, iTrapezoid > 0, texturelength ); Segment->RenderLoft( vertices, m_origin, rpts1, iTrapezoid > 0, texturelength );
GfxRenderer->Replace( vertices, Geometry1[ 0 ] ); GfxRenderer->Replace( vertices, Geometry1[ 0 ], GL_TRIANGLE_STRIP );
vertices.clear(); // reuse the scratchpad vertices.clear(); // reuse the scratchpad
Segment->RenderLoft( vertices, m_origin, rpts2, iTrapezoid > 0, texturelength ); Segment->RenderLoft( vertices, m_origin, rpts2, iTrapezoid > 0, texturelength );
GfxRenderer->Replace( vertices, Geometry1[ 1 ] ); GfxRenderer->Replace( vertices, Geometry1[ 1 ], GL_TRIANGLE_STRIP );
} }
} }
break; break;
@@ -1789,7 +1789,7 @@ TTrack * TTrack::RaAnimate()
// composed from two parts: transition from blade to regular rail, and regular rail // composed from two parts: transition from blade to regular rail, and regular rail
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts3, true, texturelength, 1.0, 0, bladelength / 2, { SwitchExtension->fOffset2, SwitchExtension->fOffset2 / 2 } ); SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts3, true, texturelength, 1.0, 0, bladelength / 2, { SwitchExtension->fOffset2, SwitchExtension->fOffset2 / 2 } );
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts1, false, texturelength, 1.0, bladelength / 2, bladelength, { SwitchExtension->fOffset2 / 2, 0.f } ); SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts1, false, texturelength, 1.0, bladelength / 2, bladelength, { SwitchExtension->fOffset2 / 2, 0.f } );
GfxRenderer->Replace( vertices, Geometry1[ 0 ] ); GfxRenderer->Replace( vertices, Geometry1[ 0 ], GL_TRIANGLE_STRIP );
vertices.clear(); vertices.clear();
} }
if( m_material2 ) { if( m_material2 ) {
@@ -1798,7 +1798,7 @@ TTrack * TTrack::RaAnimate()
// composed from two parts: transition from blade to regular rail, and regular rail // composed from two parts: transition from blade to regular rail, and regular rail
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts4, true, texturelength, 1.0, 0, bladelength / 2, { -fMaxOffset + SwitchExtension->fOffset1, ( -fMaxOffset + SwitchExtension->fOffset1 ) / 2 } ); SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts4, true, texturelength, 1.0, 0, bladelength / 2, { -fMaxOffset + SwitchExtension->fOffset1, ( -fMaxOffset + SwitchExtension->fOffset1 ) / 2 } );
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts2, false, texturelength, 1.0, bladelength / 2, bladelength, { ( -fMaxOffset + SwitchExtension->fOffset1 ) / 2, 0.f } ); SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts2, false, texturelength, 1.0, bladelength / 2, bladelength, { ( -fMaxOffset + SwitchExtension->fOffset1 ) / 2, 0.f } );
GfxRenderer->Replace( vertices, Geometry2[ 0 ] ); GfxRenderer->Replace( vertices, Geometry2[ 0 ], GL_TRIANGLE_STRIP );
vertices.clear(); vertices.clear();
} }
} }
@@ -1809,7 +1809,7 @@ TTrack * TTrack::RaAnimate()
// composed from two parts: transition from blade to regular rail, and regular rail // composed from two parts: transition from blade to regular rail, and regular rail
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts4, true, texturelength, 1.0, 0, bladelength / 2, { -SwitchExtension->fOffset2, -SwitchExtension->fOffset2 / 2 } ); SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts4, true, texturelength, 1.0, 0, bladelength / 2, { -SwitchExtension->fOffset2, -SwitchExtension->fOffset2 / 2 } );
SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts2, false, texturelength, 1.0, bladelength / 2, bladelength, { -SwitchExtension->fOffset2 / 2, 0.f } ); SwitchExtension->Segments[ 0 ]->RenderLoft( vertices, m_origin, rpts2, false, texturelength, 1.0, bladelength / 2, bladelength, { -SwitchExtension->fOffset2 / 2, 0.f } );
GfxRenderer->Replace( vertices, Geometry1[ 0 ] ); GfxRenderer->Replace( vertices, Geometry1[ 0 ], GL_TRIANGLE_STRIP );
vertices.clear(); vertices.clear();
} }
if( m_material2 ) { if( m_material2 ) {
@@ -1818,7 +1818,7 @@ TTrack * TTrack::RaAnimate()
// composed from two parts: transition from blade to regular rail, and regular rail // composed from two parts: transition from blade to regular rail, and regular rail
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts3, true, texturelength, 1.0, 0, bladelength / 2, { fMaxOffset - SwitchExtension->fOffset1, ( fMaxOffset - SwitchExtension->fOffset1 ) / 2 } ); SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts3, true, texturelength, 1.0, 0, bladelength / 2, { fMaxOffset - SwitchExtension->fOffset1, ( fMaxOffset - SwitchExtension->fOffset1 ) / 2 } );
SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts1, false, texturelength, 1.0, bladelength / 2, bladelength, { ( fMaxOffset - SwitchExtension->fOffset1 ) / 2, 0.f } ); SwitchExtension->Segments[ 1 ]->RenderLoft( vertices, m_origin, rpts1, false, texturelength, 1.0, bladelength / 2, bladelength, { ( fMaxOffset - SwitchExtension->fOffset1 ) / 2, 0.f } );
GfxRenderer->Replace( vertices, Geometry2[ 0 ] ); GfxRenderer->Replace( vertices, Geometry2[ 0 ], GL_TRIANGLE_STRIP );
vertices.clear(); vertices.clear();
} }
} }

View File

@@ -19,9 +19,11 @@ http://mozilla.org/MPL/2.0/.
#include "dictionary.h" #include "dictionary.h"
#include "sceneeditor.h" #include "sceneeditor.h"
#include "openglrenderer.h" #include "openglrenderer.h"
#include "opengl33renderer.h"
#include "uilayer.h" #include "uilayer.h"
#include "translation.h" #include "translation.h"
#include "Logs.h" #include "Logs.h"
#include "Timer.h"
#ifdef EU07_BUILD_STATIC #ifdef EU07_BUILD_STATIC
#pragma comment( lib, "glfw3.lib" ) #pragma comment( lib, "glfw3.lib" )
@@ -145,15 +147,27 @@ int
eu07_application::run() { eu07_application::run() {
// main application loop // main application loop
while( ( false == glfwWindowShouldClose( m_windows.front() ) ) while (!glfwWindowShouldClose( m_windows.front() ) && !m_modestack.empty())
&& ( false == m_modestack.empty() ) {
&& ( true == m_modes[ m_modestack.top() ]->update() ) Timer::subsystem.mainloop_total.start();
&& ( true == GfxRenderer->Render() ) ) {
if( !m_modes[ m_modestack.top() ]->update() )
break;
if (!GfxRenderer->Render())
break;
glfwPollEvents(); glfwPollEvents();
if (m_modestack.empty())
return 0;
m_modes[ m_modestack.top() ]->on_event_poll(); m_modes[ m_modestack.top() ]->on_event_poll();
Timer::subsystem.mainloop_total.stop();
} }
return 0; return 0;
} }
// issues request for a worker thread to perform specified task. returns: true if task was scheduled // issues request for a worker thread to perform specified task. returns: true if task was scheduled
@@ -532,9 +546,14 @@ eu07_application::init_gfx() {
} }
} }
{ if( Global.GfxRenderer == "default" ) {
// default render path
GfxRenderer = std::make_unique<opengl33_renderer>();
}
else {
// legacy render path // legacy render path
GfxRenderer = std::make_unique<opengl_renderer>(); GfxRenderer = std::make_unique<opengl_renderer>();
Global.GfxFramebufferSRGB = false;
Global.DisabledLogTypes |= logtype::material; Global.DisabledLogTypes |= logtype::material;
} }

View File

@@ -238,10 +238,11 @@ driver_mode::update() {
// NOTE: particle system runs on simulation time, but needs actual camera position to determine how to update each particle source // NOTE: particle system runs on simulation time, but needs actual camera position to determine how to update each particle source
simulation::Particles.update(); simulation::Particles.update();
GfxRenderer->Update( deltarealtime );
simulation::is_ready = true; simulation::is_ready = true;
GfxRenderer->Update( deltarealtime );
return true; return true;
} }

View File

@@ -318,7 +318,7 @@ drivermouse_input::button( int const Button, int const Action ) {
// left mouse button launches on_click event associated with to the node // left mouse button launches on_click event associated with to the node
if( Button == GLFW_MOUSE_BUTTON_LEFT ) { if( Button == GLFW_MOUSE_BUTTON_LEFT ) {
if( Action == GLFW_PRESS ) { if( Action == GLFW_PRESS ) {
GfxRenderer->Pick_Node( GfxRenderer->Pick_Node_Callback(
[this](scene::basic_node *node) { [this](scene::basic_node *node) {
if( ( node == nullptr ) if( ( node == nullptr )
|| ( typeid( *node ) != typeid( TAnimModel ) ) ) || ( typeid( *node ) != typeid( TAnimModel ) ) )
@@ -366,7 +366,7 @@ drivermouse_input::button( int const Button, int const Action ) {
else { else {
// if not release then it's press // if not release then it's press
m_pickwaiting = true; m_pickwaiting = true;
GfxRenderer->Pick_Control( GfxRenderer->Pick_Control_Callback(
[this, Button, Action, &mousecommand](TSubModel const *control) { [this, Button, Action, &mousecommand](TSubModel const *control) {
bool pickwaiting = m_pickwaiting; bool pickwaiting = m_pickwaiting;

View File

@@ -1104,9 +1104,14 @@ debug_panel::update_section_renderer( std::vector<text_line> &Output ) {
textline = textline =
std::string( "Rendering mode: " ) std::string( "Rendering mode: " )
+ ( Global.GfxRenderer == "default" ?
"Shaders" :
( Global.BasicRenderer ?
"Legacy Simple" :
"Legacy" ) )
+ ( Global.bUseVBO ? + ( Global.bUseVBO ?
"VBO" : ", VBO" :
"Display Lists" ) ", Display Lists" )
+ " "; + " ";
if( false == Global.LastGLError.empty() ) { if( false == Global.LastGLError.empty() ) {
textline += textline +=

View File

@@ -230,7 +230,7 @@ editor_mode::on_mouse_button( int const Button, int const Action, int const Mods
if( Action == GLFW_PRESS ) { if( Action == GLFW_PRESS ) {
// left button press // left button press
m_node = nullptr; m_node = nullptr;
GfxRenderer->Pick_Node( GfxRenderer->Pick_Node_Callback(
[ this ]( scene::basic_node *node ) { [ this ]( scene::basic_node *node ) {
m_node = node; m_node = node;
if( m_node ) { if( m_node ) {

View File

@@ -10,6 +10,7 @@ http://mozilla.org/MPL/2.0/.
#include "stdafx.h" #include "stdafx.h"
#include "geometrybank.h" #include "geometrybank.h"
#include "openglgeometrybank.h" #include "openglgeometrybank.h"
#include "opengl33geometrybank.h"
#include "sn_utils.h" #include "sn_utils.h"
#include "Logs.h" #include "Logs.h"
@@ -239,8 +240,9 @@ geometrybank_manager::update() {
gfx::geometrybank_handle gfx::geometrybank_handle
geometrybank_manager::create_bank() { geometrybank_manager::create_bank() {
if( true == Global.bUseVBO ) { m_geometrybanks.emplace_back( std::make_shared<opengl_vbogeometrybank>(), std::chrono::steady_clock::time_point() ); } if( Global.GfxRenderer == "default" ) { m_geometrybanks.emplace_back( std::make_shared<opengl33_vaogeometrybank>(), std::chrono::steady_clock::time_point() ); }
else { m_geometrybanks.emplace_back( std::make_shared<opengl_dlgeometrybank>(), std::chrono::steady_clock::time_point() ); } else if( true == Global.bUseVBO ) { m_geometrybanks.emplace_back( std::make_shared<opengl_vbogeometrybank>(), std::chrono::steady_clock::time_point() ); }
else { m_geometrybanks.emplace_back( std::make_shared<opengl_dlgeometrybank>(), std::chrono::steady_clock::time_point() ); }
// NOTE: handle is effectively (index into chunk array + 1) this leaves value of 0 to serve as error/empty handle indication // NOTE: handle is effectively (index into chunk array + 1) this leaves value of 0 to serve as error/empty handle indication
return { static_cast<std::uint32_t>( m_geometrybanks.size() ), 0 }; return { static_cast<std::uint32_t>( m_geometrybanks.size() ), 0 };
} }

454
maszyna.vcxproj Normal file
View File

@@ -0,0 +1,454 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{8E0232E5-1C67-442F-9E04-45ED2DDFC960}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141_xp</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<TargetName>eu07-$(PlatformShortName)</TargetName>
<IntDir>$(SolutionDir)tmp\$(PlatformShortName)-$(Configuration)\$(ProjectName)\</IntDir>
<OutDir>$(SolutionDir)bin\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<TargetName>eu07-$(PlatformShortName)</TargetName>
<OutDir>$(SolutionDir)bin\</OutDir>
<IntDir>$(SolutionDir)tmp\$(PlatformShortName)-$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)bin\</OutDir>
<IntDir>$(SolutionDir)tmp\$(PlatformShortName)-$(Configuration)\$(ProjectName)\</IntDir>
<TargetName>eu07-$(PlatformShortName)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<TargetName>eu07-$(PlatformShortName)</TargetName>
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)bin\</OutDir>
<IntDir>$(SolutionDir)tmp\$(PlatformShortName)-$(Configuration)\$(ProjectName)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>$(SolutionDir);$(SolutionDir)console;$(SolutionDir)mczapkie;$(SolutionDir)ref/glad/include;$(SolutionDir)ref/glfw/include;$(SolutionDir)ref/glm;$(SolutionDir)ref/openal/include;$(SolutionDir)ref/dr_libs/include;$(SolutionDir)ref/imgui;$(SolutionDir)ref/imgui/examples;$(SolutionDir)ref/python/include;$(SolutionDir)ref/libserialport/include;$(SolutionDir)ref/stb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>Use</PrecompiledHeader>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<FloatingPointExceptions>true</FloatingPointExceptions>
<EnforceTypeConversionRules>true</EnforceTypeConversionRules>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(DXSKD_DIR)lib/$(PlatformShortName);$(SolutionDir)ref/glew/lib/msvc-$(MSBuildToolsVersion)/$(PlatformShortName);$(SolutionDir)ref/glfw/lib/msvc-$(MSBuildToolsVersion)/$(PlatformShortName);$(SolutionDir)ref/openal/lib/$(PlatformShortName);$(SolutionDir)ref/python/lib/$(PlatformShortName);$(SolutionDir)ref/libserialport/lib/$(PlatformShortName);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<SubSystem>Windows</SubSystem>
<IgnoreSpecificDefaultLibraries>
</IgnoreSpecificDefaultLibraries>
<LargeAddressAware>true</LargeAddressAware>
</Link>
<Bscmake />
<Bscmake />
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>$(SolutionDir);$(SolutionDir)console;$(SolutionDir)mczapkie;$(SolutionDir)ref/glad/include;$(SolutionDir)ref/glfw/include;$(SolutionDir)ref/glm;$(SolutionDir)ref/openal/include;$(SolutionDir)ref/dr_libs/include;$(SolutionDir)ref/imgui;$(SolutionDir)ref/imgui/examples;$(SolutionDir)ref/python/include;$(SolutionDir)ref/libserialport/include;$(SolutionDir)ref/stb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>Use</PrecompiledHeader>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<EnforceTypeConversionRules>true</EnforceTypeConversionRules>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(DXSKD_DIR)lib/$(PlatformShortName);$(SolutionDir)ref/glew/lib/msvc-$(MSBuildToolsVersion)/$(PlatformShortName);$(SolutionDir)ref/glfw/lib/msvc-$(MSBuildToolsVersion)/$(PlatformShortName);$(SolutionDir)ref/openal/lib/$(PlatformShortName);$(SolutionDir)ref/python/lib/$(PlatformShortName);$(SolutionDir)ref/libserialport/lib/$(PlatformShortName);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<SubSystem>Windows</SubSystem>
<IgnoreSpecificDefaultLibraries>
</IgnoreSpecificDefaultLibraries>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>$(SolutionDir);$(SolutionDir)console;$(SolutionDir)mczapkie;$(SolutionDir)ref/glad/include;$(SolutionDir)ref/glfw/include;$(SolutionDir)ref/glm;$(SolutionDir)ref/openal/include;$(SolutionDir)ref/dr_libs/include;$(SolutionDir)ref/imgui;$(SolutionDir)ref/imgui/examples;$(SolutionDir)ref/python/include;$(SolutionDir)ref/libserialport/include;$(SolutionDir)ref/stb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>Use</PrecompiledHeader>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<WholeProgramOptimization>true</WholeProgramOptimization>
<EnforceTypeConversionRules>true</EnforceTypeConversionRules>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>$(DXSKD_DIR)lib/$(PlatformShortName);$(SolutionDir)ref/glew/lib/msvc-$(MSBuildToolsVersion)/$(PlatformShortName);$(SolutionDir)ref/glfw/lib/msvc-$(MSBuildToolsVersion)/$(PlatformShortName);$(SolutionDir)ref/openal/lib/$(PlatformShortName);$(SolutionDir)ref/python/lib/$(PlatformShortName);$(SolutionDir)ref/libserialport/lib/$(PlatformShortName);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<SubSystem>Windows</SubSystem>
<IgnoreSpecificDefaultLibraries>libcmt.lib</IgnoreSpecificDefaultLibraries>
<LargeAddressAware>true</LargeAddressAware>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>$(SolutionDir);$(SolutionDir)console;$(SolutionDir)mczapkie;$(SolutionDir)ref/glad/include;$(SolutionDir)ref/glew/include;$(SolutionDir)ref/glfw/include;$(SolutionDir)ref/glm;$(SolutionDir)ref/openal/include;$(SolutionDir)ref/dr_libs/include;$(SolutionDir)ref/imgui;$(SolutionDir)ref/imgui/examples;$(SolutionDir)ref/python/include;$(SolutionDir)ref/libserialport/include;$(SolutionDir)ref/stb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>Use</PrecompiledHeader>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<WholeProgramOptimization>true</WholeProgramOptimization>
<EnforceTypeConversionRules>true</EnforceTypeConversionRules>
<FloatingPointExceptions>true</FloatingPointExceptions>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>$(DXSKD_DIR)lib/$(PlatformShortName);$(SolutionDir)ref/glew/lib/msvc-$(MSBuildToolsVersion)/$(PlatformShortName);$(SolutionDir)ref/glfw/lib/msvc-$(MSBuildToolsVersion)/$(PlatformShortName);$(SolutionDir)ref/openal/lib/$(PlatformShortName);$(SolutionDir)ref/python/lib/$(PlatformShortName);$(SolutionDir)ref/libserialport/lib/$(PlatformShortName);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<SubSystem>Windows</SubSystem>
<IgnoreSpecificDefaultLibraries>libcmt.lib</IgnoreSpecificDefaultLibraries>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="AirCoupler.cpp" />
<ClCompile Include="AnimModel.cpp" />
<ClCompile Include="application.cpp" />
<ClCompile Include="audio.cpp" />
<ClCompile Include="audiorenderer.cpp" />
<ClCompile Include="Button.cpp" />
<ClCompile Include="Camera.cpp" />
<ClCompile Include="command.cpp" />
<ClCompile Include="Console.cpp" />
<ClCompile Include="console\LPT.cpp" />
<ClCompile Include="console\PoKeys55.cpp" />
<ClCompile Include="dictionary.cpp" />
<ClCompile Include="Driver.cpp" />
<ClCompile Include="drivermode.cpp" />
<ClCompile Include="driveruilayer.cpp" />
<ClCompile Include="driveruipanels.cpp" />
<ClCompile Include="dumb3d.cpp" />
<ClCompile Include="DynObj.cpp" />
<ClCompile Include="editorkeyboardinput.cpp" />
<ClCompile Include="editormode.cpp" />
<ClCompile Include="editormouseinput.cpp" />
<ClCompile Include="editoruilayer.cpp" />
<ClCompile Include="editoruipanels.cpp" />
<ClCompile Include="eu07.cpp" />
<ClCompile Include="Event.cpp" />
<ClCompile Include="EvLaunch.cpp" />
<ClCompile Include="Float3d.cpp" />
<ClCompile Include="frustum.cpp" />
<ClCompile Include="gamepadinput.cpp" />
<ClCompile Include="Gauge.cpp" />
<ClCompile Include="geometrybank.cpp" />
<ClCompile Include="Globals.cpp" />
<ClCompile Include="driverkeyboardinput.cpp" />
<ClCompile Include="gl\buffer.cpp" />
<ClCompile Include="gl\cubemap.cpp" />
<ClCompile Include="gl\fence.cpp" />
<ClCompile Include="gl\framebuffer.cpp" />
<ClCompile Include="gl\glsl_common.cpp" />
<ClCompile Include="gl\pbo.cpp" />
<ClCompile Include="gl\postfx.cpp" />
<ClCompile Include="gl\query.cpp" />
<ClCompile Include="gl\renderbuffer.cpp" />
<ClCompile Include="gl\shader.cpp" />
<ClCompile Include="gl\ubo.cpp" />
<ClCompile Include="gl\vao.cpp" />
<ClCompile Include="keyboardinput.cpp" />
<ClCompile Include="lightarray.cpp" />
<ClCompile Include="Logs.cpp" />
<ClCompile Include="material.cpp" />
<ClCompile Include="mczapkie\friction.cpp" />
<ClCompile Include="mczapkie\hamulce.cpp" />
<ClCompile Include="mczapkie\Mover.cpp" />
<ClCompile Include="mczapkie\Oerlikon_ESt.cpp" />
<ClCompile Include="MdlMngr.cpp" />
<ClCompile Include="MemCell.cpp" />
<ClCompile Include="messaging.cpp" />
<ClCompile Include="Model3d.cpp" />
<ClCompile Include="moon.cpp" />
<ClCompile Include="drivermouseinput.cpp" />
<ClCompile Include="mtable.cpp" />
<ClCompile Include="Names.cpp" />
<ClCompile Include="opengl33geometrybank.cpp" />
<ClCompile Include="opengl33light.cpp" />
<ClCompile Include="opengl33particles.cpp" />
<ClCompile Include="opengl33precipitation.cpp" />
<ClCompile Include="opengl33renderer.cpp" />
<ClCompile Include="opengl33skydome.cpp" />
<ClCompile Include="openglcamera.cpp" />
<ClCompile Include="openglcolor.cpp" />
<ClCompile Include="openglgeometrybank.cpp" />
<ClCompile Include="opengllight.cpp" />
<ClCompile Include="openglmatrixstack.cpp" />
<ClCompile Include="openglparticles.cpp" />
<ClCompile Include="openglprecipitation.cpp" />
<ClCompile Include="openglrenderer.cpp" />
<ClCompile Include="openglskydome.cpp" />
<ClCompile Include="parser.cpp" />
<ClCompile Include="particles.cpp" />
<ClCompile Include="precipitation.cpp" />
<ClCompile Include="PyInt.cpp" />
<ClCompile Include="ref\glad\src\glad.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="ref\imgui\examples\imgui_impl_glfw.cpp" />
<ClCompile Include="ref\imgui\examples\imgui_impl_opengl2.cpp" />
<ClCompile Include="ref\imgui\examples\imgui_impl_opengl3.cpp" />
<ClCompile Include="ref\imgui\imgui.cpp" />
<ClCompile Include="ref\imgui\imgui_draw.cpp" />
<ClCompile Include="ref\imgui\imgui_widgets.cpp" />
<ClCompile Include="ref\stb\stb_vorbis.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="renderer.cpp" />
<ClCompile Include="ResourceManager.cpp" />
<ClCompile Include="scenarioloadermode.cpp" />
<ClCompile Include="scenenodegroups.cpp" />
<ClCompile Include="simulationenvironment.cpp" />
<ClCompile Include="simulationstateserializer.cpp" />
<ClCompile Include="scene.cpp" />
<ClCompile Include="sceneeditor.cpp" />
<ClCompile Include="scenenode.cpp" />
<ClCompile Include="Segment.cpp" />
<ClCompile Include="simulation.cpp" />
<ClCompile Include="simulationtime.cpp" />
<ClCompile Include="sky.cpp" />
<ClCompile Include="skydome.cpp" />
<ClCompile Include="sn_utils.cpp" />
<ClCompile Include="sound.cpp" />
<ClCompile Include="Spring.cpp" />
<ClCompile Include="stars.cpp" />
<ClCompile Include="station.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="sun.cpp" />
<ClCompile Include="Texture.cpp" />
<ClCompile Include="Timer.cpp" />
<ClCompile Include="Track.cpp" />
<ClCompile Include="Traction.cpp" />
<ClCompile Include="TractionPower.cpp" />
<ClCompile Include="Train.cpp" />
<ClCompile Include="translation.cpp" />
<ClCompile Include="TrkFoll.cpp" />
<ClCompile Include="uart.cpp" />
<ClCompile Include="uilayer.cpp" />
<ClCompile Include="uitranscripts.cpp" />
<ClCompile Include="utilities.cpp" />
<ClCompile Include="vertex.cpp" />
<ClCompile Include="windows.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="AirCoupler.h" />
<ClInclude Include="AnimModel.h" />
<ClInclude Include="application.h" />
<ClInclude Include="applicationmode.h" />
<ClInclude Include="audio.h" />
<ClInclude Include="audiorenderer.h" />
<ClInclude Include="Button.h" />
<ClInclude Include="Camera.h" />
<ClInclude Include="Classes.h" />
<ClInclude Include="color.h" />
<ClInclude Include="command.h" />
<ClInclude Include="Console.h" />
<ClInclude Include="Console\LPT.h" />
<ClInclude Include="Console\PoKeys55.h" />
<ClInclude Include="dictionary.h" />
<ClInclude Include="Driver.h" />
<ClInclude Include="drivermode.h" />
<ClInclude Include="driveruilayer.h" />
<ClInclude Include="driveruipanels.h" />
<ClInclude Include="dumb3d.h" />
<ClInclude Include="DynObj.h" />
<ClInclude Include="editorkeyboardinput.h" />
<ClInclude Include="editormode.h" />
<ClInclude Include="editormouseinput.h" />
<ClInclude Include="editoruilayer.h" />
<ClInclude Include="editoruipanels.h" />
<ClInclude Include="Event.h" />
<ClInclude Include="EvLaunch.h" />
<ClInclude Include="Float3d.h" />
<ClInclude Include="frustum.h" />
<ClInclude Include="gamepadinput.h" />
<ClInclude Include="Gauge.h" />
<ClInclude Include="geometrybank.h" />
<ClInclude Include="Globals.h" />
<ClInclude Include="driverkeyboardinput.h" />
<ClInclude Include="gl\bindable.h" />
<ClInclude Include="gl\buffer.h" />
<ClInclude Include="gl\cubemap.h" />
<ClInclude Include="gl\fence.h" />
<ClInclude Include="gl\framebuffer.h" />
<ClInclude Include="gl\glsl_common.h" />
<ClInclude Include="gl\object.h" />
<ClInclude Include="gl\pbo.h" />
<ClInclude Include="gl\postfx.h" />
<ClInclude Include="gl\query.h" />
<ClInclude Include="gl\renderbuffer.h" />
<ClInclude Include="gl\shader.h" />
<ClInclude Include="gl\ubo.h" />
<ClInclude Include="gl\vao.h" />
<ClInclude Include="keyboardinput.h" />
<ClInclude Include="light.h" />
<ClInclude Include="lightarray.h" />
<ClInclude Include="Logs.h" />
<ClInclude Include="material.h" />
<ClInclude Include="McZapkie\friction.h" />
<ClInclude Include="McZapkie\hamulce.h" />
<ClInclude Include="McZapkie\mover.h" />
<ClInclude Include="McZapkie\Oerlikon_ESt.h" />
<ClInclude Include="MdlMngr.h" />
<ClInclude Include="MemCell.h" />
<ClInclude Include="messaging.h" />
<ClInclude Include="Model3d.h" />
<ClInclude Include="moon.h" />
<ClInclude Include="drivermouseinput.h" />
<ClInclude Include="mtable.h" />
<ClInclude Include="Names.h" />
<ClInclude Include="opengl33geometrybank.h" />
<ClInclude Include="opengl33light.h" />
<ClInclude Include="opengl33particles.h" />
<ClInclude Include="opengl33precipitation.h" />
<ClInclude Include="opengl33renderer.h" />
<ClInclude Include="opengl33skydome.h" />
<ClInclude Include="openglcamera.h" />
<ClInclude Include="openglcolor.h" />
<ClInclude Include="openglgeometrybank.h" />
<ClInclude Include="opengllight.h" />
<ClInclude Include="openglmatrixstack.h" />
<ClInclude Include="openglparticles.h" />
<ClInclude Include="openglprecipitation.h" />
<ClInclude Include="openglrenderer.h" />
<ClInclude Include="openglskydome.h" />
<ClInclude Include="parser.h" />
<ClInclude Include="particles.h" />
<ClInclude Include="precipitation.h" />
<ClInclude Include="PyInt.h" />
<ClInclude Include="renderer.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="ResourceManager.h" />
<ClInclude Include="scenarioloadermode.h" />
<ClInclude Include="scenarioloaderuilayer.h" />
<ClInclude Include="scenenodegroups.h" />
<ClInclude Include="simulationenvironment.h" />
<ClInclude Include="simulationstateserializer.h" />
<ClInclude Include="scene.h" />
<ClInclude Include="sceneeditor.h" />
<ClInclude Include="scenenode.h" />
<ClInclude Include="Segment.h" />
<ClInclude Include="simulation.h" />
<ClInclude Include="simulationtime.h" />
<ClInclude Include="sky.h" />
<ClInclude Include="skydome.h" />
<ClInclude Include="sn_utils.h" />
<ClInclude Include="sound.h" />
<ClInclude Include="Spring.h" />
<ClInclude Include="stars.h" />
<ClInclude Include="station.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="sun.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="Texture.h" />
<ClInclude Include="Timer.h" />
<ClInclude Include="Track.h" />
<ClInclude Include="Traction.h" />
<ClInclude Include="TractionPower.h" />
<ClInclude Include="Train.h" />
<ClInclude Include="translation.h" />
<ClInclude Include="TrkFoll.h" />
<ClInclude Include="uart.h" />
<ClInclude Include="uilayer.h" />
<ClInclude Include="uitranscripts.h" />
<ClInclude Include="utilities.h" />
<ClInclude Include="version.h" />
<ClInclude Include="vertex.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="maszyna.rc">
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">TARGETMACHINEX86;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">TARGETMACHINEX86;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<Image Include="eu07.ico" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -435,6 +435,12 @@
<ClCompile Include="opengl33precipitation.cpp"> <ClCompile Include="opengl33precipitation.cpp">
<Filter>Source Files\gfx</Filter> <Filter>Source Files\gfx</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="opengl33skydome.cpp">
<Filter>Source Files\gfx</Filter>
</ClCompile>
<ClCompile Include="opengl33geometrybank.cpp">
<Filter>Source Files\gfx</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Globals.h"> <ClInclude Include="Globals.h">
@@ -701,9 +707,6 @@
<ClInclude Include="Texture.h"> <ClInclude Include="Texture.h">
<Filter>Header Files\gfx</Filter> <Filter>Header Files\gfx</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="stars.h">
<Filter>Header Files\gfx</Filter>
</ClInclude>
<ClInclude Include="AnimModel.h"> <ClInclude Include="AnimModel.h">
<Filter>Header Files\gfx</Filter> <Filter>Header Files\gfx</Filter>
</ClInclude> </ClInclude>
@@ -800,6 +803,15 @@
<ClInclude Include="opengl33precipitation.h"> <ClInclude Include="opengl33precipitation.h">
<Filter>Header Files\gfx</Filter> <Filter>Header Files\gfx</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="opengl33skydome.h">
<Filter>Header Files\gfx</Filter>
</ClInclude>
<ClInclude Include="opengl33geometrybank.h">
<Filter>Header Files\gfx</Filter>
</ClInclude>
<ClInclude Include="stars.h">
<Filter>Header Files\gfx</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="maszyna.rc"> <ResourceCompile Include="maszyna.rc">

View File

@@ -315,6 +315,15 @@ float opengl_material::get_or_guess_opacity() const {
return 0.0f; return 0.0f;
} }
bool
opengl_material::is_translucent() const {
return (
textures[ 0 ] != null_handle ?
GfxRenderer->Texture( textures[ 0 ] ).has_alpha :
false );
}
// create material object from data stored in specified file. // create material object from data stored in specified file.
// NOTE: the deferred load parameter is passed to textures defined by material, the material itself is always loaded immediately // NOTE: the deferred load parameter is passed to textures defined by material, the material itself is always loaded immediately
material_handle material_handle

View File

@@ -38,9 +38,7 @@ struct opengl_material {
deserialize( cParser &Input, bool const Loadnow ); deserialize( cParser &Input, bool const Loadnow );
void finalize(bool Loadnow); void finalize(bool Loadnow);
float get_or_guess_opacity() const; float get_or_guess_opacity() const;
inline bool bool is_translucent() const;
is_translucent() const {
return ( get_or_guess_opacity() == 0.0f ); }
private: private:
// methods // methods

138
opengl33geometrybank.cpp Normal file
View File

@@ -0,0 +1,138 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#include "stdafx.h"
#include "opengl33geometrybank.h"
#include "Logs.h"
namespace gfx {
// opengl vao/vbo-based variant of the geometry bank
// create() subclass details
void
opengl33_vaogeometrybank::create_( gfx::geometry_handle const &Geometry ) {
// adding a chunk means we'll be (re)building the buffer, which will fill the chunk records, amongst other things.
// thus we don't need to initialize the values here
m_chunkrecords.emplace_back( chunk_record() );
// kiss the existing buffer goodbye, new overall data size means we'll be making a new one
delete_buffer();
}
// replace() subclass details
void
opengl33_vaogeometrybank::replace_( gfx::geometry_handle const &Geometry ) {
auto &chunkrecord = m_chunkrecords[ Geometry.chunk - 1 ];
chunkrecord.is_good = false;
// if the overall length of the chunk didn't change we can get away with reusing the old buffer...
if( geometry_bank::chunk( Geometry ).vertices.size() != chunkrecord.size ) {
// ...but otherwise we'll need to allocate a new one
// TBD: we could keep and reuse the old buffer also if the new chunk is smaller than the old one,
// but it'd require some extra tracking and work to keep all chunks up to date; also wasting vram; may be not worth it?
delete_buffer();
}
}
void opengl33_vaogeometrybank::setup_buffer()
{
if( !m_buffer ) {
// if there's no buffer, we'll have to make one
// NOTE: this isn't exactly optimal in terms of ensuring the gfx card doesn't stall waiting for the data
// may be better to initiate upload earlier (during update phase) and trust this effort won't go to waste
if( true == m_chunks.empty() ) { return; }
std::size_t datasize{ 0 };
auto chunkiterator = m_chunks.cbegin();
for( auto &chunkrecord : m_chunkrecords ) {
// fill records for all chunks, based on the chunk data
chunkrecord.is_good = false; // if we're re-creating buffer, chunks might've been uploaded in the old one
chunkrecord.offset = datasize;
chunkrecord.size = chunkiterator->vertices.size();
datasize += chunkrecord.size;
++chunkiterator;
}
// the odds for all created chunks to get replaced with empty ones are quite low, but the possibility does exist
if( datasize == 0 ) { return; }
// try to set up the buffer we need
m_buffer.emplace();
// NOTE: we're using static_draw since it's generally true for all we have implemented at the moment
// TODO: allow to specify usage hint at the object creation, and pass it here
m_buffer->allocate(gl::buffer::ARRAY_BUFFER, datasize * sizeof(gfx::basic_vertex), GL_STATIC_DRAW);
if( ::glGetError() == GL_OUT_OF_MEMORY ) {
ErrorLog( "openGL error: out of memory; failed to create a geometry buffer" );
throw std::bad_alloc();
}
m_buffercapacity = datasize;
}
if (!m_vao)
{
m_vao.emplace();
m_vao->setup_attrib(*m_buffer, 0, 3, GL_FLOAT, sizeof(basic_vertex), 0 * sizeof(float));
// NOTE: normal and color streams share the data
m_vao->setup_attrib(*m_buffer, 1, 3, GL_FLOAT, sizeof(basic_vertex), 3 * sizeof(float));
m_vao->setup_attrib(*m_buffer, 2, 2, GL_FLOAT, sizeof(basic_vertex), 6 * sizeof(float));
m_vao->setup_attrib(*m_buffer, 3, 4, GL_FLOAT, sizeof(basic_vertex), 8 * sizeof(float));
m_buffer->unbind(gl::buffer::ARRAY_BUFFER);
m_vao->unbind();
}
}
// draw() subclass details
// NOTE: units and stream parameters are unused, but they're part of (legacy) interface
// TBD: specialized bank/manager pair without the cruft?
void
opengl33_vaogeometrybank::draw_( gfx::geometry_handle const &Geometry, gfx::stream_units const &Units, unsigned int const Streams )
{
setup_buffer();
auto &chunkrecord = m_chunkrecords.at(Geometry.chunk - 1);
// sanity check; shouldn't be needed but, eh
if( chunkrecord.size == 0 )
return;
auto const &chunk = gfx::geometry_bank::chunk( Geometry );
if( false == chunkrecord.is_good ) {
// we may potentially need to upload new buffer data before we can draw it
m_buffer->upload(gl::buffer::ARRAY_BUFFER, chunk.vertices.data(),
chunkrecord.offset * sizeof( gfx::basic_vertex ),
chunkrecord.size * sizeof( gfx::basic_vertex ));
chunkrecord.is_good = true;
}
// render
m_vao->bind();
::glDrawArrays( chunk.type, chunkrecord.offset, chunkrecord.size );
}
// release () subclass details
void
opengl33_vaogeometrybank::release_() {
delete_buffer();
}
void
opengl33_vaogeometrybank::delete_buffer() {
if( m_buffer ) {
m_vao.reset();
m_buffer.reset();
m_buffercapacity = 0;
// NOTE: since we've deleted the buffer all chunks it held were rendered invalid as well
// instead of clearing their state here we're delaying it until new buffer is created to avoid looping through chunk records twice
}
}
} // namespace gfx

72
opengl33geometrybank.h Normal file
View File

@@ -0,0 +1,72 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "geometrybank.h"
#include "gl/buffer.h"
#include "gl/vao.h"
namespace gfx {
// opengl vao/vbo-based variant of the geometry bank
class opengl33_vaogeometrybank : public geometry_bank {
public:
// constructors:
opengl33_vaogeometrybank() = default;
// destructor
~opengl33_vaogeometrybank() {
delete_buffer(); }
// methods:
static
void
reset() {;}
private:
// types:
struct chunk_record{
std::size_t offset{ 0 }; // beginning of the chunk data as offset from the beginning of the last established buffer
std::size_t size{ 0 }; // size of the chunk in the last established buffer
bool is_good{ false }; // true if local content of the chunk matches the data on the opengl end
};
typedef std::vector<chunk_record> chunkrecord_sequence;
// methods:
// create() subclass details
void
create_( gfx::geometry_handle const &Geometry ) override;
// replace() subclass details
void
replace_( gfx::geometry_handle const &Geometry ) override;
// draw() subclass details
void
draw_( gfx::geometry_handle const &Geometry, gfx::stream_units const &Units, unsigned int const Streams ) override;
// release() subclass details
void
release_() override;
void
setup_buffer();
void
delete_buffer();
// members:
std::optional<gl::buffer> m_buffer; // buffer data on the opengl end
std::optional<gl::vao> m_vao;
std::size_t m_buffercapacity{ 0 }; // total capacity of the last established buffer
chunkrecord_sequence m_chunkrecords; // helper data for all stored geometry chunks, in matching order
// vectors for glMultiDrawArrays in class scope
// to don't waste time on reallocating
std::vector<GLint> m_offsets;
std::vector<GLsizei> m_counts;
};
} // namespace gfx

View File

@@ -13,6 +13,7 @@ http://mozilla.org/MPL/2.0/.
#include "particles.h" #include "particles.h"
#include "openglcamera.h" #include "openglcamera.h"
#include "simulation.h" #include "simulation.h"
#include "simulationenvironment.h"
std::vector<std::pair<glm::vec3, glm::vec2>> const billboard_vertices { std::vector<std::pair<glm::vec3, glm::vec2>> const billboard_vertices {
@@ -53,7 +54,8 @@ opengl33_particles::update( opengl_camera const &Camera ) {
auto const particlecolor { auto const particlecolor {
glm::clamp( glm::clamp(
source.second.color() source.second.color()
* ( glm::vec3 { Global.DayLight.ambient } + 0.35f * glm::vec3{ Global.DayLight.diffuse } ), * ( glm::vec3 { Global.DayLight.ambient }
+ 0.35f * glm::vec3{ Global.DayLight.diffuse } ) * simulation::Environment.light_intensity(),
glm::vec3{ 0.f }, glm::vec3{ 1.f } ) }; glm::vec3{ 0.f }, glm::vec3{ 1.f } ) };
auto const &particles { source.second.sequence() }; auto const &particles { source.second.sequence() };
// TODO: put sanity cap on the overall amount of particles that can be drawn // TODO: put sanity cap on the overall amount of particles that can be drawn
@@ -65,7 +67,7 @@ opengl33_particles::update( opengl_camera const &Camera ) {
vertex.color[ 0 ] = particlecolor.r; vertex.color[ 0 ] = particlecolor.r;
vertex.color[ 1 ] = particlecolor.g; vertex.color[ 1 ] = particlecolor.g;
vertex.color[ 2 ] = particlecolor.b; vertex.color[ 2 ] = particlecolor.b;
vertex.color.a = std::clamp(particle.opacity, 0.0f, 1.0f); vertex.color.a = clamp(particle.opacity, 0.0f, 1.0f);
auto const offset { glm::vec3{ particle.position - Camera.position() } }; auto const offset { glm::vec3{ particle.position - Camera.position() } };
auto const rotation { glm::angleAxis( particle.rotation, glm::vec3{ 0.f, 0.f, 1.f } ) }; auto const rotation { glm::angleAxis( particle.rotation, glm::vec3{ 0.f, 0.f, 1.f } ) };

View File

@@ -24,6 +24,8 @@ http://mozilla.org/MPL/2.0/.
int const EU07_PICKBUFFERSIZE{1024}; // size of (square) textures bound with the pick framebuffer int const EU07_PICKBUFFERSIZE{1024}; // size of (square) textures bound with the pick framebuffer
auto const gammacorrection { glm::vec3( 2.2f ) };
bool opengl33_renderer::Init(GLFWwindow *Window) bool opengl33_renderer::Init(GLFWwindow *Window)
{ {
if (!Init_caps()) if (!Init_caps())
@@ -280,7 +282,7 @@ bool opengl33_renderer::init_viewport(viewport_config &vp)
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ALIGNMENT, 1);
glClearColor(51.0f / 255.0f, 102.0f / 255.0f, 85.0f / 255.0f, 1.0f); // initial background Color glClearColor( 51.0f / 255.f, 102.0f / 255.f, 85.0f / 255.f, 1.f ); // initial background Color
glFrontFace(GL_CCW); glFrontFace(GL_CCW);
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
@@ -397,6 +399,8 @@ bool opengl33_renderer::Render()
m_sunlight.direction = glm::normalize(quantizationstep * glm::roundEven(m_sunlight.direction * (1.f / quantizationstep))); m_sunlight.direction = glm::normalize(quantizationstep * glm::roundEven(m_sunlight.direction * (1.f / quantizationstep)));
} }
// generate new frame // generate new frame
opengl_texture::reset_unit_cache();
m_renderpass.draw_mode = rendermode::none; // force setup anew m_renderpass.draw_mode = rendermode::none; // force setup anew
m_debugstats = debug_stats(); m_debugstats = debug_stats();
@@ -431,6 +435,8 @@ bool opengl33_renderer::Render()
++m_framestamp; ++m_framestamp;
SwapBuffers();
Timer::subsystem.gfx_total.stop(); Timer::subsystem.gfx_total.stop();
return true; // for now always succeed return true; // for now always succeed
@@ -491,10 +497,13 @@ void opengl33_renderer::Render_pass(viewport_config &vp, rendermode const Mode)
if (!simulation::is_ready) if (!simulation::is_ready)
{ {
gl::framebuffer::unbind(); gl::framebuffer::unbind();
glClearColor(0.0f, 0.5f, 0.0f, 1.0f); glClearColor( 51.0f / 255.f, 102.0f / 255.f, 85.0f / 255.f, 1.f ); // initial background Color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (vp.main) if( vp.main ) {
Application.render_ui(); //glEnable( GL_FRAMEBUFFER_SRGB );
Application.render_ui();
//glDisable( GL_FRAMEBUFFER_SRGB );
}
break; break;
} }
@@ -952,49 +961,17 @@ void opengl33_renderer::setup_pass(viewport_config &Viewport, renderpass_config
Config.draw_mode = Mode; Config.draw_mode = Mode;
if (false == simulation::is_ready) if( false == simulation::is_ready ) { return; }
{ // setup draw range
return; switch( Mode ) {
} case rendermode::color: { Config.draw_range = Global.BaseDrawRange; break; }
// setup draw range case rendermode::shadows: { Config.draw_range = Global.BaseDrawRange * 0.5f; break; }
switch (Mode) case rendermode::cabshadows: { Config.draw_range = ( Global.RenderCabShadowsRange > 0 ? clamp( Global.RenderCabShadowsRange, 5, 100 ) : simulation::Train->Occupied()->Dim.L ); break; }
{ case rendermode::reflections: { Config.draw_range = Global.BaseDrawRange; break; }
case rendermode::color: case rendermode::pickcontrols: { Config.draw_range = 50.f; break; }
{ case rendermode::pickscenery: { Config.draw_range = Global.BaseDrawRange * 0.5f; break; }
Config.draw_range = Global.BaseDrawRange; default: { Config.draw_range = 0.f; break; }
break; }
}
case rendermode::shadows:
{
Config.draw_range = Global.BaseDrawRange * 0.5f;
break;
}
case rendermode::cabshadows:
{
Config.draw_range = simulation::Train->Occupied()->Dim.L;
break;
}
case rendermode::reflections:
{
Config.draw_range = Global.BaseDrawRange;
break;
}
case rendermode::pickcontrols:
{
Config.draw_range = 50.f;
break;
}
case rendermode::pickscenery:
{
Config.draw_range = Global.BaseDrawRange * 0.5f;
break;
}
default:
{
Config.draw_range = 0.f;
break;
}
}
Config.draw_range *= Viewport.draw_range; Config.draw_range *= Viewport.draw_range;
@@ -1247,7 +1224,12 @@ void opengl33_renderer::setup_shadow_map(opengl_texture *tex, renderpass_config
glm::mat4 depthcam = conf.pass_camera.modelview(); glm::mat4 depthcam = conf.pass_camera.modelview();
glm::mat4 worldcam = m_renderpass.pass_camera.modelview(); glm::mat4 worldcam = m_renderpass.pass_camera.modelview();
scene_ubs.lightview = coordmove * depthproj * depthcam * glm::inverse(worldcam); scene_ubs.lightview =
coordmove
* depthproj
* depthcam
* glm::inverse( worldcam );
scene_ubo->update(scene_ubs); scene_ubo->update(scene_ubs);
} }
} }
@@ -1328,12 +1310,18 @@ bool opengl33_renderer::Render(world_environment *Environment)
// drawn with 500m radius to blend in if the fog range is low // drawn with 500m radius to blend in if the fog range is low
glPushMatrix(); glPushMatrix();
glScalef(500.0f, 500.0f, 500.0f); glScalef(500.0f, 500.0f, 500.0f);
m_skydomerenderer.update();
m_skydomerenderer.render(); m_skydomerenderer.render();
glPopMatrix(); glPopMatrix();
// skydome uses a custom vbo which could potentially confuse the main geometry system. hardly elegant but, eh // skydome uses a custom vbo which could potentially confuse the main geometry system. hardly elegant but, eh
gfx::opengl_vbogeometrybank::reset(); gfx::opengl_vbogeometrybank::reset();
::glPushAttrib( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT );
::glDisable( GL_ALPHA_TEST );
::glEnable( GL_BLEND );
::glBlendFunc( GL_SRC_ALPHA, GL_ONE );
// stars // stars
if (Environment->m_stars.m_stars != nullptr) if (Environment->m_stars.m_stars != nullptr)
{ {
@@ -1349,43 +1337,28 @@ bool opengl33_renderer::Render(world_environment *Environment)
::glPopMatrix(); ::glPopMatrix();
} }
auto const fogfactor{clamp<float>(Global.fFogEnd / 2000.f, 0.f, 1.f)}; // stronger fog reduces opacity of the celestial bodies
float const duskfactor = 1.0f - clamp(std::abs(Environment->m_sun.getAngle()), 0.0f, 12.0f) / 12.0f;
glm::vec3 suncolor = interpolate(glm::vec3(255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f), glm::vec3(235.0f / 255.0f, 140.0f / 255.0f, 36.0f / 255.0f), duskfactor);
// clouds
if (Environment->m_clouds.mdCloud)
{
// setup
glm::vec3 color = interpolate(Environment->m_skydome.GetAverageColor(), suncolor, duskfactor * 0.25f) * interpolate(1.f, 0.35f, Global.Overcast / 2.f) // overcast darkens the clouds
* 0.5f;
// write cloud color into material
TSubModel *mdl = Environment->m_clouds.mdCloud->Root;
if (mdl->m_material != null_handle)
m_materials.material(mdl->m_material).params[0] = glm::vec4(color, 1.0f);
// render
Render(Environment->m_clouds.mdCloud, nullptr, 100.0);
Render_Alpha(Environment->m_clouds.mdCloud, nullptr, 100.0);
// post-render cleanup
}
// celestial bodies // celestial bodies
m_celestial_shader->bind(); m_celestial_shader->bind();
m_empty_vao->bind(); m_empty_vao->bind();
auto const &modelview = OpenGLMatrices.data(GL_MODELVIEW); auto const &modelview = OpenGLMatrices.data(GL_MODELVIEW);
auto const fogfactor{clamp<float>(Global.fFogEnd / 2000.f, 0.f, 1.f)}; // stronger fog reduces opacity of the celestial bodies
float const duskfactor = 1.0f - clamp(std::abs(Environment->m_sun.getAngle()), 0.0f, 12.0f) / 12.0f;
glm::vec3 suncolor = interpolate(glm::vec3(255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f), glm::vec3(235.0f / 255.0f, 140.0f / 255.0f, 36.0f / 255.0f), duskfactor);
// sun // sun
{ {
Bind_Texture(0, m_suntexture); Bind_Texture(0, m_suntexture);
glm::vec4 color(suncolor.x, suncolor.y, suncolor.z, clamp(1.5f - Global.Overcast, 0.f, 1.f) * fogfactor); glm::vec4 color(suncolor.x, suncolor.y, suncolor.z, clamp(1.5f - Global.Overcast, 0.f, 1.f) * fogfactor);
auto const sunvector = Environment->m_sun.getDirection(); auto const sunvector = Environment->m_sun.getDirection();
float const size = interpolate( // TODO: expose distance/scale factor from the moon object
0.0325f,
0.0275f,
clamp( Environment->m_sun.getAngle(), 0.f, 90.f ) / 90.f );
model_ubs.param[0] = color; model_ubs.param[0] = color;
model_ubs.param[1] = glm::vec4(glm::vec3(modelview * glm::vec4(sunvector, 1.0f)), 0.00463f); model_ubs.param[1] = glm::vec4(glm::vec3(modelview * glm::vec4(sunvector, 1.0f)), /*0.00463f*/ size);
model_ubs.param[2] = glm::vec4(0.0f, 1.0f, 1.0f, 0.0f); model_ubs.param[2] = glm::vec4(0.0f, 1.0f, 1.0f, 0.0f);
model_ubo->update(model_ubs); model_ubo->update(model_ubs);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
@@ -1451,12 +1424,36 @@ bool opengl33_renderer::Render(world_environment *Environment)
moonu = 0.0f; moonu = 0.0f;
} }
float const size = interpolate( // TODO: expose distance/scale factor from the moon object
0.0160f,
0.0135f,
clamp( Environment->m_moon.getAngle(), 0.f, 90.f ) / 90.f );
model_ubs.param[0] = color; model_ubs.param[0] = color;
model_ubs.param[1] = glm::vec4(glm::vec3(modelview * glm::vec4(moonvector, 1.0f)), 0.00451f); model_ubs.param[1] = glm::vec4(glm::vec3(modelview * glm::vec4(moonvector, 1.0f)), /*0.00451f*/ size);
model_ubs.param[2] = glm::vec4(moonu, moonv, 0.333f, 0.0f); model_ubs.param[2] = glm::vec4(moonu, moonv, 0.333f, 0.0f);
model_ubo->update(model_ubs); model_ubo->update(model_ubs);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
} }
::glPopAttrib();
// clouds
if (Environment->m_clouds.mdCloud)
{
// setup
glm::vec3 color = interpolate(Environment->m_skydome.GetAverageColor(), suncolor, duskfactor * 0.25f) * interpolate(1.f, 0.35f, Global.Overcast / 2.f) // overcast darkens the clouds
* 0.5f;
// write cloud color into material
TSubModel *mdl = Environment->m_clouds.mdCloud->Root;
if (mdl->m_material != null_handle)
m_materials.material(mdl->m_material).params[0] = glm::vec4(color, 1.0f);
// render
Render(Environment->m_clouds.mdCloud, nullptr, 100.0);
Render_Alpha(Environment->m_clouds.mdCloud, nullptr, 100.0);
// post-render cleanup
}
gl::program::unbind(); gl::program::unbind();
gl::vao::unbind(); gl::vao::unbind();
@@ -1548,6 +1545,7 @@ void opengl33_renderer::Bind_Material(material_handle const Material, TSubModel
src = sm->f4Ambient; src = sm->f4Ambient;
else if (entry.defaultparam == gl::shader::defaultparam_e::diffuse) else if (entry.defaultparam == gl::shader::defaultparam_e::diffuse)
src = sm->f4Diffuse; src = sm->f4Diffuse;
// src = glm::vec4( glm::pow( glm::vec3( sm->f4Diffuse ), gammacorrection ), sm->f4Diffuse.a );
else if (entry.defaultparam == gl::shader::defaultparam_e::specular) else if (entry.defaultparam == gl::shader::defaultparam_e::specular)
src = sm->f4Specular; src = sm->f4Specular;
} }
@@ -1645,6 +1643,11 @@ texture_handle opengl33_renderer::Fetch_Texture(std::string const &Filename, boo
return m_textures.create(Filename, Loadnow, format_hint); return m_textures.create(Filename, Loadnow, format_hint);
} }
void opengl33_renderer::Bind_Texture( texture_handle const Texture )
{
return Bind_Texture( 0, Texture );
}
void opengl33_renderer::Bind_Texture(std::size_t const Unit, texture_handle const Texture) void opengl33_renderer::Bind_Texture(std::size_t const Unit, texture_handle const Texture)
{ {
m_textures.bind(Unit, Texture); m_textures.bind(Unit, Texture);
@@ -1720,7 +1723,7 @@ void opengl33_renderer::Render(scene::basic_region *Region)
{ {
// when editor mode is active calculate world position of the cursor // when editor mode is active calculate world position of the cursor
// at this stage the z-buffer is filled with only ground geometry // at this stage the z-buffer is filled with only ground geometry
get_mouse_depth(); Update_Mouse_Position();
} }
Render(std::begin(m_cellqueue), std::end(m_cellqueue)); Render(std::begin(m_cellqueue), std::end(m_cellqueue));
break; break;
@@ -2489,7 +2492,7 @@ void opengl33_renderer::Render(TSubModel *Submodel)
Bind_Material(Submodel->m_material, Submodel); Bind_Material(Submodel->m_material, Submodel);
// main draw call // main draw call
model_ubs.param[1].x = 2.0f * 2.0f; model_ubs.param[1].x = 2.0f;
draw(Submodel->m_geometry); draw(Submodel->m_geometry);
} }
@@ -3353,9 +3356,10 @@ void opengl33_renderer::Render_Alpha(TSubModel *Submodel)
// main draw call // main draw call
model_ubs.emission = 1.0f; model_ubs.emission = 1.0f;
auto const lightcolor = glm::vec3(Submodel->DiffuseOverride.r < 0.f ? // -1 indicates no override auto lightcolor = glm::vec3(Submodel->DiffuseOverride.r < 0.f ? // -1 indicates no override
Submodel->f4Diffuse : Submodel->f4Diffuse :
Submodel->DiffuseOverride); Submodel->DiffuseOverride);
lightcolor = glm::pow( lightcolor, gammacorrection );
m_freespot_shader->bind(); m_freespot_shader->bind();
@@ -3368,7 +3372,7 @@ void opengl33_renderer::Render_Alpha(TSubModel *Submodel)
draw(Submodel->m_geometry); draw(Submodel->m_geometry);
} }
model_ubs.param[1].x = pointsize * resolutionratio * 2.0f; model_ubs.param[1].x = pointsize * resolutionratio;
model_ubs.param[0] = glm::vec4(glm::vec3(lightcolor), Submodel->fVisible * std::min(1.f, lightlevel)); model_ubs.param[0] = glm::vec4(glm::vec3(lightcolor), Submodel->fVisible * std::min(1.f, lightlevel));
if (!Submodel->occlusion_query) if (!Submodel->occlusion_query)
@@ -3517,17 +3521,17 @@ void opengl33_renderer::Update_Pick_Node()
} }
} }
void opengl33_renderer::pick_control(std::function<void(TSubModel const *)> callback) void opengl33_renderer::Pick_Control_Callback(std::function<void(TSubModel const *)> callback)
{ {
m_control_pick_requests.push_back(callback); m_control_pick_requests.push_back(callback);
} }
void opengl33_renderer::pick_node(std::function<void(scene::basic_node *)> callback) void opengl33_renderer::Pick_Node_Callback(std::function<void(scene::basic_node *)> callback)
{ {
m_node_pick_requests.push_back(callback); m_node_pick_requests.push_back(callback);
} }
glm::dvec3 opengl33_renderer::get_mouse_depth() glm::dvec3 opengl33_renderer::Update_Mouse_Position()
{ {
if (!m_depth_pointer_pbo->is_busy()) if (!m_depth_pointer_pbo->is_busy())
{ {
@@ -3631,18 +3635,33 @@ void opengl33_renderer::Update(double const Deltatime)
} }
m_updateaccumulator = 0.0; m_updateaccumulator = 0.0;
m_framerate = 1000.f / (Timer::subsystem.mainloop_total.average()); m_framerate = 1000.f / ( Timer::subsystem.mainloop_total.average() );
// adjust draw ranges etc, based on recent performance // adjust draw ranges etc, based on recent performance
// TODO: it doesn't make much sense with vsync // TODO: it doesn't make much sense with vsync
if( Global.targetfps == 0.0f ) {
if (Global.targetfps != 0.0f) { // automatic adjustment
float fps_diff = Global.targetfps - m_framerate; float targetfactor;
if (fps_diff > 0.0f) if( m_framerate > 90.0 ) { targetfactor = 3.0f; }
Global.fDistanceFactor = std::max(0.5f, Global.fDistanceFactor - 0.05f); else if( m_framerate > 60.0 ) { targetfactor = 1.5f; }
else else if( m_framerate > 30.0 ) { targetfactor = 1.25; }
Global.fDistanceFactor = std::min(3.0f, Global.fDistanceFactor + 0.05f); else { targetfactor = 1.0f; }
} if( targetfactor > Global.fDistanceFactor ) {
Global.fDistanceFactor = std::min( targetfactor, Global.fDistanceFactor + 0.05f );
}
else if( targetfactor < Global.fDistanceFactor ) {
Global.fDistanceFactor = std::max( targetfactor, Global.fDistanceFactor - 0.05f );
}
}
else {
auto const fps_diff = Global.targetfps - m_framerate;
if( fps_diff > 0.5f ) {
Global.fDistanceFactor = std::max( 1.0f, Global.fDistanceFactor - 0.05f );
}
else if( fps_diff < 0.5f ) {
Global.fDistanceFactor = std::min( 3.0f, Global.fDistanceFactor + 0.05f );
}
}
if ((true == Global.ResourceSweep) && (true == simulation::is_ready)) if ((true == Global.ResourceSweep) && (true == simulation::is_ready))
{ {
@@ -3652,10 +3671,10 @@ void opengl33_renderer::Update(double const Deltatime)
} }
if ((true == Global.ControlPicking) && (false == FreeFlyModeFlag)) if ((true == Global.ControlPicking) && (false == FreeFlyModeFlag))
pick_control([](const TSubModel *) {}); Pick_Control_Callback([](const TSubModel *) {});
// temporary conditions for testing. eventually will be coupled with editor mode // temporary conditions for testing. eventually will be coupled with editor mode
if ((true == Global.ControlPicking) && (true == DebugModeFlag) && (true == FreeFlyModeFlag)) if ((true == Global.ControlPicking) && (true == DebugModeFlag) && (true == FreeFlyModeFlag))
pick_node([](scene::basic_node *) {}); Pick_Node_Callback([](scene::basic_node *) {});
// dump last opengl error, if any // dump last opengl error, if any
auto const glerror = ::glGetError(); auto const glerror = ::glGetError();
@@ -3748,7 +3767,7 @@ void opengl33_renderer::Update_Lights(light_array &Lights)
renderlight->diffuse = glm::vec4{glm::max(glm::vec3{colors::none}, scenelight.color - glm::vec3{luminance}), renderlight->diffuse[3]}; renderlight->diffuse = glm::vec4{glm::max(glm::vec3{colors::none}, scenelight.color - glm::vec3{luminance}), renderlight->diffuse[3]};
renderlight->ambient = glm::vec4{glm::max(glm::vec3{colors::none}, scenelight.color * glm::vec3{scenelight.intensity} - glm::vec3{luminance}), renderlight->ambient[3]}; renderlight->ambient = glm::vec4{glm::max(glm::vec3{colors::none}, scenelight.color * glm::vec3{scenelight.intensity} - glm::vec3{luminance}), renderlight->ambient[3]};
renderlight->apply_intensity(); renderlight->apply_intensity( ( scenelight.count * 0.5 ) * ( scenelight.owner->DimHeadlights ? 0.5 : 1.0 ) );
renderlight->apply_angle(); renderlight->apply_angle();
gl::light_element_ubs *l = &light_ubs.lights[light_i]; gl::light_element_ubs *l = &light_ubs.lights[light_i];
@@ -3767,10 +3786,10 @@ void opengl33_renderer::Update_Lights(light_array &Lights)
++renderlight; ++renderlight;
} }
light_ubs.ambient = m_sunlight.ambient * m_sunlight.factor; light_ubs.ambient = m_sunlight.ambient * m_sunlight.factor;// *simulation::Environment.light_intensity();
light_ubs.lights[0].type = gl::light_element_ubs::DIR; light_ubs.lights[0].type = gl::light_element_ubs::DIR;
light_ubs.lights[0].dir = mv * glm::vec4(m_sunlight.direction, 0.0f); light_ubs.lights[0].dir = mv * glm::vec4(m_sunlight.direction, 0.0f);
light_ubs.lights[0].color = m_sunlight.diffuse * m_sunlight.factor; light_ubs.lights[0].color = m_sunlight.diffuse * m_sunlight.factor * simulation::Environment.light_intensity();
light_ubs.lights[0].ambient = 0.0f; light_ubs.lights[0].ambient = 0.0f;
light_ubs.lights[0].intensity = 1.0f; light_ubs.lights[0].intensity = 1.0f;
light_ubs.lights_count = light_i; light_ubs.lights_count = light_i;

View File

@@ -13,7 +13,7 @@ http://mozilla.org/MPL/2.0/.
#include "openglcamera.h" #include "openglcamera.h"
#include "opengl33light.h" #include "opengl33light.h"
#include "opengl33particles.h" #include "opengl33particles.h"
#include "openglskydome.h" #include "opengl33skydome.h"
#include "opengl33precipitation.h" #include "opengl33precipitation.h"
#include "simulationenvironment.h" #include "simulationenvironment.h"
#include "scene.h" #include "scene.h"
@@ -33,51 +33,52 @@ http://mozilla.org/MPL/2.0/.
class opengl33_renderer : public gfx_renderer { class opengl33_renderer : public gfx_renderer {
public: public:
// types // types
/// Renderer runtime settings /// Renderer runtime settings
struct Settings struct Settings
{ {
bool traction_debug { false }; bool traction_debug { false };
} settings; } settings;
// constructors
// methods opengl33_renderer() = default;
bool Init(GLFWwindow *Window); // destructor
/* ~opengl33_renderer() {}
bool AddViewport(const global_settings::extraviewport_config &conf); // methods
*/ bool
// main draw call. returns false on error Init( GLFWwindow *Window ) override;
bool Render(); // main draw call. returns false on error
void SwapBuffers(); bool
inline float Framerate() Render() override;
{ inline
return m_framerate; float
} Framerate() override { return m_framerate; }
// geometry methods // 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 // 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 // creates a new geometry bank. returns: handle to the bank or NULL
gfx::geometrybank_handle Create_Bank(); gfx::geometrybank_handle
// creates a new geometry chunk of specified type from supplied vertex data, in specified bank. returns: handle to the chunk or NULL Create_Bank() override;
gfx::geometry_handle Insert(gfx::vertex_array &Vertices, gfx::geometrybank_handle const &Geometry, int const Type); // creates a new geometry chunk of specified type from supplied vertex data, in specified bank. returns: handle to the chunk or NULL
// replaces data of specified chunk with the supplied vertex data, starting from specified offset gfx::geometry_handle
bool Replace(gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, int const Type, std::size_t const Offset = 0); Insert( gfx::vertex_array &Vertices, gfx::geometrybank_handle const &Geometry, int const Type ) override;
// adds supplied vertex data at the end of specified chunk // replaces data of specified chunk with the supplied vertex data, starting from specified offset
bool Append(gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, int const Type); bool
// draws supplied geometry handles Replace( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, int const Type, std::size_t const Offset = 0 ) override;
void Draw_Geometry(std::vector<gfx::geometrybank_handle>::iterator begin, std::vector<gfx::geometrybank_handle>::iterator end); // adds supplied vertex data at the end of specified chunk
void Draw_Geometry(const gfx::geometrybank_handle &handle); bool
// provides direct access to vertex data of specfied chunk Append( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, int const Type ) override;
gfx::vertex_array const &Vertices(gfx::geometry_handle const &Geometry) const; // provides direct access to vertex data of specfied chunk
// material methods gfx::vertex_array const &
material_handle Fetch_Material(std::string const &Filename, bool const Loadnow = true); Vertices( gfx::geometry_handle const &Geometry ) const override;
void Bind_Material(material_handle const Material, TSubModel *sm = nullptr); // material methods
void Bind_Material_Shadow(material_handle const Material); material_handle
Fetch_Material( std::string const &Filename, bool const Loadnow = true ) override;
// shader methods void
std::shared_ptr<gl::program> Fetch_Shader( std::string const &name ) override; Bind_Material( material_handle const Material, TSubModel *sm = nullptr ) override;
opengl_material const &
opengl_material const &Material(material_handle const Material) const; Material( material_handle const Material ) const override;
opengl_material &Material(material_handle const Material); // shader methods
// texture methods auto Fetch_Shader( std::string const &name ) -> std::shared_ptr<gl::program> override;
// texture methods
texture_handle texture_handle
Fetch_Texture( std::string const &Filename, bool const Loadnow = true, GLint format_hint = GL_SRGB_ALPHA ) override; Fetch_Texture( std::string const &Filename, bool const Loadnow = true, GLint format_hint = GL_SRGB_ALPHA ) override;
void void
@@ -88,25 +89,42 @@ class opengl33_renderer : public gfx_renderer {
Texture( texture_handle const Texture ) override; Texture( texture_handle const Texture ) override;
opengl_texture const & opengl_texture const &
Texture( texture_handle const Texture ) const override; Texture( texture_handle const Texture ) const override;
// utility methods // utility methods
void
Pick_Control_Callback( std::function<void( TSubModel const * )> Callback ) override;
void
Pick_Node_Callback( std::function<void( scene::basic_node * )> Callback ) override;
TSubModel const * TSubModel const *
Pick_Control() const override { return m_pickcontrolitem; } Pick_Control() const override { return m_pickcontrolitem; }
scene::basic_node const * scene::basic_node const *
Pick_Node() const override { return m_picksceneryitem; } Pick_Node() const override { return m_picksceneryitem; }
glm::dvec3 glm::dvec3
Mouse_Position() const override { return m_worldmousecoordinates; } Mouse_Position() const override { return m_worldmousecoordinates; }
void Update_AnimModel(TAnimModel *model); // maintenance methods
// maintenance methods void
void Update(double const Deltatime); Update( double const Deltatime ) override;
void Update_Pick_Control(); void
void Update_Pick_Node(); Update_Pick_Control() override;
glm::dvec3 get_mouse_depth(); void
// debug methods Update_Pick_Node() override;
std::string const &info_times() const; glm::dvec3
std::string const &info_stats() const; Update_Mouse_Position() override;
// debug methods
std::string const &
info_times() const override;
std::string const &
info_stats() const override;
void pick_control(std::function<void(TSubModel const *)> callback);
void pick_node(std::function<void(scene::basic_node *)> callback);
opengl_material & Material( material_handle const Material );
void SwapBuffers();
// draws supplied geometry handles
void Draw_Geometry(std::vector<gfx::geometrybank_handle>::iterator begin, std::vector<gfx::geometrybank_handle>::iterator end);
void Draw_Geometry(const gfx::geometrybank_handle &handle);
// material methods
void Bind_Material_Shadow(material_handle const Material);
void Update_AnimModel(TAnimModel *model);
// members // members
GLenum static const sunlight{0}; GLenum static const sunlight{0};
@@ -252,7 +270,7 @@ class opengl33_renderer : public gfx_renderer {
int m_environmentcubetextureface{0}; // helper, currently processed cube map face int m_environmentcubetextureface{0}; // helper, currently processed cube map face
double m_environmentupdatetime{0}; // time of the most recent environment map update double m_environmentupdatetime{0}; // time of the most recent environment map update
glm::dvec3 m_environmentupdatelocation; // coordinates of most recent environment map update glm::dvec3 m_environmentupdatelocation; // coordinates of most recent environment map update
opengl_skydome m_skydomerenderer; opengl33_skydome m_skydomerenderer;
opengl33_precipitation m_precipitationrenderer; opengl33_precipitation m_precipitationrenderer;
opengl33_particles m_particlerenderer; // particle visualization subsystem opengl33_particles m_particlerenderer; // particle visualization subsystem

69
opengl33skydome.cpp Normal file
View File

@@ -0,0 +1,69 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#include "stdafx.h"
#include "opengl33skydome.h"
#include "simulationenvironment.h"
void opengl33_skydome::update() {
if (!m_shader) {
gl::shader vert("vbocolor.vert");
gl::shader frag("color.frag");
m_shader.emplace(std::vector<std::reference_wrapper<const gl::shader>>({vert, frag}));
}
auto &skydome { simulation::Environment.skydome() };
if (!m_vertexbuffer) {
m_vao.emplace();
m_vao->bind();
m_vertexbuffer.emplace();
m_vertexbuffer->allocate(gl::buffer::ARRAY_BUFFER, skydome.vertices().size() * sizeof( glm::vec3 ), GL_STATIC_DRAW);
m_vertexbuffer->upload(gl::buffer::ARRAY_BUFFER, skydome.vertices().data(), 0, skydome.vertices().size() * sizeof( glm::vec3 ));
m_vao->setup_attrib(*m_vertexbuffer, 0, 3, GL_FLOAT, sizeof(glm::vec3), 0);
m_coloursbuffer.emplace();
m_coloursbuffer->allocate(gl::buffer::ARRAY_BUFFER, skydome.colors().size() * sizeof( glm::vec3 ), GL_STATIC_DRAW);
m_coloursbuffer->upload(gl::buffer::ARRAY_BUFFER, skydome.colors().data(), 0, skydome.colors().size() * sizeof( glm::vec3 ));
m_vao->setup_attrib(*m_coloursbuffer, 1, 3, GL_FLOAT, sizeof(glm::vec3), 0);
m_indexbuffer.emplace();
m_indexbuffer->allocate(gl::buffer::ELEMENT_ARRAY_BUFFER, skydome.indices().size() * sizeof( unsigned short ), GL_STATIC_DRAW);
m_indexbuffer->upload(gl::buffer::ELEMENT_ARRAY_BUFFER, skydome.indices().data(), 0, skydome.indices().size() * sizeof( unsigned short ));
m_vao->setup_ebo(*m_indexbuffer);
m_vao->unbind();
}
// ship the current dynamic data to the gpu
if( true == skydome.is_dirty() ) {
if( m_coloursbuffer ) {
// the colour buffer was already initialized, so on this run we update its content
m_coloursbuffer->upload( gl::buffer::ARRAY_BUFFER, skydome.colors().data(), 0, skydome.colors().size() * sizeof( glm::vec3 ) );
skydome.is_dirty() = false;
}
}
}
// render skydome to screen
void opengl33_skydome::render() {
if( ( !m_shader) || ( !m_vao ) ) { return; }
m_shader->bind();
m_vao->bind();
auto const &skydome { simulation::Environment.skydome() };
::glDrawElements( GL_TRIANGLES, static_cast<GLsizei>( skydome.indices().size() ), GL_UNSIGNED_SHORT, reinterpret_cast<void const*>( 0 ) );
}

36
opengl33skydome.h Normal file
View File

@@ -0,0 +1,36 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#pragma once
#include "gl/vao.h"
#include "gl/shader.h"
#include "gl/buffer.h"
class opengl33_skydome {
public:
// constructors
opengl33_skydome() = default;
// destructor
~opengl33_skydome() {;}
// methods
// updates data stores on the opengl end. NOTE: unbinds buffers
void update();
// draws the skydome
void render();
private:
// members
std::optional<gl::buffer> m_vertexbuffer;
std::optional<gl::buffer> m_indexbuffer;
std::optional<gl::buffer> m_coloursbuffer;
std::optional<gl::program> m_shader;
std::optional<gl::vao> m_vao;
};

View File

@@ -49,44 +49,8 @@ opengl_vbogeometrybank::replace_( gfx::geometry_handle const &Geometry ) {
void void
opengl_vbogeometrybank::draw_( gfx::geometry_handle const &Geometry, gfx::stream_units const &Units, unsigned int const Streams ) { opengl_vbogeometrybank::draw_( gfx::geometry_handle const &Geometry, gfx::stream_units const &Units, unsigned int const Streams ) {
if( m_buffer == 0 ) { setup_buffer();
// if there's no buffer, we'll have to make one
// NOTE: this isn't exactly optimal in terms of ensuring the gfx card doesn't stall waiting for the data
// may be better to initiate upload earlier (during update phase) and trust this effort won't go to waste
if( true == m_chunks.empty() ) { return; }
std::size_t datasize{ 0 };
auto chunkiterator = m_chunks.cbegin();
for( auto &chunkrecord : m_chunkrecords ) {
// fill records for all chunks, based on the chunk data
chunkrecord.is_good = false; // if we're re-creating buffer, chunks might've been uploaded in the old one
chunkrecord.offset = datasize;
chunkrecord.size = chunkiterator->vertices.size();
datasize += chunkrecord.size;
++chunkiterator;
}
// the odds for all created chunks to get replaced with empty ones are quite low, but the possibility does exist
if( datasize == 0 ) { return; }
// try to set up the buffer we need
::glGenBuffers( 1, &m_buffer );
bind_buffer();
if( m_buffer == 0 ) { return; } // if we didn't get a buffer we'll try again during the next draw call
// NOTE: we're using static_draw since it's generally true for all we have implemented at the moment
// TODO: allow to specify usage hint at the object creation, and pass it here
::glBufferData(
GL_ARRAY_BUFFER,
datasize * sizeof( gfx::basic_vertex ),
nullptr,
GL_STATIC_DRAW );
if( ::glGetError() == GL_OUT_OF_MEMORY ) {
// TBD: throw a bad_alloc?
ErrorLog( "openGL error: out of memory; failed to create a geometry buffer" );
delete_buffer();
return;
}
m_buffercapacity = datasize;
}
// actual draw procedure starts here
auto &chunkrecord { m_chunkrecords[ Geometry.chunk - 1 ] }; auto &chunkrecord { m_chunkrecords[ Geometry.chunk - 1 ] };
// sanity check; shouldn't be needed but, eh // sanity check; shouldn't be needed but, eh
if( chunkrecord.size == 0 ) { return; } if( chunkrecord.size == 0 ) { return; }
@@ -125,6 +89,47 @@ opengl_vbogeometrybank::release_() {
delete_buffer(); delete_buffer();
} }
void
opengl_vbogeometrybank::setup_buffer() {
if( m_buffer != 0 ) { return; }
// if there's no buffer, we'll have to make one
// NOTE: this isn't exactly optimal in terms of ensuring the gfx card doesn't stall waiting for the data
// may be better to initiate upload earlier (during update phase) and trust this effort won't go to waste
if( true == m_chunks.empty() ) { return; }
std::size_t datasize{ 0 };
auto chunkiterator = m_chunks.cbegin();
for( auto &chunkrecord : m_chunkrecords ) {
// fill records for all chunks, based on the chunk data
chunkrecord.is_good = false; // if we're re-creating buffer, chunks might've been uploaded in the old one
chunkrecord.offset = datasize;
chunkrecord.size = chunkiterator->vertices.size();
datasize += chunkrecord.size;
++chunkiterator;
}
// the odds for all created chunks to get replaced with empty ones are quite low, but the possibility does exist
if( datasize == 0 ) { return; }
// try to set up the buffer we need
::glGenBuffers( 1, &m_buffer );
bind_buffer();
if( m_buffer == 0 ) { return; } // if we didn't get a buffer we'll try again during the next draw call
// NOTE: we're using static_draw since it's generally true for all we have implemented at the moment
// TODO: allow to specify usage hint at the object creation, and pass it here
::glBufferData(
GL_ARRAY_BUFFER,
datasize * sizeof( gfx::basic_vertex ),
nullptr,
GL_STATIC_DRAW );
if( ::glGetError() == GL_OUT_OF_MEMORY ) {
// TBD: throw a bad_alloc?
ErrorLog( "openGL error: out of memory; failed to create a geometry buffer" );
delete_buffer();
return;
}
m_buffercapacity = datasize;
}
void void
opengl_vbogeometrybank::bind_buffer() { opengl_vbogeometrybank::bind_buffer() {

View File

@@ -53,6 +53,8 @@ private:
// release() subclass details // release() subclass details
void void
release_() override; release_() override;
void
setup_buffer();
void void
bind_buffer(); bind_buffer();
void void

View File

@@ -141,6 +141,8 @@ opengl_precipitation::update() {
void void
opengl_precipitation::render() { opengl_precipitation::render() {
if( m_texture == null_handle ) { return; }
GfxRenderer->Bind_Texture( m_texture ); GfxRenderer->Bind_Texture( m_texture );
// cache entry state // cache entry state

View File

@@ -39,6 +39,6 @@ private:
GLuint m_uvbuffer { (GLuint)-1 }; GLuint m_uvbuffer { (GLuint)-1 };
GLuint m_indexbuffer { (GLuint)-1 }; GLuint m_indexbuffer { (GLuint)-1 };
GLint m_textureunit { 0 }; GLint m_textureunit { 0 };
texture_handle m_texture { -1 }; texture_handle m_texture { null_handle };
float m_overcast { -1.f }; // cached overcast level, difference from current state triggers texture update float m_overcast { -1.f }; // cached overcast level, difference from current state triggers texture update
}; };

View File

@@ -27,6 +27,8 @@ http://mozilla.org/MPL/2.0/.
int const EU07_PICKBUFFERSIZE { 1024 }; // size of (square) textures bound with the pick framebuffer int const EU07_PICKBUFFERSIZE { 1024 }; // size of (square) textures bound with the pick framebuffer
int const EU07_ENVIRONMENTBUFFERSIZE { 256 }; // size of (square) environmental cube map texture int const EU07_ENVIRONMENTBUFFERSIZE { 256 }; // size of (square) environmental cube map texture
float const EU07_OPACITYDEFAULT { 0.5f };
bool bool
opengl_renderer::Init( GLFWwindow *Window ) { opengl_renderer::Init( GLFWwindow *Window ) {
@@ -329,6 +331,7 @@ opengl_renderer::Render() {
} }
// generate new frame // generate new frame
m_renderpass.draw_mode = rendermode::none; // force setup anew m_renderpass.draw_mode = rendermode::none; // force setup anew
opengl_texture::reset_unit_cache();
m_debugtimestext.clear(); m_debugtimestext.clear();
m_debugstats = debug_stats(); m_debugstats = debug_stats();
Render_pass( rendermode::color ); Render_pass( rendermode::color );
@@ -511,7 +514,7 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
setup_shadow_map( m_cabshadowtexture, m_cabshadowtexturematrix ); setup_shadow_map( m_cabshadowtexture, m_cabshadowtexturematrix );
// cache shadow colour in case we need to account for cab light // cache shadow colour in case we need to account for cab light
auto const shadowcolor{ m_shadowcolor }; auto const shadowcolor{ m_shadowcolor };
auto const *vehicle { simulation::Train->Dynamic() }; auto *vehicle { simulation::Train->Dynamic() };
if( vehicle->InteriorLightLevel > 0.f ) { if( vehicle->InteriorLightLevel > 0.f ) {
setup_shadow_color( glm::min( colors::white, shadowcolor + glm::vec4( vehicle->InteriorLight * vehicle->InteriorLightLevel, 1.f ) ) ); setup_shadow_color( glm::min( colors::white, shadowcolor + glm::vec4( vehicle->InteriorLight * vehicle->InteriorLightLevel, 1.f ) ) );
} }
@@ -525,6 +528,8 @@ opengl_renderer::Render_pass( rendermode const Mode ) {
if( vehicle->InteriorLightLevel > 0.f ) { if( vehicle->InteriorLightLevel > 0.f ) {
setup_shadow_color( shadowcolor ); setup_shadow_color( shadowcolor );
} }
// with the cab in place we can (finally) safely draw translucent part of the occupied vehicle
Render_Alpha( vehicle );
} }
if( m_environmentcubetexturesupport ) { if( m_environmentcubetexturesupport ) {
@@ -982,7 +987,7 @@ opengl_renderer::setup_drawing( bool const Alpha ) {
} }
else { else {
::glDisable( GL_BLEND ); ::glDisable( GL_BLEND );
::glAlphaFunc( GL_GREATER, 0.5f ); ::glAlphaFunc( GL_GREATER, EU07_OPACITYDEFAULT );
} }
switch( m_renderpass.draw_mode ) { switch( m_renderpass.draw_mode ) {
@@ -1536,14 +1541,14 @@ opengl_renderer::Insert( gfx::vertex_array &Vertices, gfx::geometrybank_handle c
// replaces data of specified chunk with the supplied vertex data, starting from specified offset // replaces data of specified chunk with the supplied vertex data, starting from specified offset
bool bool
opengl_renderer::Replace( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, std::size_t const Offset ) { opengl_renderer::Replace( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, int const Type, std::size_t const Offset ) {
return m_geometry.replace( Vertices, Geometry, Offset ); return m_geometry.replace( Vertices, Geometry, Offset );
} }
// adds supplied vertex data at the end of specified chunk // adds supplied vertex data at the end of specified chunk
bool bool
opengl_renderer::Append( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry ) { opengl_renderer::Append( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, int const Type ) {
return m_geometry.append( Vertices, Geometry ); return m_geometry.append( Vertices, Geometry );
} }
@@ -1563,13 +1568,13 @@ opengl_renderer::Fetch_Material( std::string const &Filename, bool const Loadnow
} }
void void
opengl_renderer::Bind_Material( material_handle const Material ) { opengl_renderer::Bind_Material( material_handle const Material, TSubModel *sm ) {
auto const &material = m_materials.material( Material ); auto const &material = m_materials.material( Material );
if( false == Global.BasicRenderer ) { if( false == Global.BasicRenderer ) {
m_textures.bind( textureunit::normals, material.textures[1] ); m_textures.bind( m_normaltextureunit - GL_TEXTURE0, material.textures[1] );
} }
m_textures.bind( textureunit::diffuse, material.textures[0] ); m_textures.bind( m_diffusetextureunit - GL_TEXTURE0, material.textures[0] );
} }
opengl_material const & opengl_material const &
@@ -1595,13 +1600,13 @@ opengl_renderer::select_unit( GLint const Textureunit ) {
texture_handle texture_handle
opengl_renderer::Fetch_Texture( std::string const &Filename, bool const Loadnow, GLint format_hint ) { opengl_renderer::Fetch_Texture( std::string const &Filename, bool const Loadnow, GLint format_hint ) {
return m_textures.create( Filename, Loadnow ); return m_textures.create( Filename, Loadnow, GL_RGBA );
} }
void void
opengl_renderer::Bind_Texture( texture_handle const Texture ) { opengl_renderer::Bind_Texture( texture_handle const Texture ) {
m_textures.bind( textureunit::diffuse, Texture ); m_textures.bind( m_diffusetextureunit - GL_TEXTURE0, Texture );
} }
void void
@@ -1623,13 +1628,13 @@ opengl_renderer::Texture( texture_handle const Texture ) const {
} }
void void
opengl_renderer::Pick_Control( std::function<void( TSubModel const * )> Callback ) { opengl_renderer::Pick_Control_Callback( std::function<void( TSubModel const * )> Callback ) {
m_control_pick_requests.emplace_back( Callback ); m_control_pick_requests.emplace_back( Callback );
} }
void void
opengl_renderer::Pick_Node( std::function<void( scene::basic_node * )> Callback ) { opengl_renderer::Pick_Node_Callback( std::function<void( scene::basic_node * )> Callback ) {
m_node_pick_requests.emplace_back( Callback ); m_node_pick_requests.emplace_back( Callback );
} }
@@ -2449,15 +2454,14 @@ opengl_renderer::Render( TSubModel *Submodel ) {
} }
#endif #endif
// material configuration: // material configuration:
auto const material{ (
Submodel->m_material < 0 ?
Submodel->ReplacableSkinId[ -Submodel->m_material ] : // zmienialne skóry
Submodel->m_material ) }; // również 0
// textures... // textures...
if( Submodel->m_material < 0 ) { // zmienialne skóry Bind_Material( material );
Bind_Material( Submodel->ReplacableSkinId[ -Submodel->m_material ] ); // ...colors and opacity...
} auto const opacity { clamp( Material( material ).get_or_guess_opacity(), 0.f, 1.f ) };
else {
// również 0
Bind_Material( Submodel->m_material );
}
// ...colors...
if( Submodel->fVisible < 1.f ) { if( Submodel->fVisible < 1.f ) {
// setup // setup
::glAlphaFunc( GL_GREATER, 0.f ); ::glAlphaFunc( GL_GREATER, 0.f );
@@ -2470,6 +2474,10 @@ opengl_renderer::Render( TSubModel *Submodel ) {
} }
else { else {
::glColor3fv( glm::value_ptr( Submodel->f4Diffuse ) ); // McZapkie-240702: zamiast ub ::glColor3fv( glm::value_ptr( Submodel->f4Diffuse ) ); // McZapkie-240702: zamiast ub
if( ( opacity != 0.f )
&& ( opacity != EU07_OPACITYDEFAULT ) ) {
::glAlphaFunc( GL_GREATER, opacity );
}
} }
// ...specular... // ...specular...
if( ( true == m_renderspecular ) && ( m_sunlight.specular.a > 0.01f ) ) { if( ( true == m_renderspecular ) && ( m_sunlight.specular.a > 0.01f ) ) {
@@ -2505,9 +2513,13 @@ opengl_renderer::Render( TSubModel *Submodel ) {
*/ */
// post-draw reset // post-draw reset
if( Submodel->fVisible < 1.f ) { if( Submodel->fVisible < 1.f ) {
::glAlphaFunc( GL_GREATER, 0.5f ); ::glAlphaFunc( GL_GREATER, EU07_OPACITYDEFAULT );
::glDisable( GL_BLEND ); ::glDisable( GL_BLEND );
} }
else if( ( opacity != 0.f )
&& ( opacity != EU07_OPACITYDEFAULT ) ) {
::glAlphaFunc( GL_GREATER, EU07_OPACITYDEFAULT );
}
if( ( true == m_renderspecular ) && ( m_sunlight.specular.a > 0.01f ) ) { if( ( true == m_renderspecular ) && ( m_sunlight.specular.a > 0.01f ) ) {
::glMaterialfv( GL_FRONT, GL_SPECULAR, glm::value_ptr( colors::none ) ); ::glMaterialfv( GL_FRONT, GL_SPECULAR, glm::value_ptr( colors::none ) );
} }
@@ -3104,6 +3116,11 @@ opengl_renderer::Render_Alpha( cell_sequence::reverse_iterator First, cell_seque
// translucent parts of vehicles // translucent parts of vehicles
for( auto *path : cell->m_paths ) { for( auto *path : cell->m_paths ) {
for( auto *dynamic : path->Dynamics ) { for( auto *dynamic : path->Dynamics ) {
if( ( false == FreeFlyModeFlag )
&& ( simulation::Train->Dynamic() == dynamic ) ) {
// delay drawing translucent parts of occupied vehicle until after the cab was drawn
continue;
}
Render_Alpha( dynamic ); Render_Alpha( dynamic );
} }
} }
@@ -3861,7 +3878,7 @@ opengl_renderer::Update( double const Deltatime ) {
&& ( true == FreeFlyModeFlag ) && ( true == FreeFlyModeFlag )
&& ( ( true == DebugModeFlag ) && ( ( true == DebugModeFlag )
|| ( true == EditorModeFlag ) ) ) { || ( true == EditorModeFlag ) ) ) {
if( ( false == m_control_pick_requests.empty() ) if( ( false == m_node_pick_requests.empty() )
|| ( m_updateaccumulator >= 1.0 ) ) { || ( m_updateaccumulator >= 1.0 ) ) {
Update_Pick_Node(); Update_Pick_Node();
} }

View File

@@ -56,10 +56,10 @@ public:
Insert( gfx::vertex_array &Vertices, gfx::geometrybank_handle const &Geometry, int const Type ) override; Insert( gfx::vertex_array &Vertices, gfx::geometrybank_handle const &Geometry, int const Type ) override;
// replaces data of specified chunk with the supplied vertex data, starting from specified offset // replaces data of specified chunk with the supplied vertex data, starting from specified offset
bool bool
Replace( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, std::size_t const Offset = 0 ) override; Replace( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, int const Type, std::size_t const Offset = 0 ) override;
// adds supplied vertex data at the end of specified chunk // adds supplied vertex data at the end of specified chunk
bool bool
Append( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry ) override; Append( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, int const Type ) override;
// provides direct access to vertex data of specfied chunk // provides direct access to vertex data of specfied chunk
gfx::vertex_array const & gfx::vertex_array const &
Vertices( gfx::geometry_handle const &Geometry ) const override; Vertices( gfx::geometry_handle const &Geometry ) const override;
@@ -67,7 +67,7 @@ public:
material_handle material_handle
Fetch_Material( std::string const &Filename, bool const Loadnow = true ) override; Fetch_Material( std::string const &Filename, bool const Loadnow = true ) override;
void void
Bind_Material( material_handle const Material ) override; Bind_Material( material_handle const Material, TSubModel *sm = nullptr ) override;
opengl_material const & opengl_material const &
Material( material_handle const Material ) const override; Material( material_handle const Material ) const override;
// shader methods // shader methods
@@ -85,9 +85,9 @@ public:
Texture( texture_handle const Texture ) const override; Texture( texture_handle const Texture ) const override;
// utility methods // utility methods
void void
Pick_Control( std::function<void( TSubModel const * )> Callback ) override; Pick_Control_Callback( std::function<void( TSubModel const * )> Callback ) override;
void void
Pick_Node( std::function<void( scene::basic_node * )> Callback ) override; Pick_Node_Callback( std::function<void( scene::basic_node * )> Callback ) override;
TSubModel const * TSubModel const *
Pick_Control() const override { return m_pickcontrolitem; } Pick_Control() const override { return m_pickcontrolitem; }
scene::basic_node const * scene::basic_node const *

View File

@@ -11,7 +11,6 @@ http://mozilla.org/MPL/2.0/.
#include "openglskydome.h" #include "openglskydome.h"
#include "simulationenvironment.h" #include "simulationenvironment.h"
#include "openglgeometrybank.h"
opengl_skydome::~opengl_skydome() { opengl_skydome::~opengl_skydome() {
@@ -58,7 +57,14 @@ void opengl_skydome::update() {
if( true == skydome.is_dirty() ) { if( true == skydome.is_dirty() ) {
if( ( m_coloursbuffer > 0 ) && ( m_coloursbuffer != (GLuint)-1 ) ) { if( ( m_coloursbuffer > 0 ) && ( m_coloursbuffer != (GLuint)-1 ) ) {
::glBindBuffer( GL_ARRAY_BUFFER, m_coloursbuffer ); ::glBindBuffer( GL_ARRAY_BUFFER, m_coloursbuffer );
auto const &colors { skydome.colors() }; auto &colors{ skydome.colors() };
/*
float twilightfactor = clamp( -simulation::Environment.sun().getAngle(), 0.0f, 18.0f ) / 18.0f;
auto gamma = interpolate( glm::vec3( 0.45f ), glm::vec3( 1.0f ), twilightfactor );
for( auto & color : colors ) {
color = glm::pow( color, gamma );
}
*/
::glBufferSubData( GL_ARRAY_BUFFER, 0, colors.size() * sizeof( glm::vec3 ), colors.data() ); ::glBufferSubData( GL_ARRAY_BUFFER, 0, colors.size() * sizeof( glm::vec3 ), colors.data() );
skydome.is_dirty() = false; skydome.is_dirty() = false;
} }

View File

@@ -598,6 +598,10 @@ namespace ImGui
IMGUI_API void* MemAlloc(size_t size); IMGUI_API void* MemAlloc(size_t size);
IMGUI_API void MemFree(void* ptr); IMGUI_API void MemFree(void* ptr);
// by zfedoran, https://github.com/ocornut/imgui/issues/1901
IMGUI_API bool BufferingBar( const char* label, float value, const ImVec2& size_arg, const ImU32& bg_col, const ImU32& fg_col );
IMGUI_API bool Spinner( const char* label, float radius, int thickness, const ImU32& color );
} // namespace ImGui } // namespace ImGui
// Flags for ImGui::Begin() // Flags for ImGui::Begin()

View File

@@ -5728,3 +5728,91 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool* p_selected,
} }
return false; return false;
} }
// by zfedoran, https://github.com/ocornut/imgui/issues/1901
bool ImGui::BufferingBar( const char* label, float value, const ImVec2& size_arg, const ImU32& bg_col, const ImU32& fg_col ) {
ImGuiWindow* window = GetCurrentWindow();
if( window->SkipItems )
return false;
ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style;
const ImGuiID id = window->GetID( label );
ImVec2 pos = window->DC.CursorPos;
ImVec2 size = size_arg;
size.x -= style.FramePadding.x * 2;
const ImRect bb( pos, ImVec2( pos.x + size.x, pos.y + size.y ) );
ItemSize( bb, style.FramePadding.y );
if( !ItemAdd( bb, id ) )
return false;
// Render
const float circleStart = std::max( size.x * 0.7f, size.x - 30.f );
const float circleEnd = size.x;
const float circleWidth = circleEnd - circleStart;
window->DrawList->AddRectFilled( bb.Min, ImVec2( pos.x + circleStart, bb.Max.y ), bg_col );
window->DrawList->AddRectFilled( bb.Min, ImVec2( pos.x + circleStart * value, bb.Max.y ), fg_col );
const float t = g.FrameCount * 0.1f; // g.Time;
const float r = size.y / 2;
const float speed = 1.5f;
const float a = speed * 0;
const float b = speed * 0.333f;
const float c = speed * 0.666f;
const float o1 = ( circleWidth + r ) * ( t + a - speed * (int)( ( t + a ) / speed ) ) / speed;
const float o2 = ( circleWidth + r ) * ( t + b - speed * (int)( ( t + b ) / speed ) ) / speed;
const float o3 = ( circleWidth + r ) * ( t + c - speed * (int)( ( t + c ) / speed ) ) / speed;
window->DrawList->AddCircleFilled( ImVec2( pos.x + circleEnd - o1, bb.Min.y + r ), r, bg_col );
window->DrawList->AddCircleFilled( ImVec2( pos.x + circleEnd - o2, bb.Min.y + r ), r, bg_col );
window->DrawList->AddCircleFilled( ImVec2( pos.x + circleEnd - o3, bb.Min.y + r ), r, bg_col );
return true;
}
bool ImGui::Spinner( const char* label, float radius, int thickness, const ImU32& color ) {
ImGuiWindow* window = GetCurrentWindow();
if( window->SkipItems )
return false;
ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style;
const ImGuiID id = window->GetID( label );
ImVec2 pos = window->DC.CursorPos;
ImVec2 size( ( radius ) * 2, ( radius + style.FramePadding.y ) * 2 );
const ImRect bb( pos, ImVec2( pos.x + size.x, pos.y + size.y ) );
ItemSize( bb, style.FramePadding.y );
if( !ItemAdd( bb, id ) )
return false;
// Render
window->DrawList->PathClear();
auto progress { g.FrameCount * 0.1f };
int num_segments = 30;
int start = abs( ImSin( progress * 1.8f )*( num_segments - 5 ) );
const float a_min = IM_PI * 2.0f * ( (float)start ) / (float)num_segments;
const float a_max = IM_PI * 2.0f * ( (float)num_segments - 3 ) / (float)num_segments;
const ImVec2 centre = ImVec2( pos.x + radius, pos.y + radius + style.FramePadding.y );
for( int i = 0; i < num_segments; i++ ) {
const float a = a_min + ( (float)i / (float)num_segments ) * ( a_max - a_min );
window->DrawList->PathLineTo( ImVec2( centre.x + ImCos( a + progress * 8 ) * radius,
centre.y + ImSin( a + progress * 8 ) * radius ) );
}
window->DrawList->PathStroke( color, false, thickness );
return true;
}

View File

@@ -31,14 +31,14 @@ public:
// creates a new geometry chunk of specified type from supplied vertex data, in specified bank. returns: handle to the chunk or NULL // creates a new geometry chunk of specified type from supplied vertex data, in specified bank. returns: handle to the chunk or NULL
virtual auto Insert( gfx::vertex_array &Vertices, gfx::geometrybank_handle const &Geometry, int const Type ) -> gfx::geometry_handle = 0; virtual auto Insert( gfx::vertex_array &Vertices, gfx::geometrybank_handle const &Geometry, int const Type ) -> gfx::geometry_handle = 0;
// replaces data of specified chunk with the supplied vertex data, starting from specified offset // replaces data of specified chunk with the supplied vertex data, starting from specified offset
virtual auto Replace( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, std::size_t const Offset = 0 ) -> bool = 0; virtual auto Replace( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, int const Type, std::size_t const Offset = 0 ) -> bool = 0;
// adds supplied vertex data at the end of specified chunk // adds supplied vertex data at the end of specified chunk
virtual auto Append( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry ) -> bool = 0; virtual auto Append( gfx::vertex_array &Vertices, gfx::geometry_handle const &Geometry, int const Type ) -> bool = 0;
// provides direct access to vertex data of specfied chunk // provides direct access to vertex data of specfied chunk
virtual auto Vertices( gfx::geometry_handle const &Geometry ) const ->gfx::vertex_array const & = 0; virtual auto Vertices( gfx::geometry_handle const &Geometry ) const ->gfx::vertex_array const & = 0;
// material methods // material methods
virtual auto Fetch_Material( std::string const &Filename, bool const Loadnow = true ) -> material_handle = 0; virtual auto Fetch_Material( std::string const &Filename, bool const Loadnow = true ) -> material_handle = 0;
virtual void Bind_Material( material_handle const Material ) = 0; virtual void Bind_Material( material_handle const Material, TSubModel *sm = nullptr ) = 0;
virtual auto Material( material_handle const Material ) const -> opengl_material const & = 0; virtual auto Material( material_handle const Material ) const -> opengl_material const & = 0;
// shader methods // shader methods
virtual auto Fetch_Shader( std::string const &name ) -> std::shared_ptr<gl::program> = 0; virtual auto Fetch_Shader( std::string const &name ) -> std::shared_ptr<gl::program> = 0;
@@ -49,8 +49,8 @@ public:
virtual auto Texture( texture_handle const Texture ) -> opengl_texture & = 0; virtual auto Texture( texture_handle const Texture ) -> opengl_texture & = 0;
virtual auto Texture( texture_handle const Texture ) const -> opengl_texture const & = 0; virtual auto Texture( texture_handle const Texture ) const -> opengl_texture const & = 0;
// utility methods // utility methods
virtual void Pick_Control( std::function<void( TSubModel const * )> Callback ) = 0; virtual void Pick_Control_Callback( std::function<void( TSubModel const * )> Callback ) = 0;
virtual void Pick_Node( std::function<void( scene::basic_node * )> Callback ) = 0; virtual void Pick_Node_Callback( std::function<void( scene::basic_node * )> Callback ) = 0;
virtual auto Pick_Control() const -> TSubModel const * = 0; virtual auto Pick_Control() const -> TSubModel const * = 0;
virtual auto Pick_Node() const -> scene::basic_node const * = 0; virtual auto Pick_Node() const -> scene::basic_node const * = 0;

View File

@@ -118,6 +118,7 @@ world_environment::update() {
Global.DayLight.position = m_moon.getDirection(); Global.DayLight.position = m_moon.getDirection();
Global.DayLight.direction = -1.0f * m_moon.getDirection(); Global.DayLight.direction = -1.0f * m_moon.getDirection();
keylightintensity = moonlightlevel; keylightintensity = moonlightlevel;
m_lightintensity = 0.35f;
// if the moon is up, it overrides the twilight // if the moon is up, it overrides the twilight
twilightfactor = 0.0f; twilightfactor = 0.0f;
keylightcolor = glm::vec3( 255.0f / 255.0f, 242.0f / 255.0f, 202.0f / 255.0f ); keylightcolor = glm::vec3( 255.0f / 255.0f, 242.0f / 255.0f, 202.0f / 255.0f );
@@ -128,6 +129,7 @@ world_environment::update() {
Global.DayLight.position = m_sun.getDirection(); Global.DayLight.position = m_sun.getDirection();
Global.DayLight.direction = -1.0f * m_sun.getDirection(); Global.DayLight.direction = -1.0f * m_sun.getDirection();
keylightintensity = sunlightlevel; keylightintensity = sunlightlevel;
m_lightintensity = 1.0f;
// include 'golden hour' effect in twilight lighting // include 'golden hour' effect in twilight lighting
float const duskfactor = 1.0f - clamp( Global.SunAngle, 0.0f, 18.0f ) / 18.0f; float const duskfactor = 1.0f - clamp( Global.SunAngle, 0.0f, 18.0f ) / 18.0f;
keylightcolor = interpolate( keylightcolor = interpolate(

View File

@@ -39,6 +39,12 @@ public:
// calculates current weather // calculates current weather
void compute_weather() const; void compute_weather() const;
// data access // data access
inline auto const &
sun() const {
return m_sun; }
inline auto const &
light_intensity() const {
return m_lightintensity; }
inline auto const & inline auto const &
skydome() const { skydome() const {
return m_skydome; } return m_skydome; }
@@ -74,6 +80,7 @@ private:
cStars m_stars; cStars m_stars;
cSun m_sun; cSun m_sun;
cMoon m_moon; cMoon m_moon;
float m_lightintensity { 1.f };
TSky m_clouds; TSky m_clouds;
basic_precipitation m_precipitation; basic_precipitation m_precipitation;
sound_source m_precipitationsound { sound_placement::external, -1 }; sound_source m_precipitationsound { sound_placement::external, -1 };

View File

@@ -118,7 +118,7 @@ state_serializer::deserialize( cParser &Input, scene::scratch_data &Scratchpad )
} }
timenow = std::chrono::steady_clock::now(); timenow = std::chrono::steady_clock::now();
if( std::chrono::duration_cast<std::chrono::milliseconds>( timenow - timelast ).count() >= 200 ) { if( std::chrono::duration_cast<std::chrono::milliseconds>( timenow - timelast ).count() >= 50 ) {
timelast = timenow; timelast = timenow;
glfwPollEvents(); glfwPollEvents();
Application.set_progress( Input.getProgress(), Input.getFullProgress() ); Application.set_progress( Input.getProgress(), Input.getFullProgress() );

View File

@@ -3,6 +3,7 @@
#include "skydome.h" #include "skydome.h"
#include "color.h" #include "color.h"
#include "utilities.h" #include "utilities.h"
#include "simulationenvironment.h"
// sky gradient based on "A practical analytic model for daylight" // sky gradient based on "A practical analytic model for daylight"
// by A. J. Preetham Peter Shirley Brian Smits (University of Utah) // by A. J. Preetham Peter Shirley Brian Smits (University of Utah)
@@ -189,6 +190,9 @@ float CSkyDome::PerezFunctionO2( float Perezcoeffs[ 5 ], const float Icostheta,
void CSkyDome::RebuildColors() { void CSkyDome::RebuildColors() {
float twilightfactor = clamp( -simulation::Environment.sun().getAngle(), 0.0f, 18.0f ) / 18.0f;
auto gammacorrection = interpolate( glm::vec3( 0.45f ), glm::vec3( 1.0f ), twilightfactor );
// get zenith luminance // get zenith luminance
float const chi = ( (4.0f / 9.0f) - (m_turbidity / 120.0f) ) * ( M_PI - (2.0f * m_thetasun) ); float const chi = ( (4.0f / 9.0f) - (m_turbidity / 120.0f) ) * ( M_PI - (2.0f * m_thetasun) );
float zenithluminance = ( (4.0453f * m_turbidity) - 4.9710f ) * std::tan( chi ) - (0.2155f * m_turbidity) + 2.4192f; float zenithluminance = ( (4.0453f * m_turbidity) - 4.9710f ) * std::tan( chi ) - (0.2155f * m_turbidity) + 2.4192f;
@@ -260,6 +264,7 @@ void CSkyDome::RebuildColors() {
colorconverter.z = 1.0f - std::exp( -m_expfactor * colorconverter.z ); colorconverter.z = 1.0f - std::exp( -m_expfactor * colorconverter.z );
} }
colorconverter.y = clamp( colorconverter.y * 1.15f, 0.0f, 1.0f );
// desaturate sky colour, based on overcast level // desaturate sky colour, based on overcast level
if( colorconverter.y > 0.0f ) { if( colorconverter.y > 0.0f ) {
colorconverter.y *= ( 1.0f - m_overcast ); colorconverter.y *= ( 1.0f - m_overcast );
@@ -296,6 +301,11 @@ void CSkyDome::RebuildColors() {
color.x = 0.20f * color.z; color.x = 0.20f * color.z;
color.y = 0.65f * color.z; color.y = 0.65f * color.z;
color = color * ( 1.15f - vertex.y ); // simple gradient, darkening towards the top color = color * ( 1.15f - vertex.y ); // simple gradient, darkening towards the top
}
// gamma correction
color = glm::pow( color, gammacorrection );
if( Global.GfxFramebufferSRGB ) {
color = glm::pow( color, glm::vec3( 2.2f ) - ( gammacorrection * 0.5f ) );
} }
// save // save
m_colours[ i ] = color; m_colours[ i ] = color;

View File

@@ -26,7 +26,7 @@ public:
std::vector<glm::vec3> const & vertices() const { std::vector<glm::vec3> const & vertices() const {
return m_vertices; } return m_vertices; }
std::vector<glm::vec3> const & colors() const { std::vector<glm::vec3> & colors() {
return m_colours; } return m_colours; }
std::vector<std::uint16_t> const & indices() const { std::vector<std::uint16_t> const & indices() const {
return m_indices; } return m_indices; }

View File

@@ -117,3 +117,5 @@ int const null_handle = 0;
#else #else
#include "imgui.h" #include "imgui.h"
#endif #endif
#pragma warning( disable : 5033 ) // "register is no longer a supported storage class" but it's all over python headers

View File

@@ -70,7 +70,7 @@ cSun::getDirection() {
} }
float float
cSun::getAngle() { cSun::getAngle() const {
return (float)m_body.elevref; return (float)m_body.elevref;
} }

2
sun.h
View File

@@ -23,7 +23,7 @@ public:
// returns vector pointing at the sun // returns vector pointing at the sun
glm::vec3 getDirection(); glm::vec3 getDirection();
// returns current elevation above horizon // returns current elevation above horizon
float getAngle(); float getAngle() const;
// return current hour angle // return current hour angle
double getHourAngle() const; double getHourAngle() const;
// returns current intensity of the sun // returns current intensity of the sun

View File

@@ -195,7 +195,7 @@ ui_layer::render() {
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); glLoadIdentity();
/*
glPushAttrib( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT ); // blendfunc included since 3rd party gui doesn't play nice glPushAttrib( GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT ); // blendfunc included since 3rd party gui doesn't play nice
glDisable( GL_LIGHTING ); glDisable( GL_LIGHTING );
glDisable( GL_DEPTH_TEST ); glDisable( GL_DEPTH_TEST );
@@ -206,18 +206,10 @@ ui_layer::render() {
::glColor4fv( glm::value_ptr( colors::white ) ); ::glColor4fv( glm::value_ptr( colors::white ) );
// render code here // render code here
render_background();
render_texture(); render_texture();
glDisable( GL_TEXTURE_2D );
glDisable( GL_TEXTURE_CUBE_MAP );
render_progress();
glDisable( GL_BLEND );
glPopAttrib(); glPopAttrib();
*/
// imgui ui code // imgui ui code
::glPushClientAttrib( GL_CLIENT_VERTEX_ARRAY_BIT ); ::glPushClientAttrib( GL_CLIENT_VERTEX_ARRAY_BIT );
@@ -232,6 +224,8 @@ ui_layer::render() {
ImGui_ImplGlfw_NewFrame(); ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame(); ImGui::NewFrame();
render_background();
render_progress();
render_panels(); render_panels();
render_tooltip(); render_tooltip();
// template method implementation // template method implementation
@@ -265,7 +259,7 @@ void
ui_layer::set_background( std::string const &Filename ) { ui_layer::set_background( std::string const &Filename ) {
if( false == Filename.empty() ) { if( false == Filename.empty() ) {
m_background = GfxRenderer->Fetch_Texture( Filename ); m_background = GfxRenderer->Fetch_Texture( Filename, true, GL_RGBA );
} }
else { else {
m_background = null_handle; m_background = null_handle;
@@ -283,52 +277,27 @@ ui_layer::set_background( std::string const &Filename ) {
void void
ui_layer::render_progress() { ui_layer::render_progress() {
if( (m_progress == 0.0f) && (m_subtaskprogress == 0.0f) ) return; if ((m_progress == 0.0f) && (m_subtaskprogress == 0.0f))
return;
glm::vec2 origin, size; ImGui::SetNextWindowPos(ImVec2(50, Global.iWindowHeight - 50));
if( m_progressbottom == true ) { ImGui::SetNextWindowSize(ImVec2(0, 0));
origin = glm::vec2{ 0.0f, 768.0f - 20.0f }; ImGui::Begin(
size = glm::vec2{ 1024.0f, 20.0f }; "Loading", nullptr,
} ImGuiWindowFlags_NoTitleBar
else { | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse
origin = glm::vec2{ 75.0f, 640.0f }; | ImGuiWindowFlags_NoCollapse );
size = glm::vec2{ 320.0f, 16.0f };
}
quad( glm::vec4( origin.x, origin.y, origin.x + size.x, origin.y + size.y ), glm::vec4(0.0f, 0.0f, 0.0f, 0.25f) ); const ImU32 col = ImGui::ColorConvertFloat4ToU32( ImVec4( 8.0f / 255.0f, 160.0f / 255.0f, 8.0f / 255.0f, 1.0f ) ); // ImGui::GetColorU32( ImGuiCol_ButtonHovered );
// secondary bar const ImU32 bg = ImGui::ColorConvertFloat4ToU32( ImVec4( 8.0f / 255.0f, 160.0f / 255.0f, 8.0f / 255.0f, 0.35f ) ); // ImGui::GetColorU32( ImGuiCol_Button );
if( m_subtaskprogress ) { /*
quad( ImGui::Spinner( "##spinner", 8, 4, col );
glm::vec4( origin.x, origin.y, origin.x + size.x * m_subtaskprogress, origin.y + size.y), ImGui::SetCursorPos( ImVec2( 40, 18 ) );
glm::vec4( 8.0f/255.0f, 160.0f/255.0f, 8.0f/255.0f, 0.35f ) ); */
} ImGui::SetCursorPos( ImVec2( 15, 15 ) );
// primary bar ImGui::BufferingBar( "##buffer_bar", m_progress, ImVec2( Global.iWindowWidth - 125, 4 ), bg, col );
if( m_progress ) {
quad(
glm::vec4( origin.x, origin.y, origin.x + size.x * m_progress, origin.y + size.y ),
glm::vec4( 8.0f / 255.0f, 160.0f / 255.0f, 8.0f / 255.0f, 1.0f ) );
}
if( false == m_progresstext.empty() ) { ImGui::End();
float const screenratio = static_cast<float>( Global.iWindowWidth ) / Global.iWindowHeight;
float const width =
( screenratio >= (4.0f/3.0f) ?
( 4.0f / 3.0f ) * Global.iWindowHeight :
Global.iWindowWidth );
float const heightratio =
( screenratio >= ( 4.0f / 3.0f ) ?
Global.iWindowHeight / 768.f :
Global.iWindowHeight / 768.f * screenratio / ( 4.0f / 3.0f ) );
float const height = 768.0f * heightratio;
::glColor4f( 216.0f / 255.0f, 216.0f / 255.0f, 216.0f / 255.0f, 1.0f );
auto const charsize = 9.0f;
auto const textwidth = m_progresstext.size() * charsize;
auto const textheight = 12.0f;
::glRasterPos2f(
( 0.5f * ( Global.iWindowWidth - width ) + origin.x * heightratio ) + ( ( size.x * heightratio - textwidth ) * 0.5f * heightratio ),
( 0.5f * ( Global.iWindowHeight - height ) + origin.y * heightratio ) + ( charsize ) + ( ( size.y * heightratio - textheight ) * 0.5f * heightratio ) );
}
} }
void void
@@ -351,23 +320,22 @@ ui_layer::render_tooltip() {
void void
ui_layer::render_background() { ui_layer::render_background() {
if( m_background == 0 ) return; if (m_background == 0)
// NOTE: we limit/expect the background to come with 4:3 ratio. return;
// TODO, TBD: if we expose texture width or ratio from texture object, this limitation could be lifted
GfxRenderer->Bind_Texture( m_background ); ImVec2 size = ImGui::GetIO().DisplaySize;
auto const height { 768.0f }; opengl_texture &tex = GfxRenderer->Texture(m_background);
auto const &texture = GfxRenderer->Texture( m_background ); tex.create();
float const width = (
texture.width() == texture.height() ? ImGui::SetNextWindowPos(ImVec2(0, 0));
1024.0f : // legacy mode, square texture displayed as 4:3 image ImGui::SetNextWindowSize(size);
texture.width() / ( texture.height() / 768.0f ) ); ImGui::Begin(
quad( "Logo", nullptr,
glm::vec4( ImGuiWindowFlags_NoTitleBar
( 1024.0f * 0.5f ) - ( width * 0.5f ), | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse
( 768.0f * 0.5f ) - ( height * 0.5f ), | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoBringToFrontOnFocus );
( 1024.0f * 0.5f ) - ( width * 0.5f ) + width, ImGui::Image(reinterpret_cast<void *>(tex.id), size, ImVec2(0, 1), ImVec2(1, 0));
( 768.0f * 0.5f ) - ( height * 0.5f ) + height ), ImGui::End();
colors::white );
} }
void void

104
uiwidgets.cpp Normal file
View File

@@ -0,0 +1,104 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#include "stdafx.h"
#include "uiwidgets.h"
#include "imgui_impl_glfw.h"
#ifdef EU07_USEIMGUIIMPLOPENGL2
#include "imgui_impl_opengl2.h"
#else
#include "imgui_impl_opengl3.h"
#endif
// by zfedoran, https://github.com/ocornut/imgui/issues/1901
namespace ImGui {
bool BufferingBar( const char* label, float value, const ImVec2& size_arg, const ImU32& bg_col, const ImU32& fg_col ) {
ImGuiWindow* window = GetCurrentWindow();
if( window->SkipItems )
return false;
ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style;
const ImGuiID id = window->GetID( label );
ImVec2 pos = window->DC.CursorPos;
ImVec2 size = size_arg;
size.x -= style.FramePadding.x * 2;
const ImRect bb( pos, ImVec2( pos.x + size.x, pos.y + size.y ) );
ItemSize( bb, style.FramePadding.y );
if( !ItemAdd( bb, id ) )
return false;
// Render
const float circleStart = size.x * 0.7f;
const float circleEnd = size.x;
const float circleWidth = circleEnd - circleStart;
window->DrawList->AddRectFilled( bb.Min, ImVec2( pos.x + circleStart, bb.Max.y ), bg_col );
window->DrawList->AddRectFilled( bb.Min, ImVec2( pos.x + circleStart * value, bb.Max.y ), fg_col );
const float t = g.Time;
const float r = size.y / 2;
const float speed = 1.5f;
const float a = speed * 0;
const float b = speed * 0.333f;
const float c = speed * 0.666f;
const float o1 = ( circleWidth + r ) * ( t + a - speed * (int)( ( t + a ) / speed ) ) / speed;
const float o2 = ( circleWidth + r ) * ( t + b - speed * (int)( ( t + b ) / speed ) ) / speed;
const float o3 = ( circleWidth + r ) * ( t + c - speed * (int)( ( t + c ) / speed ) ) / speed;
window->DrawList->AddCircleFilled( ImVec2( pos.x + circleEnd - o1, bb.Min.y + r ), r, bg_col );
window->DrawList->AddCircleFilled( ImVec2( pos.x + circleEnd - o2, bb.Min.y + r ), r, bg_col );
window->DrawList->AddCircleFilled( ImVec2( pos.x + circleEnd - o3, bb.Min.y + r ), r, bg_col );
}
bool Spinner( const char* label, float radius, int thickness, const ImU32& color ) {
ImGuiWindow* window = GetCurrentWindow();
if( window->SkipItems )
return false;
ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style;
const ImGuiID id = window->GetID( label );
ImVec2 pos = window->DC.CursorPos;
ImVec2 size( ( radius ) * 2, ( radius + style.FramePadding.y ) * 2 );
const ImRect bb( pos, ImVec2( pos.x + size.x, pos.y + size.y ) );
ItemSize( bb, style.FramePadding.y );
if( !ItemAdd( bb, id ) )
return false;
// Render
window->DrawList->PathClear();
int num_segments = 30;
int start = abs( ImSin( g.Time*1.8f )*( num_segments - 5 ) );
const float a_min = IM_PI * 2.0f * ( (float)start ) / (float)num_segments;
const float a_max = IM_PI * 2.0f * ( (float)num_segments - 3 ) / (float)num_segments;
const ImVec2 centre = ImVec2( pos.x + radius, pos.y + radius + style.FramePadding.y );
for( int i = 0; i < num_segments; i++ ) {
const float a = a_min + ( (float)i / (float)num_segments ) * ( a_max - a_min );
window->DrawList->PathLineTo( ImVec2( centre.x + ImCos( a + g.Time * 8 ) * radius,
centre.y + ImSin( a + g.Time * 8 ) * radius ) );
}
window->DrawList->PathStroke( color, false, thickness );
}
} // namespace ImGui

17
uiwidgets.h Normal file
View File

@@ -0,0 +1,17 @@
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#pragma once
namespace ImGui {
bool BufferingBar( const char* label, float value, const ImVec2& size_arg, const ImU32& bg_col, const ImU32& fg_col );
bool Spinner( const char* label, float radius, int thickness, const ImU32& color );
} // namespace ImGui

View File

@@ -487,3 +487,13 @@ deserialize_random_set( cParser &Input, char const *Break ) {
return ""; return "";
} }
} }
int count_trailing_zeros( uint32_t val )
{
int r = 0;
for( uint32_t shift = 1; !( val & shift ); shift <<= 1 )
r++;
return r;
}

View File

@@ -334,6 +334,8 @@ glm::dvec3 LoadPoint( class cParser &Input );
std::string std::string
deserialize_random_set( cParser &Input, char const *Break = "\n\r\t ;" ); deserialize_random_set( cParser &Input, char const *Break = "\n\r\t ;" );
int count_trailing_zeros( uint32_t val );
namespace threading { namespace threading {
// simple POD pairing of a data item and a mutex // simple POD pairing of a data item and a mutex