mirror of
https://github.com/Relintai/sfw.git
synced 2024-11-08 07:52:09 +01:00
Reworked Texture.
This commit is contained in:
parent
fe18833bc6
commit
885c07d2c3
@ -355,174 +355,11 @@ Ref<Image> RasterizerStorageGLES2::_get_gl_image_and_format(const Ref<Image> &p_
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref<Image> &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<Image> 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<uint8_t>::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<uint8_t> 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<Image> &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);
|
||||
}
|
||||
}
|
||||
|
@ -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<Image> &img);
|
||||
|
||||
@ -23,12 +25,15 @@ public:
|
||||
virtual ~Texture();
|
||||
|
||||
protected:
|
||||
int _image_width;
|
||||
int _image_height;
|
||||
int _texture_width;
|
||||
int _texture_height;
|
||||
Ref<Image> _image;
|
||||
Vector<uint8_t> _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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user