Skip to content

Commit

Permalink
fix(core): improve antialiasing of text and link marks
Browse files Browse the repository at this point in the history
... by applying slight "gamma correction" to opacity.

Ideally, all blending should happen in linear color space, not in sRGB.
  • Loading branch information
tuner committed Mar 7, 2024
1 parent 33055fe commit 5feda3f
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 3 deletions.
11 changes: 11 additions & 0 deletions packages/core/src/gl/includes/common.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,17 @@ float linearstep(float edge0, float edge1, float x) {
return clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
}

/**
* Calculates a gamma for antialiasing opacity based on the color.
*/
float getGammaForColor(vec3 rgb) {
return mix(
1.25,
0.75,
// RGB should be linearized but this is good enough for now
smoothstep(0.0, 1.0, dot(rgb, vec3(0.299, 0.587, 0.114))));
}

// Fragment shader stuff ////////////////////////////////////////////////////////

// TODO: include the following only in fragment shaders
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/marks/link.fragment.glsl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
in vec4 vColor;
in float vSize;
in float vNormalLengthInPixels;
in float vGamma;

out lowp vec4 fragColor;

Expand All @@ -10,6 +11,8 @@ void main(void) {
float distance = abs(vNormalLengthInPixels);
float opacity = clamp(((vSize / 2.0 - distance) * dpr), 0.0, 1.0);

opacity = pow(opacity, vGamma);

fragColor = vColor * opacity;

if (uPickingEnabled) {
Expand Down
4 changes: 4 additions & 0 deletions packages/core/src/marks/link.vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ out float vSize;
/** The distance from the line center to the direction of normal in pixels */
out float vNormalLengthInPixels;

out float vGamma;

const int SHAPE_ARC = 0;
const int SHAPE_DOME = 1;
const int SHAPE_DIAGONAL = 2;
Expand Down Expand Up @@ -194,6 +196,8 @@ void main(void) {

vColor = vec4(color * opacity, opacity);

vGamma = getGammaForColor(color);

vSize = paddedSize;

setupPicking();
Expand Down
6 changes: 4 additions & 2 deletions packages/core/src/marks/text.fragment.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ in vec2 vTexCoord;
in float vEdgeFadeOpacity;
in vec4 vColor;
in float vSlope;
in float vGamma;

out lowp vec4 fragColor;

Expand All @@ -28,8 +29,9 @@ void main() {

float opa = clamp((sigDist - 0.5) * slope + 0.5, 0.0, 1.0);

// Raise to the power of 2.2 to do some cheap gamma correction
opa *= pow(clamp(vEdgeFadeOpacity, 0.0, 1.0), 2.2);
opa *= clamp(vEdgeFadeOpacity, 0.0, 1.0);

opa = pow(opa, vGamma);

fragColor = vColor * opa;

Expand Down
9 changes: 8 additions & 1 deletion packages/core/src/marks/text.vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ out vec2 vTexCoord;
out vec4 vColor;
out float vSlope;
out float vEdgeFadeOpacity;
out float vGamma;

struct RangeResult {
float pos;
Expand Down Expand Up @@ -203,7 +204,13 @@ void main(void) {
// Controls antialiasing of the SDF
vSlope = max(1.0, min(size.x, size.y) / uSdfNumerator);

vColor = vec4(getScaled_color() * opacity, opacity);
vec3 color = getScaled_color();

// Premultiply alpha
vColor = vec4(color * opacity, opacity);

// Do something like gamma correction for text when the color is close to black or white.
vGamma = getGammaForColor(color);

vTexCoord = textureCoord;

Expand Down

0 comments on commit 5feda3f

Please sign in to comment.