From e3d21a313f2b9a76e1bae078d7ced261d6de46a9 Mon Sep 17 00:00:00 2001 From: Adam Foflonker <87928802+DnA-IntRicate@users.noreply.github.com> Date: Sat, 31 Jan 2026 08:46:00 +0200 Subject: [PATCH 1/3] Hero render at half-res on mobile --- content/javascripts/hero.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/content/javascripts/hero.js b/content/javascripts/hero.js index b7bce89..8c7ce94 100644 --- a/content/javascripts/hero.js +++ b/content/javascripts/hero.js @@ -87,6 +87,8 @@ const iResolutionLoc = gl.getUniformLocation(program, "iResolution"); const iTimeLoc = gl.getUniformLocation(program, "iTime"); + const isMobile = window.matchMedia("(pointer: coarse)").matches && !window.matchMedia("(hover: hover)").matches; + // Render loop function render(time) { @@ -98,8 +100,10 @@ if ((canvas.width !== displayWidth) || (canvas.height !== displayHeight)) { - canvas.width = displayWidth; - canvas.height = displayHeight; + const scale = isMobile ? 0.5 : 1.0; // Render at half-res on mobile + canvas.width = displayWidth * scale; + canvas.height = displayHeight * scale; + gl.viewport(0, 0, canvas.width, canvas.height); } From 93535594cb3fde697a5402895c89a278cb7ad05b Mon Sep 17 00:00:00 2001 From: Adam Foflonker <87928802+DnA-IntRicate@users.noreply.github.com> Date: Sat, 31 Jan 2026 09:00:37 +0200 Subject: [PATCH 2/3] FPS limiting Limit to 60 FPS on desktop & 30 FPS on mobile --- content/javascripts/hero.js | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/content/javascripts/hero.js b/content/javascripts/hero.js index 8c7ce94..cdc4523 100644 --- a/content/javascripts/hero.js +++ b/content/javascripts/hero.js @@ -89,7 +89,26 @@ const isMobile = window.matchMedia("(pointer: coarse)").matches && !window.matchMedia("(hover: hover)").matches; + const targetMobileDeltaTime = 33.33; // 33.33ms ~ 30 FPS + const targetDesktopDeltaTime = 16.67; // 16.67ms ~ 60 FPS + let lastFrameTime = 0; + // Render loop + function frame(time) + { + // Lock framerate to 30 FPS on mobile, and 60 FPS for desktop + const targetDeltaTime = isMobile ? targetMobileDeltaTime : targetDesktopDeltaTime; + + // Framerate limiting + if ((time - lastFrameTime) >= targetDeltaTime) + { + lastFrameTime = time; + render(time); + } + + requestAnimationFrame(frame); + } + function render(time) { // Resize handling (High-DPI / Retina aware) @@ -111,9 +130,8 @@ gl.uniform1f(iTimeLoc, time * 0.001); // Convert time to seconds gl.drawArrays(gl.TRIANGLES, 0, 6); - requestAnimationFrame(render); } // Start the render loop - requestAnimationFrame(render); + requestAnimationFrame(frame); })(); From 032af6b8fd98b1d23832c484ebc50b3e7f4576f9 Mon Sep 17 00:00:00 2001 From: Adam Foflonker <87928802+DnA-IntRicate@users.noreply.github.com> Date: Sat, 31 Jan 2026 09:46:47 +0200 Subject: [PATCH 3/3] Determine render resolution based on first frame delta time --- content/javascripts/hero.js | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/content/javascripts/hero.js b/content/javascripts/hero.js index cdc4523..b33ba22 100644 --- a/content/javascripts/hero.js +++ b/content/javascripts/hero.js @@ -1,6 +1,7 @@ /** * This script applies to index.md. */ +"use strict"; (async () => { // DOM guard // if (!document.querySelector(".hero-page")) @@ -88,10 +89,27 @@ const iTimeLoc = gl.getUniformLocation(program, "iTime"); const isMobile = window.matchMedia("(pointer: coarse)").matches && !window.matchMedia("(hover: hover)").matches; - const targetMobileDeltaTime = 33.33; // 33.33ms ~ 30 FPS const targetDesktopDeltaTime = 16.67; // 16.67ms ~ 60 FPS + let lastFrameTime = 0; + let renderQuality = 1.0; // Full desktop quality by default + + function determineBestRenderQuality() + { + const start = performance.now(); + render(0.0) + const deltaTime = performance.now() - start; + + if (deltaTime > 16) + renderQuality = 0.4; // Low quality, 40% resolution + else if (deltaTime > 8) + renderQuality = 0.7; // Medium quality, 70% resolution + else + renderQuality = 1.0; // High quality, full resolution + + console.log("Using render quality: %f", renderQuality); + } // Render loop function frame(time) @@ -113,25 +131,24 @@ { // Resize handling (High-DPI / Retina aware) const dpr = Math.min(window.devicePixelRatio || 1, 1.25); // Clamp resolution on mobile - const displayWidth = Math.floor(canvas.clientWidth * dpr); const displayHeight = Math.floor(canvas.clientHeight * dpr); - if ((canvas.width !== displayWidth) || (canvas.height !== displayHeight)) - { - const scale = isMobile ? 0.5 : 1.0; // Render at half-res on mobile - canvas.width = displayWidth * scale; - canvas.height = displayHeight * scale; - - gl.viewport(0, 0, canvas.width, canvas.height); - } + // NOTE: Previously, this was conditionally resized based on: + // if ((canvas.width !== displayWidth) || (canvas.height !== displayHeight)) + // But we removed this to make renderQuality updates easier. This system doesn't need anymore complexity! + canvas.width = displayWidth * renderQuality; + canvas.height = displayHeight * renderQuality; + gl.viewport(0, 0, canvas.width, canvas.height); gl.uniform3f(iResolutionLoc, canvas.width, canvas.height, 1.0); gl.uniform1f(iTimeLoc, time * 0.001); // Convert time to seconds gl.drawArrays(gl.TRIANGLES, 0, 6); } + determineBestRenderQuality(); + // Start the render loop requestAnimationFrame(frame); })();