Fix using RenderTargets on a texture that has mipmaps.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 5m40s

Also better mipmap generation.
This commit is contained in:
2024-10-10 13:10:04 -04:00
parent e155d272bb
commit 39c7c7ac0d
4 changed files with 40 additions and 50 deletions

View File

@@ -35,8 +35,9 @@ public:
/// @param new_size new size in px.
void Resize(const Vector2& new_size);
void SetMSAAEnabled(MSAA_SAMPLE_RATE sample_rate);
/// Blits the MSAA FBO onto the regular FBO if MSAA is enabled.
/// Does nothing is MSAA is not enabled or if the color attachment is a texture not created by the RenderTarget.
/// If you're using raw OpenGL commands to draw to this outside of J2D or J3D don't forget to do this.
/// 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;
[[nodiscard]] bool TextureCreatedByRenderTarget() const;
public:

View File

@@ -802,7 +802,7 @@ namespace JGL {
void J3D::DrawLine(const Color4& color, const Vector3& A, const Vector3& B, float thickness) {
if (!inJ3D)
Logger::Error("Attempt to Render J3D element before J3D begin.");
Logger::Error("Drawing J3D element before J3D begin.");
Vector3 vertices[] = {A, B};

View File

@@ -268,23 +268,36 @@ void JGL::RenderTarget::SetMSAAEnabled(JGL::MSAA_SAMPLE_RATE sample_rate) {
}
void JGL::RenderTarget::Blit() const {
if (!MSAAEnabled() || !TextureCreatedByRenderTarget())
return;
if (MSAAEnabled() && TextureCreatedByRenderTarget()) {
// 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);
// 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, msaa_framebuffer_object);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer_object);
glBlitFramebuffer(0, 0, size.x, size.y, 0, 0, size.x, size.y, GL_COLOR_BUFFER_BIT, GL_NEAREST);
// Draw the contents of one into the other.
glBindFramebuffer(GL_READ_FRAMEBUFFER, msaa_framebuffer_object);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer_object);
glBlitFramebuffer(0, 0, size.x, size.y, 0, 0, size.x, 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);
// Put the GL state back.
glBindFramebuffer(GL_READ_FRAMEBUFFER, current_read_fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, current_draw_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, current_fbo);
}
// Fixes using render targets on a texture that has mipmaps.
if (GetJGLTexture()->GetFilteringMode() == TextureFilteringMode::MIPMAP_NEAREST
|| GetJGLTexture()->GetFilteringMode() == TextureFilteringMode::MIPMAP_BILINEAR ||
GetJGLTexture()->GetFilteringMode() == TextureFilteringMode::MIPMAP_TRILINEAR) {
GLint current_texture = 0;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
glBindTexture(GL_TEXTURE_2D, GetJGLTexture()->GetGLTextureHandle());
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, current_texture);
}
}

View File

@@ -60,53 +60,33 @@ namespace JGL
if (wrapping_mode == TextureWrappingMode::CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
else if (wrapping_mode == TextureWrappingMode::REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
else if (wrapping_mode == TextureWrappingMode::MIRRORED_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
else if (wrapping_mode == TextureWrappingMode::CLAMP_TO_BORDER)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
if (filtering_mode == TextureFilteringMode::NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
else if (filtering_mode == TextureFilteringMode::BILINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
else if (filtering_mode == TextureFilteringMode::MIPMAP_NEAREST ||
filtering_mode == TextureFilteringMode::MIPMAP_BILINEAR ||
filtering_mode == TextureFilteringMode::MIPMAP_TRILINEAR) {
//3 mipmap levels.
auto *m1 = new Image(software_texture->downscale(2));
auto *m2 = new Image(software_texture->downscale(4));
auto *m3 = new Image(software_texture->downscale(8));
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 3);
if (format == TextureFormat::RGBA) {
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, m1->getWidth(), m1->getHeight(), 0, GL_RGBA,
GL_UNSIGNED_BYTE, m1->pixel_data.data());
glTexImage2D(GL_TEXTURE_2D, 2, GL_RGBA, m2->getWidth(), m2->getHeight(), 0, GL_RGBA,
GL_UNSIGNED_BYTE, m2->pixel_data.data());
glTexImage2D(GL_TEXTURE_2D, 3, GL_RGBA, m3->getWidth(), m3->getHeight(), 0, GL_RGBA,
GL_UNSIGNED_BYTE, m3->pixel_data.data());
} else if (format == TextureFormat::RGB) {
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, m1->getWidth(), m1->getHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE,
m1->pixel_data.data());
glTexImage2D(GL_TEXTURE_2D, 2, GL_RGB, m2->getWidth(), m2->getHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE,
m2->pixel_data.data());
glTexImage2D(GL_TEXTURE_2D, 3, GL_RGB, m3->getWidth(), m3->getHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE,
m3->pixel_data.data());
}
if (filtering_mode == TextureFilteringMode::MIPMAP_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST),
@@ -119,10 +99,6 @@ namespace JGL
else if (filtering_mode == TextureFilteringMode::MIPMAP_TRILINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR),
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
delete m1;
delete m2;
delete m3;
}
texture_size = size;
texture_format = format;