diff --git a/static/canvas-renderer.js b/static/canvas-renderer.js index 8999cbc..cfc5bb5 100644 --- a/static/canvas-renderer.js +++ b/static/canvas-renderer.js @@ -34,16 +34,25 @@ class CanvasRenderer extends HTMLElement { // Rendering #updateSize() { - this.canvas.width = this.clientWidth; - this.canvas.height = this.clientHeight; + let { width, height } = this.getBoundingClientRect(); + this.width = width; + this.height = height; + + // To properly handle DPI scaling, we want the canvas's layout size to be equal to that of + // its parent container, + this.style.width = `${width}px`; + this.style.height = `${height}px`; + this.canvas.width = width * window.devicePixelRatio; + this.canvas.height = height * window.devicePixelRatio; + // Rerender immediately after the canvas is resized, as its contents have now been invalidated. this.#render(); } getWindowSize() { return { - width: this.clientWidth, - height: this.clientHeight, + width: this.width, + height: this.height, }; } @@ -250,10 +259,15 @@ class CanvasRenderer extends HTMLElement { this.gl.useProgram(this.renderChunksProgram.id); - let translationX = this.canvas.width / 2 - this.viewport.panX * this.viewport.zoom; - let translationY = this.canvas.height / 2 - this.viewport.panY * this.viewport.zoom; + let translationX = this.width / 2 - this.viewport.panX * this.viewport.zoom; + let translationY = this.height / 2 - this.viewport.panY * this.viewport.zoom; let scale = this.viewport.zoom; + let dpiScale = window.devicePixelRatio; + translationX *= dpiScale; + translationY *= dpiScale; + scale *= dpiScale; + this.gl.uniformMatrix4fv( this.renderChunksProgram.u_projection, false, diff --git a/static/index.css b/static/index.css index b13f26b..0c5fddb 100644 --- a/static/index.css +++ b/static/index.css @@ -3,6 +3,16 @@ /* Main container layout */ +html { + /* Don't want any scrollbars to ruin our layout. + Technically this will cause jank in case the view _does_ scroll somehow, but that's less of + an annoying bug than browser layout triggering scrollbars and ruining the page size... + I'm not sure what caused the browser to show scrollbars when I switched my displays to 4k, + but it did, and I didn't like it. + CSS remains a mystery, as it always has. */ + overflow: hidden; +} + body { width: 100vw; height: 100vh; @@ -148,6 +158,11 @@ rkgk-canvas-renderer { & > canvas { display: block; + + /* Fill the parent, don't overflow it. + This is important because under HiDPI, the canvas's pixel size is larger than the layout size. */ + max-width: 100%; + max-height: 100%; } } @@ -360,6 +375,10 @@ rkgk-brush-preview { & > canvas { border-radius: 4px; + + /* The brush preview doesn't scale with DPI as easily as the canvas renderer does, + so instead we pixelate it. */ + image-rendering: pixelated; } &.error {