Refactoring in GLTexture
This commit is contained in:
parent
84d61e28fd
commit
749bb2bfed
6 changed files with 39 additions and 162 deletions
|
@ -418,7 +418,7 @@ void Bed3D::render_prusa(GLCanvas3D* canvas, const std::string &key, bool bottom
|
||||||
// generate a temporary lower resolution texture to show while no main texture levels have been compressed
|
// generate a temporary lower resolution texture to show while no main texture levels have been compressed
|
||||||
if ((m_temp_texture.get_id() == 0) || (m_temp_texture.get_source() != filename))
|
if ((m_temp_texture.get_id() == 0) || (m_temp_texture.get_source() != filename))
|
||||||
{
|
{
|
||||||
if (!m_temp_texture.load_from_file(filename, false, false, false, max_tex_size))
|
if (!m_temp_texture.load_from_file(filename, false, GLTexture::None, false))
|
||||||
{
|
{
|
||||||
render_custom();
|
render_custom();
|
||||||
return;
|
return;
|
||||||
|
@ -426,7 +426,7 @@ void Bed3D::render_prusa(GLCanvas3D* canvas, const std::string &key, bool bottom
|
||||||
}
|
}
|
||||||
|
|
||||||
// starts generating the main texture, compression will run asynchronously
|
// starts generating the main texture, compression will run asynchronously
|
||||||
if (!m_texture.load_from_file(filename, true, true, true, max_tex_size))
|
if (!m_texture.load_from_file(filename, true, GLTexture::MultiThreaded, true))
|
||||||
{
|
{
|
||||||
render_custom();
|
render_custom();
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -302,7 +302,7 @@ void GLCanvas3D::LayersEditing::_render_tooltip_texture(const GLCanvas3D& canvas
|
||||||
if (m_tooltip_texture.get_id() == 0)
|
if (m_tooltip_texture.get_id() == 0)
|
||||||
{
|
{
|
||||||
std::string filename = resources_dir() + "/icons/variable_layer_height_tooltip.png";
|
std::string filename = resources_dir() + "/icons/variable_layer_height_tooltip.png";
|
||||||
if (!m_tooltip_texture.load_from_file(filename, false, true))
|
if (!m_tooltip_texture.load_from_file(filename, false, GLTexture::SingleThreaded, false))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,7 +334,7 @@ void GLCanvas3D::LayersEditing::_render_reset_texture(const Rect& reset_rect) co
|
||||||
if (m_reset_texture.get_id() == 0)
|
if (m_reset_texture.get_id() == 0)
|
||||||
{
|
{
|
||||||
std::string filename = resources_dir() + "/icons/variable_layer_height_reset.png";
|
std::string filename = resources_dir() + "/icons/variable_layer_height_reset.png";
|
||||||
if (!m_reset_texture.load_from_file(filename, false, true))
|
if (!m_reset_texture.load_from_file(filename, false, GLTexture::SingleThreaded, false))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -134,7 +134,7 @@ GLTexture::~GLTexture()
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLTexture::load_from_file(const std::string& filename, bool use_mipmaps, bool compress)
|
bool GLTexture::load_from_file(const std::string& filename, bool use_mipmaps, ECompressionType compression_type, bool apply_anisotropy)
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
|
@ -142,20 +142,7 @@ bool GLTexture::load_from_file(const std::string& filename, bool use_mipmaps, bo
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (boost::algorithm::iends_with(filename, ".png"))
|
if (boost::algorithm::iends_with(filename, ".png"))
|
||||||
return load_from_png(filename, use_mipmaps, compress);
|
return load_from_png(filename, use_mipmaps, compression_type, apply_anisotropy);
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GLTexture::load_from_file(const std::string& filename, bool use_mipmaps, bool compress, bool apply_anisotropy, unsigned int max_size_px)
|
|
||||||
{
|
|
||||||
reset();
|
|
||||||
|
|
||||||
if (!boost::filesystem::exists(filename))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (boost::algorithm::iends_with(filename, ".png"))
|
|
||||||
return load_from_png(filename, use_mipmaps, compress, apply_anisotropy, max_size_px);
|
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -367,120 +354,9 @@ void GLTexture::render_sub_texture(unsigned int tex_id, float left, float right,
|
||||||
glsafe(::glDisable(GL_BLEND));
|
glsafe(::glDisable(GL_BLEND));
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int GLTexture::generate_mipmaps(wxImage& image, bool compress)
|
bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps, ECompressionType compression_type, bool apply_anisotropy)
|
||||||
{
|
{
|
||||||
int w = image.GetWidth();
|
bool compression_enabled = (compression_type != None) && GLEW_EXT_texture_compression_s3tc;
|
||||||
int h = image.GetHeight();
|
|
||||||
GLint level = 0;
|
|
||||||
std::vector<unsigned char> data(w * h * 4, 0);
|
|
||||||
|
|
||||||
while ((w > 1) || (h > 1))
|
|
||||||
{
|
|
||||||
++level;
|
|
||||||
|
|
||||||
w = std::max(w / 2, 1);
|
|
||||||
h = std::max(h / 2, 1);
|
|
||||||
|
|
||||||
int n_pixels = w * h;
|
|
||||||
|
|
||||||
image = image.ResampleBicubic(w, h);
|
|
||||||
|
|
||||||
unsigned char* img_rgb = image.GetData();
|
|
||||||
unsigned char* img_alpha = image.GetAlpha();
|
|
||||||
|
|
||||||
data.resize(n_pixels * 4);
|
|
||||||
for (int i = 0; i < n_pixels; ++i)
|
|
||||||
{
|
|
||||||
int data_id = i * 4;
|
|
||||||
int img_id = i * 3;
|
|
||||||
data[data_id + 0] = img_rgb[img_id + 0];
|
|
||||||
data[data_id + 1] = img_rgb[img_id + 1];
|
|
||||||
data[data_id + 2] = img_rgb[img_id + 2];
|
|
||||||
data[data_id + 3] = (img_alpha != nullptr) ? img_alpha[i] : 255;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (compress && GLEW_EXT_texture_compression_s3tc)
|
|
||||||
glsafe(::glTexImage2D(GL_TEXTURE_2D, level, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, (GLsizei)w, (GLsizei)h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data()));
|
|
||||||
else
|
|
||||||
glsafe(::glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, (GLsizei)w, (GLsizei)h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return (unsigned int)level;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps, bool compress)
|
|
||||||
{
|
|
||||||
// Load a PNG with an alpha channel.
|
|
||||||
wxImage image;
|
|
||||||
if (!image.LoadFile(wxString::FromUTF8(filename.c_str()), wxBITMAP_TYPE_PNG))
|
|
||||||
{
|
|
||||||
reset();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_width = image.GetWidth();
|
|
||||||
m_height = image.GetHeight();
|
|
||||||
int n_pixels = m_width * m_height;
|
|
||||||
|
|
||||||
if (n_pixels <= 0)
|
|
||||||
{
|
|
||||||
reset();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get RGB & alpha raw data from wxImage, pack them into an array.
|
|
||||||
unsigned char* img_rgb = image.GetData();
|
|
||||||
if (img_rgb == nullptr)
|
|
||||||
{
|
|
||||||
reset();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char* img_alpha = image.GetAlpha();
|
|
||||||
|
|
||||||
std::vector<unsigned char> data(n_pixels * 4, 0);
|
|
||||||
for (int i = 0; i < n_pixels; ++i)
|
|
||||||
{
|
|
||||||
int data_id = i * 4;
|
|
||||||
int img_id = i * 3;
|
|
||||||
data[data_id + 0] = img_rgb[img_id + 0];
|
|
||||||
data[data_id + 1] = img_rgb[img_id + 1];
|
|
||||||
data[data_id + 2] = img_rgb[img_id + 2];
|
|
||||||
data[data_id + 3] = (img_alpha != nullptr) ? img_alpha[i] : 255;
|
|
||||||
}
|
|
||||||
|
|
||||||
// sends data to gpu
|
|
||||||
glsafe(::glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
|
|
||||||
glsafe(::glGenTextures(1, &m_id));
|
|
||||||
glsafe(::glBindTexture(GL_TEXTURE_2D, m_id));
|
|
||||||
if (compress && GLEW_EXT_texture_compression_s3tc)
|
|
||||||
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data()));
|
|
||||||
else
|
|
||||||
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data()));
|
|
||||||
if (use_mipmaps)
|
|
||||||
{
|
|
||||||
// we manually generate mipmaps because glGenerateMipmap() function is not reliable on all graphics cards
|
|
||||||
unsigned int levels_count = generate_mipmaps(image, compress);
|
|
||||||
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, levels_count));
|
|
||||||
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
|
|
||||||
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0));
|
|
||||||
}
|
|
||||||
glsafe(::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
|
|
||||||
|
|
||||||
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
|
|
||||||
|
|
||||||
m_source = filename;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps, bool compress, bool apply_anisotropy, unsigned int max_size_px)
|
|
||||||
{
|
|
||||||
bool compression_enabled = compress && GLEW_EXT_texture_compression_s3tc;
|
|
||||||
|
|
||||||
// Load a PNG with an alpha channel.
|
// Load a PNG with an alpha channel.
|
||||||
wxImage image;
|
wxImage image;
|
||||||
|
@ -493,18 +369,9 @@ bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps, boo
|
||||||
m_width = image.GetWidth();
|
m_width = image.GetWidth();
|
||||||
m_height = image.GetHeight();
|
m_height = image.GetHeight();
|
||||||
|
|
||||||
unsigned int max_size = (unsigned int)std::max(m_width, m_height);
|
|
||||||
bool requires_rescale = false;
|
bool requires_rescale = false;
|
||||||
if (max_size_px < max_size)
|
|
||||||
{
|
|
||||||
float scale = (float)max_size_px / (float)max_size;
|
|
||||||
|
|
||||||
m_width = (int)(scale * (float)m_width);
|
if (compression_enabled && (compression_type == MultiThreaded))
|
||||||
m_height = (int)(scale * (float)m_height);
|
|
||||||
requires_rescale = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (compression_enabled)
|
|
||||||
{
|
{
|
||||||
// the stb_dxt compression library seems to like only texture sizes which are a multiple of 4
|
// the stb_dxt compression library seems to like only texture sizes which are a multiple of 4
|
||||||
int width_rem = m_width % 4;
|
int width_rem = m_width % 4;
|
||||||
|
@ -567,12 +434,17 @@ bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps, boo
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compression_enabled)
|
if (compression_enabled)
|
||||||
|
{
|
||||||
|
if (compression_type == SingleThreaded)
|
||||||
|
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data()));
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// initializes the texture on GPU
|
// initializes the texture on GPU
|
||||||
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
|
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
|
||||||
// and send the uncompressed data to the compressor
|
// and send the uncompressed data to the compressor
|
||||||
m_compressor.add_level((unsigned int)m_width, (unsigned int)m_height, data);
|
m_compressor.add_level((unsigned int)m_width, (unsigned int)m_height, data);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data()));
|
glsafe(::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data()));
|
||||||
|
|
||||||
|
@ -609,12 +481,17 @@ bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps, boo
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compression_enabled)
|
if (compression_enabled)
|
||||||
|
{
|
||||||
|
if (compression_type == SingleThreaded)
|
||||||
|
glsafe(::glTexImage2D(GL_TEXTURE_2D, level, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, (GLsizei)m_width, (GLsizei)m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data()));
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// initializes the texture on GPU
|
// initializes the texture on GPU
|
||||||
glsafe(::glTexImage2D(GL_TEXTURE_2D, level, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, (GLsizei)lod_w, (GLsizei)lod_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
|
glsafe(::glTexImage2D(GL_TEXTURE_2D, level, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, (GLsizei)lod_w, (GLsizei)lod_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0));
|
||||||
// and send the uncompressed data to the compressor
|
// and send the uncompressed data to the compressor
|
||||||
m_compressor.add_level((unsigned int)lod_w, (unsigned int)lod_h, data);
|
m_compressor.add_level((unsigned int)lod_w, (unsigned int)lod_h, data);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
glsafe(::glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, (GLsizei)lod_w, (GLsizei)lod_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data()));
|
glsafe(::glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, (GLsizei)lod_w, (GLsizei)lod_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)data.data()));
|
||||||
}
|
}
|
||||||
|
@ -637,7 +514,7 @@ bool GLTexture::load_from_png(const std::string& filename, bool use_mipmaps, boo
|
||||||
|
|
||||||
m_source = filename;
|
m_source = filename;
|
||||||
|
|
||||||
if (compression_enabled)
|
if (compression_enabled && (compression_type == MultiThreaded))
|
||||||
// start asynchronous compression
|
// start asynchronous compression
|
||||||
m_compressor.start_compressing();
|
m_compressor.start_compressing();
|
||||||
|
|
||||||
|
@ -651,7 +528,6 @@ bool GLTexture::load_from_svg(const std::string& filename, bool use_mipmaps, boo
|
||||||
NSVGimage* image = nsvgParseFromFile(filename.c_str(), "px", 96.0f);
|
NSVGimage* image = nsvgParseFromFile(filename.c_str(), "px", 96.0f);
|
||||||
if (image == nullptr)
|
if (image == nullptr)
|
||||||
{
|
{
|
||||||
// printf("Could not open SVG image.\n");
|
|
||||||
reset();
|
reset();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -686,7 +562,6 @@ bool GLTexture::load_from_svg(const std::string& filename, bool use_mipmaps, boo
|
||||||
NSVGrasterizer* rast = nsvgCreateRasterizer();
|
NSVGrasterizer* rast = nsvgCreateRasterizer();
|
||||||
if (rast == nullptr)
|
if (rast == nullptr)
|
||||||
{
|
{
|
||||||
// printf("Could not init rasterizer.\n");
|
|
||||||
nsvgDelete(image);
|
nsvgDelete(image);
|
||||||
reset();
|
reset();
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -48,6 +48,13 @@ namespace GUI {
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
enum ECompressionType : unsigned char
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
SingleThreaded,
|
||||||
|
MultiThreaded
|
||||||
|
};
|
||||||
|
|
||||||
struct UV
|
struct UV
|
||||||
{
|
{
|
||||||
float u;
|
float u;
|
||||||
|
@ -75,8 +82,7 @@ namespace GUI {
|
||||||
GLTexture();
|
GLTexture();
|
||||||
virtual ~GLTexture();
|
virtual ~GLTexture();
|
||||||
|
|
||||||
bool load_from_file(const std::string& filename, bool use_mipmaps, bool compress);
|
bool load_from_file(const std::string& filename, bool use_mipmaps, ECompressionType compression_type, bool apply_anisotropy);
|
||||||
bool load_from_file(const std::string& filename, bool use_mipmaps, bool compress, bool apply_anisotropy, unsigned int max_size_px);
|
|
||||||
bool load_from_svg_file(const std::string& filename, bool use_mipmaps, bool compress, bool apply_anisotropy, unsigned int max_size_px);
|
bool load_from_svg_file(const std::string& filename, bool use_mipmaps, bool compress, bool apply_anisotropy, unsigned int max_size_px);
|
||||||
// meanings of states: (std::pair<int, bool>)
|
// meanings of states: (std::pair<int, bool>)
|
||||||
// first field (int):
|
// first field (int):
|
||||||
|
@ -102,12 +108,8 @@ namespace GUI {
|
||||||
static void render_texture(unsigned int tex_id, float left, float right, float bottom, float top);
|
static void render_texture(unsigned int tex_id, float left, float right, float bottom, float top);
|
||||||
static void render_sub_texture(unsigned int tex_id, float left, float right, float bottom, float top, const Quad_UVs& uvs);
|
static void render_sub_texture(unsigned int tex_id, float left, float right, float bottom, float top, const Quad_UVs& uvs);
|
||||||
|
|
||||||
protected:
|
|
||||||
unsigned int generate_mipmaps(wxImage& image, bool compress);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool load_from_png(const std::string& filename, bool use_mipmaps, bool compress);
|
bool load_from_png(const std::string& filename, bool use_mipmaps, ECompressionType compression_type, bool apply_anisotropy);
|
||||||
bool load_from_png(const std::string& filename, bool use_mipmaps, bool compress, bool apply_anisotropy, unsigned int max_size_px);
|
|
||||||
bool load_from_svg(const std::string& filename, bool use_mipmaps, bool compress, bool apply_anisotropy, unsigned int max_size_px);
|
bool load_from_svg(const std::string& filename, bool use_mipmaps, bool compress, bool apply_anisotropy, unsigned int max_size_px);
|
||||||
|
|
||||||
friend class Compressor;
|
friend class Compressor;
|
||||||
|
|
|
@ -172,7 +172,7 @@ bool GLToolbar::init(const BackgroundTexture::Metadata& background_texture)
|
||||||
bool res = false;
|
bool res = false;
|
||||||
|
|
||||||
if (!background_texture.filename.empty())
|
if (!background_texture.filename.empty())
|
||||||
res = m_background_texture.texture.load_from_file(path + background_texture.filename, false, true);
|
res = m_background_texture.texture.load_from_file(path + background_texture.filename, false, GLTexture::SingleThreaded, false);
|
||||||
|
|
||||||
if (res)
|
if (res)
|
||||||
m_background_texture.metadata = background_texture;
|
m_background_texture.metadata = background_texture;
|
||||||
|
|
|
@ -43,7 +43,7 @@ bool GLGizmosManager::init()
|
||||||
|
|
||||||
if (!m_background_texture.metadata.filename.empty())
|
if (!m_background_texture.metadata.filename.empty())
|
||||||
{
|
{
|
||||||
if (!m_background_texture.texture.load_from_file(resources_dir() + "/icons/" + m_background_texture.metadata.filename, false, true))
|
if (!m_background_texture.texture.load_from_file(resources_dir() + "/icons/" + m_background_texture.metadata.filename, false, GLTexture::SingleThreaded, false))
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Reference in a new issue