mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-18 20:29:17 +02:00
merge
This commit is contained in:
253
Texture.cpp
253
Texture.cpp
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user