From ea79fdea119b40e4eca875611d4d224bddb963f1 Mon Sep 17 00:00:00 2001 From: Qwerasd Date: Thu, 15 May 2025 12:22:56 -0600 Subject: [PATCH] fix(OpenGL): use sRGB texture format for gamma correct interpolation otherwise images will be too dark when scaled --- pkg/opengl/Texture.zig | 3 +++ src/renderer/opengl/image.zig | 4 ++-- src/renderer/shaders/image.f.glsl | 17 +++++++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/pkg/opengl/Texture.zig b/pkg/opengl/Texture.zig index 5804ef538..fa5cf770b 100644 --- a/pkg/opengl/Texture.zig +++ b/pkg/opengl/Texture.zig @@ -70,6 +70,9 @@ pub const InternalFormat = enum(c_int) { rgb = c.GL_RGB, rgba = c.GL_RGBA, + srgb = c.GL_SRGB, + srgba = c.GL_SRGB_ALPHA, + // There are so many more that I haven't filled in. _, }; diff --git a/src/renderer/opengl/image.zig b/src/renderer/opengl/image.zig index b22d10ea3..26cd90736 100644 --- a/src/renderer/opengl/image.zig +++ b/src/renderer/opengl/image.zig @@ -368,8 +368,8 @@ pub const Image = union(enum) { internal: gl.Texture.InternalFormat, format: gl.Texture.Format, } = switch (self.*) { - .pending_rgb, .replace_rgb => .{ .internal = .rgb, .format = .rgb }, - .pending_rgba, .replace_rgba => .{ .internal = .rgba, .format = .rgba }, + .pending_rgb, .replace_rgb => .{ .internal = .srgb, .format = .rgb }, + .pending_rgba, .replace_rgba => .{ .internal = .srgba, .format = .rgba }, else => unreachable, }; diff --git a/src/renderer/shaders/image.f.glsl b/src/renderer/shaders/image.f.glsl index e8c00b271..e4aa9ef8e 100644 --- a/src/renderer/shaders/image.f.glsl +++ b/src/renderer/shaders/image.f.glsl @@ -6,7 +6,24 @@ layout(location = 0) out vec4 out_FragColor; uniform sampler2D image; +// Converts a color from linear to sRGB gamma encoding. +vec4 unlinearize(vec4 linear) { + bvec3 cutoff = lessThan(linear.rgb, vec3(0.0031308)); + vec3 higher = pow(linear.rgb, vec3(1.0/2.4)) * vec3(1.055) - vec3(0.055); + vec3 lower = linear.rgb * vec3(12.92); + + return vec4(mix(higher, lower, cutoff), linear.a); +} + void main() { vec4 color = texture(image, tex_coord); + + // Our texture is stored with an sRGB internal format, + // which means that the values are linearized when we + // sample the texture, but for now we actually want to + // output the color with gamma compression, so we do + // that. + color = unlinearize(color); + out_FragColor = vec4(color.rgb * color.a, color.a); }