Creating a texture atlas from multiple small textures.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 1m57s

This commit is contained in:
2025-01-10 20:48:13 -05:00
parent a0cc8524d9
commit bd918aa351
4 changed files with 40 additions and 5 deletions

View File

@@ -49,7 +49,7 @@ public:
/// Copy one Render Target onto another. Will break if they're not the same size.
// TODO support different sizes. If the destination is too small fix it for them but log a warning.
static void Blit(const RenderTarget& source, RenderTarget* destination);
static void Blit(const RenderTarget& source, RenderTarget* destination, const Vector2i& position = {0, 0});
/// Plots a single pixel onto a Render Target.
/// @param color The color to render.
@@ -57,6 +57,12 @@ public:
/// @param destination The destination RenderTarget.
static void Blit(const Color4& color, const Vector2i& position, RenderTarget* destination);
/// Blit an input texture onto this render target at the given position.
/// @param source Source texture.
/// @param destination Render Target to draw on.
/// @param position Where in the destination to draw.
static void Blit(const Texture* source, RenderTarget* destination, const Vector2i& position = {0, 0});
/// @returns Whether or not this Render Target created it's Texture.
[[nodiscard]] bool OwnsTexture() const;
public:
@@ -113,4 +119,5 @@ public:
/** @note If this Render Target was made with a Texture that already existed
* the Texture will not be deleted. */
~RenderTarget();
};

View File

@@ -39,6 +39,8 @@ namespace JGL {
/// Load a texture from a file,
explicit Texture(const std::string& file, TextureFilteringMode filtering_mode = TextureFilteringMode::BILINEAR, TextureWrappingMode wrapping_mode = TextureWrappingMode::CLAMP_TO_EDGE, const TextureFlag& flags = TextureFlag::INVERT_Y);
Texture(Image* software_texture, const Vector2& size, const TextureFormat& format, TextureFilteringMode filtering_mode, TextureWrappingMode wrapping_mode);
// Texture atlas.
Texture(const Texture* textures, const size_t& texture_count);
/* Initialize a texture filled with trash data
this is primarily for the RenderTarget */
explicit Texture(const Vector2& size);

View File

@@ -308,9 +308,9 @@ void JGL::RenderTarget::MSAABlit() const {
}
}
void JGL::RenderTarget::Blit(const JGL::RenderTarget& source, JGL::RenderTarget* destination) {
if (source.size != destination->size)
Logger::Warning("Blitting a render target but they're not the same size?");
void JGL::RenderTarget::Blit(const JGL::RenderTarget& source, JGL::RenderTarget* destination, const Vector2i& position) {
if (source.GetDimensions().x > destination->GetDimensions().x || source.GetDimensions().y > destination->GetDimensions().y)
Logger::Warning("Blitting a Render Target onto another Render Target but the destination Render Target is too small?");
// Save the GL state.
GLuint current_fbo = GetActiveGLFramebufferHandle();
@@ -322,7 +322,7 @@ void JGL::RenderTarget::Blit(const JGL::RenderTarget& source, JGL::RenderTarget*
// Draw the contents of one into the other.
glBindFramebuffer(GL_READ_FRAMEBUFFER, source.framebuffer_object);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, destination->framebuffer_object);
glBlitFramebuffer(0, 0, source.size.x, source.size.y, 0, 0, source.size.x, source.size.y, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBlitFramebuffer(0, 0, source.size.x, source.size.y, position.x, position.y, position.x + source.size.x, position.y + source.size.y, GL_COLOR_BUFFER_BIT, GL_NEAREST);
// Put the GL state back.
glBindFramebuffer(GL_READ_FRAMEBUFFER, current_read_fbo);
@@ -330,6 +330,12 @@ void JGL::RenderTarget::Blit(const JGL::RenderTarget& source, JGL::RenderTarget*
glBindFramebuffer(GL_FRAMEBUFFER, current_fbo);
}
void JGL::RenderTarget::Blit(const Texture* source, RenderTarget* destination, const Vector2i& position) {
auto temp = new RenderTarget(source);
Blit(*temp, destination);
delete temp;
}
// To avoid repeatedly allocating and deallocating.
JGL::RenderTarget* pixel = nullptr;
void JGL::RenderTarget::Blit(const Color4& color, const Vector2i& position, JGL::RenderTarget* destination) {

View File

@@ -189,4 +189,24 @@ namespace JGL
// In 99% of cases you wouldn't want this. But in this scenario we do.
operator delete(this_texture);
}
Texture::Texture(const Texture* textures, const size_t& texture_count) {
float length = 0;
float biggest_y = 0;
for (int i = 0; i < texture_count; i++) {
if (biggest_y < textures[i].texture_size.y)
biggest_y = textures[i].texture_size.y;
length += textures[i].texture_size.x;
}
auto* result = new Texture(Vector2(length, biggest_y));
auto render_target = RenderTarget(result);
int next_x = 0;
for (int i = 0; i < texture_count; i++) {
RenderTarget::Blit(&textures[i], &render_target, Vector2i(next_x, 0));
next_x += textures[i].GetDimensions().x;
}
}
}