@@ -1491,7 +1491,7 @@ dependencies = [
[[package]]
name = "blade-graphics"
version = "0.4.0"
-source = "git+https://github.com/kvark/blade?rev=f5766863de9dcc092e90fdbbc5e0007a99e7f9bf#f5766863de9dcc092e90fdbbc5e0007a99e7f9bf"
+source = "git+https://github.com/kvark/blade?rev=e35b2d41f221a48b75f7cf2e78a81e7ecb7a383c#e35b2d41f221a48b75f7cf2e78a81e7ecb7a383c"
dependencies = [
"ash",
"ash-window",
@@ -1521,7 +1521,7 @@ dependencies = [
[[package]]
name = "blade-macros"
version = "0.2.1"
-source = "git+https://github.com/kvark/blade?rev=f5766863de9dcc092e90fdbbc5e0007a99e7f9bf#f5766863de9dcc092e90fdbbc5e0007a99e7f9bf"
+source = "git+https://github.com/kvark/blade?rev=e35b2d41f221a48b75f7cf2e78a81e7ecb7a383c#e35b2d41f221a48b75f7cf2e78a81e7ecb7a383c"
dependencies = [
"proc-macro2",
"quote",
@@ -256,8 +256,8 @@ async-recursion = "1.0.0"
async-tar = "0.4.2"
async-trait = "0.1"
bitflags = "2.4.2"
-blade-graphics = { git = "https://github.com/kvark/blade", rev = "f5766863de9dcc092e90fdbbc5e0007a99e7f9bf" }
-blade-macros = { git = "https://github.com/kvark/blade", rev = "f5766863de9dcc092e90fdbbc5e0007a99e7f9bf" }
+blade-graphics = { git = "https://github.com/kvark/blade", rev = "e35b2d41f221a48b75f7cf2e78a81e7ecb7a383c" }
+blade-macros = { git = "https://github.com/kvark/blade", rev = "e35b2d41f221a48b75f7cf2e78a81e7ecb7a383c" }
cap-std = "3.0"
chrono = { version = "0.4", features = ["serde"] }
clap = { version = "4.4", features = ["derive"] }
@@ -162,7 +162,7 @@ impl BladeAtlasState {
usage = gpu::TextureUsage::COPY | gpu::TextureUsage::RESOURCE;
}
AtlasTextureKind::Polychrome => {
- format = gpu::TextureFormat::Bgra8Unorm;
+ format = gpu::TextureFormat::Bgra8UnormSrgb;
usage = gpu::TextureUsage::COPY | gpu::TextureUsage::RESOURCE;
}
AtlasTextureKind::Path => {
@@ -360,9 +360,7 @@ impl BladeRenderer {
size: config.size,
usage: gpu::TextureUsage::TARGET,
display_sync: gpu::DisplaySync::Recent,
- //Note: this matches the original logic of the Metal backend,
- // but ultimaterly we need to switch to `Linear`.
- color_space: gpu::ColorSpace::Srgb,
+ color_space: gpu::ColorSpace::Linear,
allow_exclusive_full_screen: false,
transparent: config.transparent,
};
@@ -88,6 +88,14 @@ fn distance_from_clip_rect(unit_vertex: vec2<f32>, bounds: Bounds, clip_bounds:
return distance_from_clip_rect_impl(position, clip_bounds);
}
+// https://gamedev.stackexchange.com/questions/92015/optimized-linear-to-srgb-glsl
+fn srgb_to_linear(srgb: vec3<f32>) -> vec3<f32> {
+ let cutoff = srgb < vec3<f32>(0.04045);
+ let higher = pow((srgb + vec3<f32>(0.055)) / vec3<f32>(1.055), vec3<f32>(2.4));
+ let lower = srgb / vec3<f32>(12.92);
+ return select(higher, lower, cutoff);
+}
+
fn hsla_to_rgba(hsla: Hsla) -> vec4<f32> {
let h = hsla.h * 6.0; // Now, it's an angle but scaled in [0, 6) range
let s = hsla.s;
@@ -97,8 +105,7 @@ fn hsla_to_rgba(hsla: Hsla) -> vec4<f32> {
let c = (1.0 - abs(2.0 * l - 1.0)) * s;
let x = c * (1.0 - abs(h % 2.0 - 1.0));
let m = l - c / 2.0;
-
- var color = vec4<f32>(m, m, m, a);
+ var color = vec3<f32>(m);
if (h >= 0.0 && h < 1.0) {
color.r += c;
@@ -120,7 +127,12 @@ fn hsla_to_rgba(hsla: Hsla) -> vec4<f32> {
color.b += x;
}
- return color;
+ // Input colors are assumed to be in sRGB space,
+ // but blending and rendering needs to happen in linear space.
+ // The output will be converted to sRGB by either the target
+ // texture format or the swapchain color space.
+ let linear = srgb_to_linear(color);
+ return vec4<f32>(linear, a);
}
fn over(below: vec4<f32>, above: vec4<f32>) -> vec4<f32> {
@@ -181,7 +193,8 @@ fn quad_sdf(point: vec2<f32>, bounds: Bounds, corner_radii: Corners) -> f32 {
// target alpha compositing mode.
fn blend_color(color: vec4<f32>, alpha_factor: f32) -> vec4<f32> {
let alpha = color.a * alpha_factor;
- return select(vec4<f32>(color.rgb, alpha), vec4<f32>(color.rgb, 1.0) * alpha, globals.premultiplied_alpha != 0u);
+ let multiplier = select(1.0, alpha, globals.premultiplied_alpha != 0u);
+ return vec4<f32>(color.rgb * multiplier, alpha);
}
// --- quads --- //