Skip to content

Commit

Permalink
display(fixed): Glitches that may have appeared on the edges of previ…
Browse files Browse the repository at this point in the history
…ewed raster tiles have been resolved.

Signed-off-by: Tim Deubler <[email protected]>
  • Loading branch information
TerminalTim committed Dec 8, 2023
1 parent c388ea2 commit 607e937
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 11 deletions.
22 changes: 15 additions & 7 deletions packages/display/src/displays/webgl/GLRender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export class GLRender implements BasicRender {
r: false, g: false, b: false, a: false
};
readonly vPMat: Float32Array; // projection matrix
readonly vPRasterMat: Float32Array; // pixel aligned projection matrix for raster data
private readonly vMat: Float32Array; // view matrix
private readonly invVPMat: Float32Array; // inverse projection matrix
// the worldmatrix used by custom layers to project from absolute worldcoordinates [0-1] to screencoordinates
Expand Down Expand Up @@ -175,6 +176,7 @@ export class GLRender implements BasicRender {
};

this.vPMat = mat4.create();
this.vPRasterMat = mat4.create();
this.vMat = mat4.create();
this.invVPMat = mat4.create();
this.screenMat = mat4.create();
Expand Down Expand Up @@ -438,9 +440,7 @@ export class GLRender implements BasicRender {
// scale
scale / groundRes
]);

mat4.translate(viewMatrix, viewMatrix, [-centerPixelX, -centerPixelY, 0]);

mat4.multiply(projectionMatrix, projectionMatrix, viewMatrix);

invert(this.invVPMat, projectionMatrix);
Expand All @@ -460,6 +460,14 @@ export class GLRender implements BasicRender {
cameraWorld[2] = -1;
transformMat4(cameraWorld, cameraWorld, this.invVPMat);

// pixel perfect matrix used for crisper raster graphics, icons/text/raster-tiles
// rounding in shader leads to precision issues and tiles edges become visible when the map is scaled.
const pixelPerfectMatrix = mat4.copy(this.vPRasterMat, projectionMatrix);
const worldCenterPixelX = worldCenterX * worldSize;
const worldCenterPixelY = worldCenterY * worldSize;
const dx = worldCenterPixelX - Math.round(worldCenterPixelX) + centerPixelX % 1;
const dy = worldCenterPixelY - Math.round(worldCenterPixelY) + centerPixelY % 1;
mat4.translate(pixelPerfectMatrix, pixelPerfectMatrix, [dx - Math.round(dx), dy - Math.round(dy), 0]);

// used for debug only...
// let s05 = mat4.clone(this.vPMat);
Expand Down Expand Up @@ -643,7 +651,7 @@ export class GLRender implements BasicRender {
const {sharedUniforms} = this;
sharedUniforms.u_fixedView = this.fixedView; // must be set at render time
sharedUniforms.u_scale = this.scale * dZoom;
sharedUniforms.u_matrix = pMat || this.vPMat;
sharedUniforms.u_matrix = pMat || (buffer.pixelPerfect ? this.vPRasterMat : this.vPMat);
sharedUniforms.u_zMeterToPixel = this.zMeterToPixel / dZoom;

const uses2PassAlpha = buffer.pass & PASS.POST_ALPHA;
Expand Down Expand Up @@ -872,7 +880,7 @@ export class GLRender implements BasicRender {
const scale = dWidth / sWidth;
const px = dx / scale - sx;
const py = dy / scale - sy;
const previewTransformMatrix = this.initPreviewMatrix(x, y, scale);
const previewTransformMatrix = this.initPreviewMatrix(x, y, scale, buffer.pixelPerfect);
// if (buffer.scissor) {
// this.initScissor(x + dx, y + dy, tileSize * scale, this.vPMat);
// // this.initScissor(x - sx * scale, y - sy * scale, dWidth * scale, this.vPMat);
Expand All @@ -886,15 +894,15 @@ export class GLRender implements BasicRender {
}
}

private initPreviewMatrix(tx: number, ty: number, s: number): Float32Array {
const {tilePreviewTransform, vPMat} = this;
private initPreviewMatrix(tx: number, ty: number, s: number, pixelPerfect?: boolean): Float32Array {
const {tilePreviewTransform} = this;
const {m} = tilePreviewTransform;
if (
tilePreviewTransform.tx != tx ||
tilePreviewTransform.ty != ty ||
tilePreviewTransform.s != s
) {
mat4.copy(m, vPMat);
mat4.copy(m, pixelPerfect ? this.vPRasterMat : this.vPMat);
mat4.translate(m, m, [tx, ty, 0]);
mat4.scale(m, m, [s, s, 1]);

Expand Down
2 changes: 2 additions & 0 deletions packages/display/src/displays/webgl/buffer/GeometryBuffer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ class GeometryBuffer {
instances: number = 0;
// id of the program to render the buffer
progId: string;
// If set to true, the buffer should render "pixel-perfect" to ensure sharp, precise raster graphics.
pixelPerfect?: boolean = false;

private _cullFace: number = 0;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ const createImageBuffer = (img: Image, gl: WebGLRenderingContext, size: number,
tileBuffer.clip = true;
tileBuffer.blend = alpha;
tileBuffer.pass = alpha ? PASS.ALPHA : PASS.OPAQUE;
tileBuffer.pixelPerfect = true;

tileBuffer.cullFace(FRONT);

Expand Down
9 changes: 5 additions & 4 deletions packages/display/src/displays/webgl/glsl/image_vertex.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ uniform highp mat4 u_matrix;
uniform highp vec2 u_topLeft;
uniform highp vec2 u_resolution;
uniform float u_tileScale;
//uniform bool u_snapGrid;
//uniform bool u_fixedView;
varying vec2 v_textureCoord;
uniform float u_scale;

void main(void){
v_textureCoord = a_textureCoord;
vec4 position = u_matrix * vec4( u_topLeft + a_position * u_tileScale, 0.0, 1.0 );
gl_Position = snapToScreenPixel(position, u_resolution);
// gl_Position = u_snapGrid ? snapToScreenPixel(position, u_resolution) : position;
highp vec4 position = u_matrix * vec4( u_topLeft + a_position * u_tileScale, 0.0, 1.0 );
gl_Position = position;
// gl_Position = u_fixedView ? snapToScreenPixel(position, u_resolution) : position;
}

0 comments on commit 607e937

Please sign in to comment.