Fix using RenderTargets on a texture that has mipmaps.
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 5m40s
All checks were successful
Run ReCI Build Test / Explore-Gitea-Actions (push) Successful in 5m40s
Also better mipmap generation.
This commit is contained in:
@@ -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:
|
||||
|
@@ -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};
|
||||
|
||||
|
@@ -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, ¤t_read_fbo);
|
||||
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, ¤t_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, ¤t_read_fbo);
|
||||
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, ¤t_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, ¤t_texture);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, GetJGLTexture()->GetGLTextureHandle());
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, current_texture);
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user