From 1529d37d585ec38aee475519e444d2718a81fda5 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Thu, 13 Apr 2023 02:10:44 +0100 Subject: Add TextureAtlas class as an extension of Texture --- gfx/models/texture.cpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'gfx/models/texture.cpp') diff --git a/gfx/models/texture.cpp b/gfx/models/texture.cpp index efc76e1..a500fed 100644 --- a/gfx/models/texture.cpp +++ b/gfx/models/texture.cpp @@ -85,3 +85,35 @@ Texture::saveNormal(const glTexture & texture, const glm::ivec2 & size, const ch { save(texture, GL_BGR, GL_BYTE, size, 3, path, 2); } + +TextureAtlas::TextureAtlas(GLsizei width, GLsizei height, GLuint count) : Texture(width, height, nullptr, {}) +{ + glBindTexture(GL_TEXTURE_RECTANGLE, m_atlas); + + glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA16UI, 2, static_cast(count), 0, GL_RGBA_INTEGER, + GL_UNSIGNED_BYTE, nullptr); +} + +void +TextureAtlas::bind(GLenum unit) const +{ + Texture::bind(unit); + glActiveTexture(unit + 1); + glBindTexture(GL_TEXTURE_RECTANGLE, m_atlas); +} + +GLuint +TextureAtlas::add(glm::ivec2 position, glm::ivec2 size, void * data, TextureOptions) +{ + glTextureSubImage2D(m_texture, 0, position.x, position.y, size.x, size.y, GL_RGBA, GL_UNSIGNED_BYTE, data); + struct Material { + glm::vec<2, uint16_t> position, size, unused1 {}, unused2 {}; + } material {position, size}; + glTextureSubImage2D(m_atlas, 0, 0, static_cast(used), 2, 1, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, &material); + return ++used; +} -- cgit v1.2.3 From 0638aaaf2a60efae95a1b404d7eee29e894047bc Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 14 Apr 2023 01:54:19 +0100 Subject: No need to pass size around, we can get it back from the texture --- gfx/models/texture.cpp | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'gfx/models/texture.cpp') diff --git a/gfx/models/texture.cpp b/gfx/models/texture.cpp index a500fed..ab256d5 100644 --- a/gfx/models/texture.cpp +++ b/gfx/models/texture.cpp @@ -44,12 +44,22 @@ Texture::bind(GLenum unit) const glBindTexture(type, m_texture); } +glm::ivec2 +Texture::getSize(const glTexture & texture) +{ + glm::ivec2 size; + glGetTextureLevelParameteriv(texture, 0, GL_TEXTURE_WIDTH, &size.x); + glGetTextureLevelParameteriv(texture, 0, GL_TEXTURE_HEIGHT, &size.y); + return size; +} + void -Texture::save(const glTexture & texture, GLenum format, GLenum type, const glm::ivec2 & size, unsigned short channels, - const char * path, short tgaFormat) +Texture::save(const glTexture & texture, GLenum format, GLenum type, unsigned short channels, const char * path, + short tgaFormat) { using TGAHead = std::array; + const auto size = getSize(texture); const size_t dataSize = (static_cast(size.x * size.y * channels)); const size_t fileSize = dataSize + sizeof(TGAHead); @@ -63,27 +73,27 @@ Texture::save(const glTexture & texture, GLenum format, GLenum type, const glm:: } void -Texture::save(const glm::ivec2 & size, const char * path) const +Texture::save(const char * path) const { - save(m_texture, GL_BGR, GL_UNSIGNED_BYTE, size, 3, path, 2); + save(m_texture, GL_BGR, GL_UNSIGNED_BYTE, 3, path, 2); } void -Texture::save(const glTexture & texture, const glm::ivec2 & size, const char * path) +Texture::save(const glTexture & texture, const char * path) { - save(texture, GL_BGR, GL_UNSIGNED_BYTE, size, 3, path, 2); + save(texture, GL_BGR, GL_UNSIGNED_BYTE, 3, path, 2); } void -Texture::saveDepth(const glTexture & texture, const glm::ivec2 & size, const char * path) +Texture::saveDepth(const glTexture & texture, const char * path) { - save(texture, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, size, 1, path, 3); + save(texture, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 1, path, 3); } void -Texture::saveNormal(const glTexture & texture, const glm::ivec2 & size, const char * path) +Texture::saveNormal(const glTexture & texture, const char * path) { - save(texture, GL_BGR, GL_BYTE, size, 3, path, 2); + save(texture, GL_BGR, GL_BYTE, 3, path, 2); } TextureAtlas::TextureAtlas(GLsizei width, GLsizei height, GLuint count) : Texture(width, height, nullptr, {}) -- cgit v1.2.3 From c44e7537d027cba66abe564b247549040426ebfe Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 14 Apr 2023 02:56:33 +0100 Subject: Externalise a neater definition of TGAHead --- gfx/models/texture.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'gfx/models/texture.cpp') diff --git a/gfx/models/texture.cpp b/gfx/models/texture.cpp index ab256d5..3b27e77 100644 --- a/gfx/models/texture.cpp +++ b/gfx/models/texture.cpp @@ -1,5 +1,6 @@ #include "texture.h" #include "glArrays.h" +#include "tga.h" #include #include #include @@ -54,11 +55,9 @@ Texture::getSize(const glTexture & texture) } void -Texture::save(const glTexture & texture, GLenum format, GLenum type, unsigned short channels, const char * path, - short tgaFormat) +Texture::save( + const glTexture & texture, GLenum format, GLenum type, uint8_t channels, const char * path, uint8_t tgaFormat) { - using TGAHead = std::array; - const auto size = getSize(texture); const size_t dataSize = (static_cast(size.x * size.y * channels)); const size_t fileSize = dataSize + sizeof(TGAHead); @@ -66,8 +65,11 @@ Texture::save(const glTexture & texture, GLenum format, GLenum type, unsigned sh filesystem::fh out {path, O_RDWR | O_CREAT, 0660}; out.truncate(fileSize); auto tga = out.mmap(fileSize, 0, PROT_WRITE, MAP_SHARED); - *tga.get() = {0, tgaFormat, 0, 0, 0, 0, static_cast(size.x), static_cast(size.y), - static_cast(8 * channels)}; + *tga.get() = { + .format = tgaFormat, + .size = size, + .pixelDepth = static_cast(8 * channels), + }; glGetTextureImage(texture, 0, format, type, static_cast(dataSize), tga.get() + 1); tga.msync(MS_ASYNC); } -- cgit v1.2.3 From 59733c3c3de7aa6dee5fde8e2a60b80b4c706583 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 14 Apr 2023 15:21:36 +0100 Subject: Set GL_PACK_ALIGNMENT before saving texture to fit buffer correctly --- gfx/models/texture.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'gfx/models/texture.cpp') diff --git a/gfx/models/texture.cpp b/gfx/models/texture.cpp index 3b27e77..6319eb8 100644 --- a/gfx/models/texture.cpp +++ b/gfx/models/texture.cpp @@ -70,6 +70,7 @@ Texture::save( .size = size, .pixelDepth = static_cast(8 * channels), }; + glPixelStorei(GL_PACK_ALIGNMENT, 1); glGetTextureImage(texture, 0, format, type, static_cast(dataSize), tga.get() + 1); tga.msync(MS_ASYNC); } -- cgit v1.2.3 From b4ede2fd89d0effb44ebae15862427de9a147476 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 14 Apr 2023 16:34:56 +0100 Subject: Define our own enum for texture mapmode --- gfx/models/texture.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'gfx/models/texture.cpp') diff --git a/gfx/models/texture.cpp b/gfx/models/texture.cpp index 6319eb8..e29fd6c 100644 --- a/gfx/models/texture.cpp +++ b/gfx/models/texture.cpp @@ -13,6 +13,21 @@ Cache Texture::cachedTexture; +GLint +TextureOptions::glMapMode(TextureOptions::MapMode mm) +{ + switch (mm) { + case MapMode::Repeat: + return GL_REPEAT; + case MapMode::Clamp: + return GL_CLAMP_TO_EDGE; + case MapMode::Mirror: + return GL_MIRRORED_REPEAT; + default: + throw std::domain_error("Invalid MapMode value"); + } +} + Texture::Texture(const std::filesystem::path & fileName, TextureOptions to) : Texture {Image {Resource::mapPath(fileName).c_str(), STBI_rgb_alpha}, to} { @@ -30,8 +45,8 @@ Texture::Texture(GLsizei width, GLsizei height, const void * data, TextureOption glBindTexture(type, m_texture); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexParameteri(type, GL_TEXTURE_WRAP_S, to.wrap); - glTexParameteri(type, GL_TEXTURE_WRAP_T, to.wrap); + glTexParameteri(type, GL_TEXTURE_WRAP_S, TextureOptions::glMapMode(to.wrapU)); + glTexParameteri(type, GL_TEXTURE_WRAP_T, TextureOptions::glMapMode(to.wrapV)); glTexParameteri(type, GL_TEXTURE_MIN_FILTER, to.minFilter); glTexParameteri(type, GL_TEXTURE_MAG_FILTER, to.magFilter); -- cgit v1.2.3 From be9a796e68a25f7567b7c16e00d9b42f5e0d9528 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 14 Apr 2023 16:39:27 +0100 Subject: Write applicable Texture Options into texture atlas texture data --- gfx/models/texture.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'gfx/models/texture.cpp') diff --git a/gfx/models/texture.cpp b/gfx/models/texture.cpp index e29fd6c..e014f80 100644 --- a/gfx/models/texture.cpp +++ b/gfx/models/texture.cpp @@ -136,12 +136,15 @@ TextureAtlas::bind(GLenum unit) const } GLuint -TextureAtlas::add(glm::ivec2 position, glm::ivec2 size, void * data, TextureOptions) +TextureAtlas::add(glm::ivec2 position, glm::ivec2 size, void * data, TextureOptions to) { glTextureSubImage2D(m_texture, 0, position.x, position.y, size.x, size.y, GL_RGBA, GL_UNSIGNED_BYTE, data); struct Material { - glm::vec<2, uint16_t> position, size, unused1 {}, unused2 {}; - } material {position, size}; + glm::vec<2, uint16_t> position, size; + TextureOptions::MapMode wrapU; + TextureOptions::MapMode wrapV; + } material {position, size, to.wrapU, to.wrapV}; + static_assert(sizeof(Material) <= 32); glTextureSubImage2D(m_atlas, 0, 0, static_cast(used), 2, 1, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, &material); return ++used; } -- cgit v1.2.3