Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Selected object outline has a consistent width with zoom #505

Merged
merged 3 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/colorizer/ColorizeCanvas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export const BACKGROUND_ID = -1;
type ColorizeUniformTypes = {
/** Scales from canvas coordinates to frame coordinates. */
canvasToFrameScale: Vector2;
canvasSizePx: Vector2;
/** XY offset of the frame, in normalized frame coordinates. [-0.5, 0.5] range. */
panOffset: Vector2;
/** Image, mapping each pixel to an object ID using the RGBA values. */
Expand Down Expand Up @@ -91,6 +92,7 @@ const getDefaultUniforms = (): ColorizeUniforms => {
return {
panOffset: new Uniform(new Vector2(0, 0)),
canvasToFrameScale: new Uniform(new Vector2(1, 1)),
canvasSizePx: new Uniform(new Vector2(1, 1)),
frame: new Uniform(emptyFrame),
featureData: new Uniform(emptyFeature),
outlierData: new Uniform(emptyOutliers),
Expand Down Expand Up @@ -299,6 +301,7 @@ export default class ColorizeCanvas {
if (!frameResolution || !canvasResolution) {
return;
}
this.setUniform("canvasSizePx", canvasResolution);
// Both the frame and the canvas have coordinates in a range of [0, 1] in the x and y axis.
// However, the canvas may have a different aspect ratio than the frame, so we need to scale
// the frame to fit within the canvas while maintaining the aspect ratio.
Expand Down
14 changes: 7 additions & 7 deletions src/colorizer/shaders/colorize_RGBA8U.frag
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ uniform float featureColorRampMin;
uniform float featureColorRampMax;

uniform vec2 canvasToFrameScale;
uniform vec2 canvasSizePx;
uniform vec2 panOffset;
uniform sampler2D colorRamp;
uniform sampler2D overlay;
Expand All @@ -25,6 +26,7 @@ uniform float objectOpacity;

uniform vec3 backgroundColor;
uniform vec3 outlineColor;
uniform float outlineWidthPx;
// Background color for the canvas, anywhere where the frame is not drawn.
uniform vec3 canvasBackgroundColor;

Expand Down Expand Up @@ -89,13 +91,12 @@ vec4 getColorRamp(float val) {
return texture(colorRamp, vec2(adjustedVal, 0.5));
}

bool isEdge(vec2 uv, ivec2 frameDims) {
bool isEdge(vec2 uv) {
float thickness = 2.0;
float wStep = 1.0 / float(frameDims.x);
float hStep = 1.0 / float(frameDims.y);
// step size is equal to 1 onscreen canvas pixel
float wStep = 1.0 / float(canvasSizePx.x) * float(canvasToFrameScale.x);
float hStep = 1.0 / float(canvasSizePx.y) * float(canvasToFrameScale.y);
// sample around the pixel to see if we are on an edge
// TODO: Fix this so it samples using canvas pixel offsets instead of frame pixel offsets.
// Currently, the edge detection is sparser when loading high-resolution frames.
int R = int(combineColor(texture(frame, uv + vec2(thickness * wStep, 0)))) - 1;
int L = int(combineColor(texture(frame, uv + vec2(-thickness * wStep, 0)))) - 1;
int T = int(combineColor(texture(frame, uv + vec2(0, thickness * hStep)))) - 1;
Expand Down Expand Up @@ -159,9 +160,8 @@ vec4 getObjectColor(vec2 sUv, float opacity) {
}

// do an outline around highlighted object
ivec2 frameDims = textureSize(frame, 0);
if (int(id) - 1 == highlightedId) {
if (isEdge(sUv, frameDims)) {
if (isEdge(sUv)) {
// ignore opacity for edge color
return vec4(outlineColor, 1.0);
}
Expand Down
Loading