This commit is contained in:
evanpelle
2026-06-02 19:52:56 -07:00
parent 9413642952
commit a1eccc8bcf
5 changed files with 22 additions and 7 deletions
+2 -1
View File
@@ -79,6 +79,7 @@ import {
import { ALL_UNIT_TYPES, UnitState } from "./render/types";
import { SoundManager } from "./sound/SoundManager";
import { themeProvider } from "./theme/ThemeProvider";
import { getEffectiveDpr } from "./utilities/Dpr";
export interface LobbyConfig {
cosmetics: PlayerCosmeticRefs;
@@ -344,7 +345,7 @@ function mountWebGLFrameLoop(
const syncCamera = (): void => {
const scale = transformHandler.scale;
const dpr = window.devicePixelRatio || 1;
const dpr = getEffectiveDpr();
const centerX =
transformHandler.offsetX +
mapWidth / 2 +
+5 -3
View File
@@ -1,3 +1,5 @@
import { getEffectiveDpr } from "../../utilities/Dpr";
/**
* 2D camera: pan/zoom → column-major mat3 for WebGL2 vertex shaders.
*
@@ -44,7 +46,7 @@ export class Camera {
/** Update canvas pixel dimensions. Triggers initial fitMap on first call. */
resize(cssWidth: number, cssHeight: number): void {
const dpr = window.devicePixelRatio || 1;
const dpr = getEffectiveDpr();
this.canvasW = Math.round(cssWidth * dpr);
this.canvasH = Math.round(cssHeight * dpr);
if (this.needsInitialFit) {
@@ -163,7 +165,7 @@ export class Camera {
/** Convert screen pixel position to world coordinates. */
screenToWorld(screenX: number, screenY: number): { x: number; y: number } {
const dpr = window.devicePixelRatio || 1;
const dpr = getEffectiveDpr();
const ndcX = ((screenX * dpr) / this.canvasW) * 2 - 1;
const ndcY = -(((screenY * dpr) / this.canvasH) * 2 - 1);
const sx = (this.zoom * 2) / this.canvasW;
@@ -176,7 +178,7 @@ export class Camera {
/** Convert world coordinates to screen pixel position (CSS pixels). */
worldToScreen(worldX: number, worldY: number): { x: number; y: number } {
const dpr = window.devicePixelRatio || 1;
const dpr = getEffectiveDpr();
return {
x: (this.zoom * (worldX - this.offsetX)) / dpr + this.canvasW / (2 * dpr),
y: (this.zoom * (worldY - this.offsetY)) / dpr + this.canvasH / (2 * dpr),
+2 -1
View File
@@ -10,6 +10,7 @@
*/
import type { Config } from "../../../core/configuration/Config";
import { getEffectiveDpr } from "../../utilities/Dpr";
import type {
AttackRingInput,
BonusEvent,
@@ -544,7 +545,7 @@ export class GPURenderer {
// ---------------------------------------------------------------------------
resize(cssWidth: number, cssHeight: number): void {
const dpr = window.devicePixelRatio || 1;
const dpr = getEffectiveDpr();
this.canvas.width = Math.round(cssWidth * dpr);
this.canvas.height = Math.round(cssHeight * dpr);
this.camera.resize(cssWidth, cssHeight);
@@ -22,6 +22,7 @@ import iconVertSrc from "../shaders/radial-menu/icon.vert.glsl?raw";
import emojiAtlasMeta from "resources/atlases/emoji-atlas-meta.json";
import { assetUrl } from "src/core/AssetUrls";
import { getEffectiveDpr } from "../../../utilities/Dpr";
const emojiAtlasUrl = assetUrl("atlases/emoji-atlas.png");
@@ -437,7 +438,7 @@ export class RadialMenuPass {
if (this.items.length === 0 && !this.centerItem) return;
const gl = this.gl;
const dpr = window.devicePixelRatio || 1;
const dpr = getEffectiveDpr();
const vw = gl.drawingBufferWidth;
const vh = gl.drawingBufferHeight;
const ax = this.anchorX * dpr;
@@ -491,7 +492,7 @@ export class RadialMenuPass {
centerHovered: boolean,
): void {
const gl = this.gl;
const dpr = window.devicePixelRatio || 1;
const dpr = getEffectiveDpr();
const n = items.length;
const hasCenter = centerItem !== null;
const outerR = cfg.outerR * dpr;
+10
View File
@@ -0,0 +1,10 @@
// Cap the effective devicePixelRatio used for the WebGL drawing buffer and
// any pixel-aware HUD math. Above 1.5×, low-end integrated GPU compositors
// (notably older Chromebooks) can't swap the drawing buffer within a vsync
// interval and frame pacing collapses. All callers must agree on this value
// or camera ↔ screen coordinate math will desync.
const MAX_RENDER_DPR = 1.5;
export function getEffectiveDpr(): number {
return Math.min(window.devicePixelRatio || 1, MAX_RENDER_DPR);
}