mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-09-05 19:08:17 +00:00
Gamma correct image scaling (#7368)
Fixes the gamma error noted in #7367 for both Metal and OpenGL by using sRGB image formats for the textures. This branch also includes the commits from #7367, so it'd probably be best to review and merge that first.
This commit is contained in:
@@ -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.
|
||||
_,
|
||||
};
|
||||
|
@@ -96,6 +96,7 @@ pub const MTLVertexStepFunction = enum(c_ulong) {
|
||||
pub const MTLPixelFormat = enum(c_ulong) {
|
||||
r8unorm = 10,
|
||||
rgba8unorm = 70,
|
||||
rgba8unorm_srgb = 71,
|
||||
rgba8uint = 73,
|
||||
bgra8unorm = 80,
|
||||
bgra8unorm_srgb = 81,
|
||||
|
@@ -441,7 +441,7 @@ pub const Image = union(enum) {
|
||||
};
|
||||
|
||||
// Set our properties
|
||||
desc.setProperty("pixelFormat", @intFromEnum(mtl.MTLPixelFormat.rgba8unorm));
|
||||
desc.setProperty("pixelFormat", @intFromEnum(mtl.MTLPixelFormat.rgba8unorm_srgb));
|
||||
desc.setProperty("width", @as(c_ulong, @intCast(p.width)));
|
||||
desc.setProperty("height", @as(c_ulong, @intCast(p.height)));
|
||||
|
||||
|
@@ -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,
|
||||
};
|
||||
|
||||
|
@@ -668,12 +668,12 @@ fragment float4 image_fragment(
|
||||
|
||||
float4 rgba = image.sample(textureSampler, in.tex_coord);
|
||||
|
||||
return load_color(
|
||||
uchar4(rgba * 255.0),
|
||||
// We assume all images are sRGB regardless of the configured colorspace
|
||||
// TODO: Maybe support wide gamut images?
|
||||
false,
|
||||
uniforms.use_linear_blending
|
||||
);
|
||||
if (!uniforms.use_linear_blending) {
|
||||
rgba = unlinearize(rgba);
|
||||
}
|
||||
|
||||
rgba.rgb *= rgba.a;
|
||||
|
||||
return rgba;
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user