Copy texture without readbacks.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 2m5s

This commit is contained in:
2024-10-13 09:45:24 -04:00
parent 5d981e64fc
commit bb4a80e36d
6 changed files with 56 additions and 23 deletions

View File

@@ -1,12 +1,13 @@
#pragma once
#include <glad/glad.h>
#include <JGL/types/Texture.h>
#include <Color4.hpp>
#include <Colors.hpp>
#include <JGL/types/Enums.h>
#include <J3ML/LinearAlgebra/Vector2.hpp>
namespace JGL {
class RenderTarget;
class Texture; // Forward declare.
}
//TODO copy constructor for this. Copying this as it is and then that copy going out of scope will crash the program as it sits.
@@ -21,7 +22,7 @@ private:
bool texture_created_by_us = false;
GLuint framebuffer_object = 0;
GLuint depth_buffer = 0;
Texture* texture = nullptr;
const Texture* texture = nullptr;
MSAA_SAMPLE_RATE msaa_sample_rate = MSAA_SAMPLE_RATE::MSAA_NONE;
GLuint msaa_framebuffer_object = 0;
GLuint msaa_depth_buffer = 0;
@@ -39,6 +40,9 @@ public:
/// Blits the MSAA FBO onto the regular FBO if MSAA is enabled and or If you're rendering to a texture which uses mipmaps,
/// It regenerates them so what you drew doesn't disappear at a distance. Otherwise it does nothing.
void Blit() const;
/// Blit a render target onto another. Will break if they're not the same size.
static void Blit(const RenderTarget& source, RenderTarget* destination);
[[nodiscard]] bool TextureCreatedByRenderTarget() const;
public:
[[nodiscard]] Vector2 GetDimensions() const;
@@ -47,7 +51,7 @@ public:
/// You need to run "Blit()" after rendering to your FBO before you show it.
/// @note Also, If the texture wasn't made by the RenderTarget you don't want this. It would destroy the texture.
[[nodiscard]] bool MSAAEnabled() const;
[[nodiscard]] Texture* GetJGLTexture() const;
[[nodiscard]] const Texture* GetJGLTexture() const;
[[nodiscard]] GLuint GetGLTextureHandle() const;
[[nodiscard]] GLuint GetGLFramebufferObjectHandle() const;
[[nodiscard]] GLuint GetGLDepthBufferHandle() const;
@@ -56,7 +60,7 @@ public:
[[nodiscard]] std::vector<GLfloat> GetData() const;
public:
/// Create a render target for a texture that already exists. For adding to an existing texture.
explicit RenderTarget(Texture* texture, const Color4& clear_color = Colors::Black);
explicit RenderTarget(const Texture* texture, const Color4& clear_color = Colors::Black);
/// Create a Render Target with a brand new texture. Want to render JGL elements onto a texture and display it as a sprite?
explicit RenderTarget(const Vector2& size, const Color4& clear_color = Colors::Black, bool use_depth = false, MSAA_SAMPLE_RATE sample_rate = MSAA_SAMPLE_RATE::MSAA_NONE);
~RenderTarget();

View File

@@ -52,8 +52,6 @@ namespace JGL {
[[nodiscard]] TextureFlag GetFlags() const;
[[nodiscard]] TextureFormat GetFormat() const;
[[nodiscard]] std::vector<Color4> GetPixelData() const;
void SetTextureHandle(GLuint handle);
void SetFlags(const TextureFlag& flags);
};
}

View File

@@ -118,7 +118,7 @@ public:
glDepthMask(GL_TRUE);
image = new Texture("assets/sprites/Re3D.png", TextureFilteringMode::BILINEAR);
j2d_render_target = new RenderTarget({540, 540}, {0,0,0,0}, false, MSAA_SAMPLE_RATE::MSAA_8X);
image2 = new Texture("assets/sprites/Re3D.png",TextureFilteringMode::BILINEAR);
image2 = image;
image2_render_target = new RenderTarget(image2);
J2D::Begin(image2_render_target);

View File

@@ -162,7 +162,8 @@ namespace JGL {
float y = pos.y;
float z = pos.z;
// TODO: this is broken because it causes the text to be shifted downwards.
/*
bool round_text_coords_for_crisp_rendering = true;
// TODO: This currently does not account for non-integer scale factors.
@@ -172,6 +173,7 @@ namespace JGL {
y = J3ML::Math::Floor(y);
z = J3ML::Math::Floor(z);
}
*/
CachedFont* cachedFont = fontCache.getFont(size, font.index);
if (font.face == nullptr)

View File

@@ -1,8 +1,9 @@
#include <JGL/types/RenderTarget.h>
#include <JGL/types/Texture.h>
#include <JGL/logger/logger.h>
#include <stdexcept>
JGL::Texture* JGL::RenderTarget::GetJGLTexture() const {
const JGL::Texture* JGL::RenderTarget::GetJGLTexture() const {
return texture;
}
@@ -51,7 +52,7 @@ Color4 JGL::RenderTarget::GetClearColor() const {
}
/// Idk why you'd ever want to clear it out if you're rendering onto a texture you passed in :shrug:.
JGL::RenderTarget::RenderTarget(JGL::Texture* texture, const Color4& clear_color) {
JGL::RenderTarget::RenderTarget(const JGL::Texture* texture, const Color4& clear_color) {
GLuint current_fbo = GetActiveGLFramebufferHandle();
GLint viewport[4] = {0, 0, 0, 0};
glGetIntegerv(GL_VIEWPORT, viewport);
@@ -112,7 +113,6 @@ JGL::RenderTarget::RenderTarget(const Vector2& size, const Color4& clear_color,
this->clear_color = clear_color;
this->size = size;
texture_created_by_us = true;
this->texture->SetFlags(INVERT_Y);
if (sample_rate != MSAA_SAMPLE_RATE::MSAA_NONE)
SetMSAAEnabled(sample_rate);
@@ -301,3 +301,25 @@ void JGL::RenderTarget::Blit() const {
glBindTexture(GL_TEXTURE_2D, current_texture);
}
}
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?");
// Save the GL state.
GLuint current_fbo = GetActiveGLFramebufferHandle();
GLint current_draw_fbo = 0;
GLint current_read_fbo = 0;
glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &current_read_fbo);
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &current_draw_fbo);
// 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);
// Put the GL state back.
glBindFramebuffer(GL_READ_FRAMEBUFFER, current_read_fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, current_draw_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, current_fbo);
}

View File

@@ -1,5 +1,6 @@
#include <JGL/types/Texture.h>
#include <iostream>
#include <JGL/types/RenderTarget.h>
using namespace ReImage;
@@ -36,9 +37,11 @@ namespace JGL
texture_size = size;
texture_filtering_mode = TextureFilteringMode::NEAREST;
texture_wrapping_mode = TextureWrappingMode::CLAMP_TO_EDGE;
texture_flags = TextureFlag::NONE;
// Because in vram it'll be right side up.
texture_flags = TextureFlag::INVERT_Y;
glBindTexture(GL_TEXTURE_2D, previous_texture);
}
void Texture::load(Image* software_texture, const Vector2& size, const TextureFormat& format,
@@ -155,10 +158,6 @@ namespace JGL
return texture_filtering_mode;
}
void Texture::SetTextureHandle(GLuint handle) {
texture_handle = handle;
}
TextureWrappingMode Texture::GetWrappingMode() const {
return texture_wrapping_mode;
}
@@ -173,13 +172,21 @@ namespace JGL
}
Texture::Texture(const Texture& rhs) {
auto pixels = rhs.GetPixelData();
auto image = Image(pixels.data(), pixels.size(), rhs.GetDimensions().x, rhs.GetDimensions().y);
this->load(&image, rhs.GetDimensions(), rhs.texture_format, rhs.texture_filtering_mode, rhs.texture_wrapping_mode);
this->texture_flags = rhs.texture_flags;
}
auto* this_texture = new Texture(rhs.GetDimensions());
auto this_render_target = RenderTarget(this);
auto rhs_render_target = RenderTarget(&rhs);
void Texture::SetFlags(const TextureFlag &flags) {
this->texture_flags = flags;
RenderTarget::Blit(rhs_render_target, &this_render_target);
this->texture_handle = this_texture->texture_handle;
this->texture_size = this_texture->texture_size;
this->texture_flags = this_texture->texture_flags;
this->texture_format = this_texture->texture_format;
this->texture_filtering_mode = this_texture->texture_filtering_mode;
this->texture_wrapping_mode = this_texture->texture_wrapping_mode;
// Free the memory of "this_texture" without calling the destructor.
// In 99% of cases you wouldn't want this. But in this scenario we do.
operator delete(this_texture);
}
}