16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-18 20:29:17 +02:00
This commit is contained in:
VB
2017-03-20 22:37:49 +01:00
46 changed files with 3170 additions and 2508 deletions

View File

@@ -53,6 +53,13 @@ opengl_texture::load() {
// data state will be set by called loader, so we're all done here
if( data_state == resource_state::good ) {
has_alpha = (
data_components == GL_RGBA ?
true :
false );
size = data.size() / 1024;
return;
}
@@ -473,6 +480,16 @@ opengl_texture::load_TGA() {
return;
}
downsize( GL_BGRA );
if( ( data_width > Global::iMaxTextureSize ) || ( data_height > Global::iMaxTextureSize ) ) {
// for non-square textures there's currently possibility the scaling routine will have to abort
// before it gets all work done
data_state = resource_state::failed;
return;
}
// TODO: add horizontal/vertical data flip, based on the descriptor (18th) header byte
// fill remaining data info
data_mapcount = 1;
data_format = GL_BGRA;
@@ -485,82 +502,101 @@ opengl_texture::load_TGA() {
return;
}
void
resource_state
opengl_texture::bind() {
if( false == is_ready ) {
create();
if( data_state != resource_state::good ) {
return data_state;
}
}
::glBindTexture( GL_TEXTURE_2D, id );
return data_state;
}
resource_state
opengl_texture::create() {
if( data_state != resource_state::good ) {
// don't bother until we have useful texture data
return;
return data_state;
}
::glGenTextures( 1, &id );
::glBindTexture( GL_TEXTURE_2D, id );
// TODO: consider creating and storing low-res version of the texture if it's ever unloaded from the gfx card,
// as a placeholder until it can be loaded again
if( id == -1 ) {
// analyze specified texture traits
bool wraps{ true };
bool wrapt{ true };
for( auto const &trait : traits ) {
::glGenTextures( 1, &id );
::glBindTexture( GL_TEXTURE_2D, id );
switch( trait ) {
// analyze specified texture traits
bool wraps{ true };
bool wrapt{ true };
for( auto const &trait : traits ) {
case 's': { wraps = false; break; }
case 't': { wrapt = false; break; }
switch( trait ) {
case 's': { wraps = false; break; }
case 't': { wrapt = false; 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 ) );
::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();
set_filtering();
if( data_mapcount == 1 ) {
// fill missing mipmaps if needed
::glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE );
}
// upload texture data
int dataoffset = 0,
datasize = 0,
datawidth = data_width,
dataheight = data_height;
for( int maplevel = 0; maplevel < data_mapcount; ++maplevel ) {
if( data_mapcount == 1 ) {
// fill missing mipmaps if needed
::glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE );
}
// upload texture data
int dataoffset = 0,
datasize = 0,
datawidth = data_width,
dataheight = data_height;
for( int maplevel = 0; maplevel < data_mapcount; ++maplevel ) {
if( ( data_format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT )
|| ( data_format == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT )
|| ( data_format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ) ) {
// compressed dds formats
int const datablocksize =
( data_format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ?
if( ( data_format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT )
|| ( data_format == GL_COMPRESSED_RGBA_S3TC_DXT3_EXT )
|| ( data_format == GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ) ) {
// compressed dds formats
int const datablocksize =
( data_format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ?
8 :
16 );
datasize = ( ( std::max(datawidth, 4) + 3 ) / 4 ) * ( ( std::max(dataheight, 4) + 3 ) / 4 ) * datablocksize;
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] );
::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{
// uncompressed texture data
::glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGBA8,
data_width, data_height, 0,
data_format, GL_UNSIGNED_BYTE, (GLubyte *)&data[0] );
dataoffset += datasize;
datawidth = std::max( datawidth / 2, 1 );
dataheight = std::max( dataheight / 2, 1 );
}
else {
// uncompressed texture data
::glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGBA8,
data_width, data_height, 0,
data_format, GL_UNSIGNED_BYTE, (GLubyte *)&data[ 0 ] );
}
}
data.resize( 0 ); // TBD, TODO: keep the texture data if we start doing some gpu data cleaning down the road
/*
data_state = resource_state::none;
*/
data_state = resource_state::good;
is_ready = true;
}
is_ready = true;
has_alpha = (
data_components == GL_RGBA ?
true :
false );
data.resize( 0 ); // TBD, TODO: keep the texture data if we start doing some gpu data cleaning down the road
data_state = resource_state::none;
return data_state;
}
void
@@ -628,6 +664,31 @@ opengl_texture::set_filtering() {
}
}
void
opengl_texture::downsize( GLuint const Format ) {
while( ( data_width > Global::iMaxTextureSize ) || ( data_height > Global::iMaxTextureSize ) ) {
// scale down the base texture, if it's larger than allowed maximum
// NOTE: scaling is uniform along both axes, meaning non-square textures can drop below the maximum
// TODO: replace with proper scaling function once we have image middleware in place
if( ( data_width < 2 ) || ( data_height < 2 ) ) {
// can't go any smaller
break;
}
switch( Format ) {
case GL_RGB: { downsample< glm::tvec3<std::uint8_t> >( data_width, data_height, data.data() ); break; }
case GL_BGRA:
case GL_RGBA: { downsample< glm::tvec4<std::uint8_t> >( data_width, data_height, data.data() ); break; }
default: { break; }
}
data_width /= 2;
data_height /= 2;
data.resize( data.size() / 4 ); // not strictly needed, but, eh
};
}
void
texture_manager::Init() {
}
@@ -733,7 +794,9 @@ texture_manager::GetTextureId( std::string Filename, std::string const &Dir, int
if( true == Loadnow ) {
Texture( textureindex ).load();
#ifndef EU07_DEFERRED_TEXTURE_UPLOAD
Texture( textureindex ).create();
#endif
}
return textureindex;
@@ -753,20 +816,77 @@ texture_manager::Bind( texture_manager::size_type const Id ) {
// TODO: do binding in texture object, add support for other types
if( Id != 0 ) {
auto const &texture = Texture( Id );
if( true == texture.is_ready ) {
::glBindTexture( GL_TEXTURE_2D, texture.id );
#ifndef EU07_DEFERRED_TEXTURE_UPLOAD
::glBindTexture( GL_TEXTURE_2D, Id );
m_activetexture = 0;
#else
if( Texture( Id ).bind() == resource_state::good ) {
m_activetexture = Id;
return;
}
else {
// TODO: bind a special 'error' texture on failure
}
#endif
}
else {
::glBindTexture( GL_TEXTURE_2D, 0 );
m_activetexture = 0;
::glBindTexture( GL_TEXTURE_2D, 0 );
m_activetexture = 0;
}
// all done
return;
}
void
texture_manager::Free() {
for( auto const &texture : m_textures ) {
// usunięcie wszyskich tekstur (bez usuwania struktury)
if( ( texture.id > 0 )
&& ( texture.id != -1 ) ) {
::glDeleteTextures( 1, &texture.id );
}
}
}
// debug performance string
std::string
texture_manager::Info() const {
// TODO: cache this data and update only during resource sweep
std::size_t totaltexturecount{ m_textures.size() - 1 };
std::size_t totaltexturesize{ 0 };
#ifdef EU07_DEFERRED_TEXTURE_UPLOAD
std::size_t readytexturecount{ 0 };
std::size_t readytexturesize{ 0 };
#endif
for( auto const& texture : m_textures ) {
totaltexturesize += texture.size;
#ifdef EU07_DEFERRED_TEXTURE_UPLOAD
if( texture.is_ready ) {
++readytexturecount;
readytexturesize += texture.size;
}
#endif
}
return
"Textures: "
#ifdef EU07_DEFERRED_TEXTURE_UPLOAD
+ std::to_string( readytexturecount )
+ " ("
+ to_string( readytexturesize / 1024.0f, 2 ) + " mb)"
+ " in vram, ";
#endif
+ std::to_string( totaltexturecount )
+ " ("
+ to_string( totaltexturesize / 1024.0f, 2 ) + " mb)"
+ " total";
}
// checks whether specified texture is in the texture bank. returns texture id, or npos.
texture_manager::size_type
texture_manager::find_in_databank( std::string const &Texturename ) {
@@ -806,12 +926,3 @@ texture_manager::find_on_disk( std::string const &Texturename ) {
// no results either way, report failure
return "";
}
void
texture_manager::Free()
{
for( auto const &texture : m_textures ) {
// usunięcie wszyskich tekstur (bez usuwania struktury)
::glDeleteTextures( 1, &texture.id );
}
}