From 885c07d2c345fc18e57cb5f58e8b309f68281802 Mon Sep 17 00:00:00 2001 From: Relintai Date: Sun, 31 Dec 2023 02:10:01 +0100 Subject: [PATCH] Reworked Texture. --- sfw/render_core/texture.cpp | 341 ++++++------------ sfw/render_core/texture.h | 29 +- sfw/render_core/texture_material.h | 2 +- sfw/render_core/texture_material_2d.h | 2 +- .../transparent_texture_material.h | 2 +- 5 files changed, 121 insertions(+), 255 deletions(-) diff --git a/sfw/render_core/texture.cpp b/sfw/render_core/texture.cpp index 0ad54bb..0d83254 100644 --- a/sfw/render_core/texture.cpp +++ b/sfw/render_core/texture.cpp @@ -355,174 +355,11 @@ Ref RasterizerStorageGLES2::_get_gl_image_and_format(const Ref &p_ } */ -/* - -void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref &p_image, int p_layer) { - Texture *texture = texture_owner.getornull(p_texture); - - ERR_FAIL_COND(!texture); - if (texture->target == GL_TEXTURE_3D) { - // Target is set to a 3D texture or array texture, exit early to avoid spamming errors - return; - } - ERR_FAIL_COND(!texture->active); - ERR_FAIL_COND(texture->render_target); - ERR_FAIL_COND(texture->format != p_image->get_format()); - ERR_FAIL_COND(p_image.is_null()); - ERR_FAIL_COND(texture->type == RS::TEXTURE_TYPE_EXTERNAL); - - GLenum type; - GLenum format; - GLenum internal_format; - bool compressed = false; - - if (config.keep_original_textures && !(texture->flags & RS::TEXTURE_FLAG_USED_FOR_STREAMING)) { - texture->images.write[p_layer] = p_image; - } - - Image::Format real_format; - Ref img = _get_gl_image_and_format(p_image, p_image->get_format(), texture->flags, real_format, format, internal_format, type, compressed, texture->resize_to_po2); - - if (texture->resize_to_po2) { - if (p_image->is_compressed()) { - ERR_PRINT("Texture '" + texture->path + "' is required to be a power of 2 because it uses either mipmaps or repeat, so it was decompressed. This will hurt performance and memory usage."); - } - - if (img == p_image) { - img = img->duplicate(); - } - img->resize_to_po2(false, texture->flags & RS::TEXTURE_FLAG_FILTER ? Image::INTERPOLATE_BILINEAR : Image::INTERPOLATE_NEAREST); - } - - if (config.shrink_textures_x2 && (p_image->has_mipmaps() || !p_image->is_compressed()) && !(texture->flags & RS::TEXTURE_FLAG_USED_FOR_STREAMING)) { - texture->alloc_height = MAX(1, texture->alloc_height / 2); - texture->alloc_width = MAX(1, texture->alloc_width / 2); - - if (texture->alloc_width == img->get_width() / 2 && texture->alloc_height == img->get_height() / 2) { - img->shrink_x2(); - } else if (img->get_format() <= Image::FORMAT_RGBA8) { - img->resize(texture->alloc_width, texture->alloc_height, Image::INTERPOLATE_BILINEAR); - } - } - - GLenum blit_target = (texture->target == GL_TEXTURE_CUBE_MAP) ? _cube_side_enum[p_layer] : GL_TEXTURE_2D; - - texture->data_size = img->get_data().size(); - PoolVector::Read read = img->get_data().read(); - ERR_FAIL_COND(!read.ptr()); - - gl_wrapper.gl_active_texture(GL_TEXTURE0); - glBindTexture(texture->target, texture->tex_id); - - texture->ignore_mipmaps = compressed && !img->has_mipmaps(); - - if ((texture->flags & RS::TEXTURE_FLAG_MIPMAPS) && !texture->ignore_mipmaps) { - if (texture->flags & RS::TEXTURE_FLAG_FILTER) { - glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, config.use_fast_texture_filter ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR_MIPMAP_LINEAR); - } else { - glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, config.use_fast_texture_filter ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST_MIPMAP_LINEAR); - } - } else { - if (texture->flags & RS::TEXTURE_FLAG_FILTER) { - glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } else { - glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } - } - - if (texture->flags & RS::TEXTURE_FLAG_FILTER) { - glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear Filtering - - } else { - glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // raw Filtering - } - - if (((texture->flags & RS::TEXTURE_FLAG_REPEAT) || (texture->flags & RS::TEXTURE_FLAG_MIRRORED_REPEAT)) && texture->target != GL_TEXTURE_CUBE_MAP) { - if (texture->flags & RS::TEXTURE_FLAG_MIRRORED_REPEAT) { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); - } else { - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - } - } else { - //glTexParameterf( texture->target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE ); - glTexParameterf(texture->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } - - if (config.use_anisotropic_filter) { - if (texture->flags & RS::TEXTURE_FLAG_ANISOTROPIC_FILTER) { - glTexParameterf(texture->target, _GL_TEXTURE_MAX_ANISOTROPY_EXT, config.anisotropic_level); - } else { - glTexParameterf(texture->target, _GL_TEXTURE_MAX_ANISOTROPY_EXT, 1); - } - } - - int mipmaps = ((texture->flags & RS::TEXTURE_FLAG_MIPMAPS) && img->has_mipmaps()) ? img->get_mipmap_count() + 1 : 1; - - int w = img->get_width(); - int h = img->get_height(); - - int tsize = 0; - - for (int i = 0; i < mipmaps; i++) { - int size, ofs; - img->get_mipmap_offset_and_size(i, ofs, size); - - if (compressed) { - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - - int bw = w; - int bh = h; - - glCompressedTexImage2D(blit_target, i, internal_format, bw, bh, 0, size, &read[ofs]); - } else { - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - if (texture->flags & RS::TEXTURE_FLAG_USED_FOR_STREAMING) { - glTexSubImage2D(blit_target, i, 0, 0, w, h, format, type, &read[ofs]); - } else { - glTexImage2D(blit_target, i, internal_format, w, h, 0, format, type, &read[ofs]); - } - } - - tsize += size; - - w = MAX(1, w >> 1); - h = MAX(1, h >> 1); - } - - info.texture_mem -= texture->total_data_size; - texture->total_data_size = tsize; - info.texture_mem += texture->total_data_size; - - // printf("texture: %i x %i - size: %i - total: %i\n", texture->width, texture->height, tsize, info.texture_mem); - - texture->stored_cube_sides |= (1 << p_layer); - - if ((texture->flags & RS::TEXTURE_FLAG_MIPMAPS) && mipmaps == 1 && !texture->ignore_mipmaps && (texture->type != RS::TEXTURE_TYPE_CUBEMAP || texture->stored_cube_sides == (1 << 6) - 1)) { - //generate mipmaps if they were requested and the image does not contain them - glGenerateMipmap(texture->target); - } - - texture->mipmaps = mipmaps; -} - -*/ - -void Texture::texture_update(int flags) { +void Texture::texture_update() { if (!_image.is_valid()) { return; } - //if (t && !t->id) { - // glGenTextures(1, &t->id); - // return texture_update(t, w, h, n, pixels, flags); - //} - - //ASSERT(t && t->id); - //ASSERT(n <= 4); - //GLuint pixel_types[] = { GL_RED, GL_RED, GL_RG, GL_RGB, GL_RGBA, GL_R32F, GL_R32F, GL_RG32F, GL_RGB32F, GL_RGBA32F }; //GLenum pixel_storage = flags & TEXTURE_FLOAT ? GL_FLOAT : GL_UNSIGNED_BYTE; GLenum pixel_storage = GL_UNSIGNED_BYTE; @@ -531,10 +368,6 @@ void Texture::texture_update(int flags) { //GLuint texel_type = t->texel_type = pixel_types[n + 5 * !!(flags & TEXTURE_FLOAT)]; GLuint texel_type = GL_RGBA; - GLenum wrap = GL_CLAMP_TO_EDGE; - GLenum min_filter = GL_NEAREST, mag_filter = GL_NEAREST; - // GLfloat color = (flags&7)/7.f, border_color[4] = { color, color, color, 1.f }; - /* if (flags & TEXTURE_BGR) if (pixel_type == GL_RGB) @@ -571,99 +404,127 @@ void Texture::texture_update(int flags) { mag_filter = flags & TEXTURE_LINEAR ? GL_LINEAR : GL_NEAREST; */ - //GLenum texture_type = t->flags & TEXTURE_ARRAY ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D; // @fixme: test GL_TEXTURE_2D_ARRAY - GLenum texture_type = GL_TEXTURE_2D; // @fixme: test GL_TEXTURE_2D_ARRAY + _data_size = _image->get_data().size(); + Vector image_data = _image->get_data(); - //glPixelStorei( GL_UNPACK_ALIGNMENT, n < 4 ? 1 : 4 ); // for framebuffer reading - //glActiveTexture(GL_TEXTURE0 + (flags&7)); - glBindTexture(texture_type, texture); - //glTexImage2D(texture_type, 0, texel_type, w, h, 0, pixel_type, pixel_storage, pixels); - - glTexParameteri(texture_type, GL_TEXTURE_WRAP_S, wrap); - glTexParameteri(texture_type, GL_TEXTURE_WRAP_T, wrap); - glTexParameteri(texture_type, GL_TEXTURE_MIN_FILTER, min_filter); - glTexParameteri(texture_type, GL_TEXTURE_MAG_FILTER, mag_filter); - - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexImage2D(texture_type, 0, texel_type, _image_width, _image_height, 0, pixel_type, pixel_storage, _image_data.ptr()); - - // if( flags & TEXTURE_BORDER ) glTexParameterfv(texture_type, GL_TEXTURE_BORDER_COLOR, border_color); - /* - if (flags & TEXTURE_MIPMAPS) - glGenerateMipmap(texture_type); - - if (flags & TEXTURE_MIPMAPS) { - GLfloat max_aniso = 0; - // glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY, &max_aniso); - max_aniso = 4; - // glTexParameterf(texture_type, GL_TEXTURE_MAX_ANISOTROPY, max_aniso); - } - - */ - - // glBindTexture(texture_type, 0); // do not unbind. current code expects texture to be bound at function exit - /* - t->w = w; - t->h = h; - t->n = n; - t->flags = flags; - t->filename = t->filename ? t->filename : ""; - */ -} - -void Texture::apply_filter() { - if (!texture) { + if (image_data.size() == 0) { return; } - GLint params = GL_NEAREST; - - if (filter == TEXTURE_FILTER_LINEAR) { - params = GL_LINEAR; + if (!_texture) { + glGenTextures(1, &_texture); } - glBindTexture(GL_TEXTURE_2D, texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, params); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, params); + const uint8_t *read = image_data.ptr(); + ERR_FAIL_COND(!read); + + glActiveTexture(GL_TEXTURE0 + _texture_index); + + if ((_flags | TEXTURE_FLAG_MIP_MAPS)) { + if ((_flags | TEXTURE_FLAG_FILTER)) { + glTexParameteri(_texture, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + } else { + glTexParameteri(_texture, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + } + } else { + if ((_flags | TEXTURE_FLAG_FILTER)) { + glTexParameteri(_texture, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } else { + glTexParameteri(_texture, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + } + + if ((_flags | TEXTURE_FLAG_FILTER)) { + glTexParameteri(_texture, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear Filtering + } else { + glTexParameteri(_texture, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // raw Filtering + } + + if ((_flags & TEXTURE_FLAG_REPEAT) || (_flags & TEXTURE_FLAG_MIRRORED_REPEAT)) { + if (_flags & TEXTURE_FLAG_MIRRORED_REPEAT) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); + } else { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + } + } else { + glTexParameterf(_texture, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(_texture, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + + GLenum texture_type = GL_TEXTURE_2D; + + glBindTexture(texture_type, _texture); + + int mipmaps = ((_flags | TEXTURE_FLAG_MIP_MAPS) && _image->has_mipmaps()) ? _image->get_mipmap_count() + 1 : 1; + + _texture_width = _image->get_width(); + _texture_height = _image->get_height(); + + int w = _texture_width; + int h = _texture_height; + + int tsize = 0; + + for (int i = 0; i < mipmaps; i++) { + int size; + int ofs; + _image->get_mipmap_offset_and_size(i, ofs, size); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexImage2D(texture_type, i, texel_type, w, h, 0, pixel_type, pixel_storage, &read[ofs]); + + tsize += size; + + w = MAX(1, w >> 1); + h = MAX(1, h >> 1); + } + + if ((_flags | TEXTURE_FLAG_MIP_MAPS) && mipmaps == 1) { + //generate mipmaps if they were requested and the image does not contain them + glGenerateMipmap(texture_type); + } + + _mipmaps = mipmaps; + + glBindTexture(texture_type, 0); } void Texture::set_image(const Ref &img) { + if (_image == img) { + return; + } + _image = img; - if (texture) { - glDeleteTextures(1, &texture); - } + _texture_width = 0; + _texture_height = 0; if (!_image.is_valid()) { + if (_texture) { + glDeleteTextures(1, &_texture); + _texture = 0; + } + return; } - _image_data = _image->get_data(); - _image_format = _image->get_format(); - _image_width = _image->get_width(); - _image_height = _image->get_height(); - _image_mip_maps = _image->has_mipmaps(); - - if (_image_data.size() == 0) { - return; - } - - glGenTextures(1, &texture); - - texture_update(0); + texture_update(); } Texture::Texture() { - filter = TEXTURE_FILTER_NEAREST; - texture = 0; - _image_width = 0; - _image_height = 0; - _image_format = Image::FORMAT_RGBA8; - _image_mip_maps = false; + _texture = 0; + _texture_width = 0; + _texture_height = 0; + _mipmaps = 1; + _data_size = 0; + _texture_index = 0; + _flags = 0; } Texture::~Texture() { - if (texture) { - glDeleteTextures(1, &texture); + if (_texture) { + glDeleteTextures(1, &_texture); } } diff --git a/sfw/render_core/texture.h b/sfw/render_core/texture.h index 98fb2da..a015182 100644 --- a/sfw/render_core/texture.h +++ b/sfw/render_core/texture.h @@ -6,16 +6,18 @@ class Texture { public: - enum TextureFilter { - TEXTURE_FILTER_NEAREST = 0, - TEXTURE_FILTER_LINEAR, + enum TextureFlags { + TEXTURE_FLAG_FILTER = 1 << 0, + TEXTURE_FLAG_REPEAT = 1 << 1, + TEXTURE_FLAG_MIRRORED_REPEAT = 1 << 2, + TEXTURE_FLAG_MIP_MAPS = 1 << 3, }; - TextureFilter filter; - GLuint texture; + _FORCE_INLINE_ GLuint get_gl_texture() { + return _texture; + } - void apply_filter(); - void texture_update(int flags); + void texture_update(); void set_image(const Ref &img); @@ -23,12 +25,15 @@ public: virtual ~Texture(); protected: - int _image_width; - int _image_height; + int _texture_width; + int _texture_height; Ref _image; - Vector _image_data; - Image::Format _image_format; - bool _image_mip_maps; + + int _flags; + int _texture_index; + int _data_size; + int _mipmaps; + GLuint _texture; }; #endif // TEXTURE_H diff --git a/sfw/render_core/texture_material.h b/sfw/render_core/texture_material.h index c1b11e1..f569053 100644 --- a/sfw/render_core/texture_material.h +++ b/sfw/render_core/texture_material.h @@ -19,7 +19,7 @@ public: if (texture) { glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, texture->texture); + glBindTexture(GL_TEXTURE_2D, texture->get_gl_texture()); glUniform1i(texture_location, 0); } } diff --git a/sfw/render_core/texture_material_2d.h b/sfw/render_core/texture_material_2d.h index 0bd2a9e..f06cc3b 100644 --- a/sfw/render_core/texture_material_2d.h +++ b/sfw/render_core/texture_material_2d.h @@ -18,7 +18,7 @@ public: if (texture) { glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, texture->texture); + glBindTexture(GL_TEXTURE_2D, texture->get_gl_texture()); glUniform1i(texture_location, 0); } } diff --git a/sfw/render_core/transparent_texture_material.h b/sfw/render_core/transparent_texture_material.h index e25a9f9..d4759e5 100644 --- a/sfw/render_core/transparent_texture_material.h +++ b/sfw/render_core/transparent_texture_material.h @@ -21,7 +21,7 @@ public: if (texture) { glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, texture->texture); + glBindTexture(GL_TEXTURE_2D, texture->get_gl_texture()); glUniform1i(texture_location, 0); } }