<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/inside-haoqi-design-letting-dom-and-webgl-share-a-retro-futurist-stage-onvg2vzkk" -->

---
title: Inside HAOQI.DESIGN: Letting DOM and WebGL Share a...
description: A design engineer breaks down the technical build of their personal portfolio site, HAOQI.DESIGN, which blends DOM-based layout with WebGL effects in a...
canonical: https://daily.dev/posts/inside-haoqi-design-letting-dom-and-webgl-share-a-retro-futurist-stage-onvg2vzkk
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Inside HAOQI.DESIGN: Letting DOM and WebGL Share a Retro-Futurist Stage | daily.dev
og:description: A design engineer breaks down the technical build of their personal portfolio site, HAOQI.DESIGN, which blends DOM-based layout with WebGL effects in a...
og:url: https://daily.dev/posts/inside-haoqi-design-letting-dom-and-webgl-share-a-retro-futurist-stage-onvg2vzkk
og:image: https://api.daily.dev/og/posts/oNvg2VzkK.png
og:image:alt: Inside HAOQI.DESIGN: Letting DOM and WebGL Share a Retro-Futurist Stage
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Inside HAOQI.DESIGN: Letting DOM and WebGL Share a Retro-Futurist Stage

**[Codrops](https://daily.dev/sources/codrops)** · 24 min read · 1 upvotes · 0 comments

## Summary

A design engineer breaks down the technical build of their personal portfolio site, HAOQI.DESIGN, which blends DOM-based layout with WebGL effects in a retro-futurist visual style. Key topics include synchronizing Lenis smooth scroll with Three.js/R3F render loops via a shared ScrollBus, mirroring DOM grid layouts into WebGL meshes for hover-reveal image transitions, building a glass shader with refraction, chromatic dispersion, and Beer-Lambert-inspired tinting for light/dark modes, using instanced meshes with a texture atlas for falling sticker particles, and adding a custom Star 6 lens-flare filter plus dot-matrix/character-scramble effects for cohesive interface feedback. The author notes AI assisted in learning shaders and Three.js but design judgment drove final decisions.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://tympanus.net/codrops/2026/08/15/inside-haoqi-design-letting-dom-and-webgl-share-a-retro-futurist-stage>

## Questions this post answers

### How do you fix the one-frame lag between Lenis smooth scroll and Three.js/React Three Fiber rendering?

The lag comes from Lenis and R3F each running their own requestAnimationFrame loop, so R3F sometimes reads scroll data before Lenis updates it for that frame. The fix is disabling Lenis's own raf loop, calling lenis.raf manually inside R3F's addEffect, and storing the resulting scroll value in a shared bus that every useFrame consumer reads from the same snapshot each frame.

_Anyone chasing scroll-sync jitter between libraries can find implementation patterns like this through daily.dev._

### How can WebGL effects stay aligned with elements positioned by CSS Grid?

A shared rectangle sampler caches each element's getBoundingClientRect() output, correcting positions by scroll delta every frame instead of re-measuring layout constantly; nearby cards refresh every frame while distant ones refresh once every 12 frames, staggered to avoid layout thrashing. The cached rectangle is written into a shader uniform (uRect) so a fullscreen mesh's UV coordinates align to the DOM placeholder without moving 3D geometry.

_Developers blending CSS layout with canvas rendering can track techniques like this on daily.dev while building hybrid DOM/WebGL interfaces._

### How do you make a glass shader look convincing in both light and dark themes?

For light backgrounds, tint color is derived from a Beer-Lambert-inspired transmittance formula, pow(tint, thickness), approximating how much color survives passing through glass. That same calculation looks too dim on dark backgrounds, so dark mode instead blends the tint using a Hard Light operation, with a uDark uniform mixing between the two approaches as an art-directed adjustment rather than a single physical model.

_Anyone tuning shader materials for theme-aware rendering can find shader breakdowns like this via daily.dev._

## Similar posts on daily.dev

- [WebGL for Designers: Creating Interactive, Shader-Driven Graphics Directly in the Browser](https://daily.dev/posts/webgl-for-designers-creating-interactive-shader-driven-graphics-directly-in-the-browser-tynmq00fd) · Codrops · 4 upvotes · 0 comments
- [When Community Becomes UI: Building the Website for the First Three.js Conference](https://daily.dev/posts/when-community-becomes-ui-building-the-website-for-the-first-three-js-conference-7wnsbhrf1) · Codrops · 1 upvotes · 0 comments
- [Hello, my name is Niels Leenheer](https://daily.dev/posts/hello-my-name-is-niels-leenheer-1kfzjqnuq) · Hacker News · 69 upvotes · 7 comments
- [Liquid Glass in the Browser – Frontend Masters Blog](https://daily.dev/posts/liquid-glass-in-the-browser-frontend-masters-blog-aeuunx3ok) · Frontend Masters · 2 upvotes · 0 comments

---

Tags: [#webdev](https://daily.dev/tags/webdev), [#game-development](https://daily.dev/tags/game-development), [#threejs](https://daily.dev/tags/threejs), [#creative-coding](https://daily.dev/tags/creative-coding), [#react-three-fiber](https://daily.dev/tags/react-three-fiber)

[View this post on daily.dev](https://daily.dev/posts/inside-haoqi-design-letting-dom-and-webgl-share-a-retro-futurist-stage-onvg2vzkk)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Inside HAOQI.DESIGN: Letting DOM and WebGL Share a Retro-Futurist Stage","url":"https://daily.dev/posts/inside-haoqi-design-letting-dom-and-webgl-share-a-retro-futurist-stage-onvg2vzkk","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/inside-haoqi-design-letting-dom-and-webgl-share-a-retro-futurist-stage-onvg2vzkk"},"datePublished":"2026-08-15T13:32:19.696Z","dateModified":"2026-09-14T06:43:06.209Z","description":"A design engineer breaks down the technical build of their personal portfolio site, HAOQI.DESIGN, which blends DOM-based layout with WebGL effects in a...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/7517257099070bf723e0daa091fbd8b8?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/7517257099070bf723e0daa091fbd8b8?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Codrops","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Codrops","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/codrops","url":"https://daily.dev/sources/codrops"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/inside-haoqi-design-letting-dom-and-webgl-share-a-retro-futurist-stage-onvg2vzkk","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":1},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"webdev,game-development,threejs,creative-coding,react-three-fiber","timeRequired":"PT24M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Codrops","item":"https://daily.dev/sources/codrops"},{"@type":"ListItem","position":3,"name":"Inside HAOQI.DESIGN: Letting DOM and WebGL Share a Retro-Futurist Stage"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/inside-haoqi-design-letting-dom-and-webgl-share-a-retro-futurist-stage-onvg2vzkk#faq","mainEntity":[{"@type":"Question","name":"How do you fix the one-frame lag between Lenis smooth scroll and Three.js/React Three Fiber rendering?","acceptedAnswer":{"@type":"Answer","text":"The lag comes from Lenis and R3F each running their own requestAnimationFrame loop, so R3F sometimes reads scroll data before Lenis updates it for that frame. The fix is disabling Lenis's own raf loop, calling lenis.raf manually inside R3F's addEffect, and storing the resulting scroll value in a shared bus that every useFrame consumer reads from the same snapshot each frame. Anyone chasing scroll-sync jitter between libraries can find implementation patterns like this through daily.dev."}},{"@type":"Question","name":"How can WebGL effects stay aligned with elements positioned by CSS Grid?","acceptedAnswer":{"@type":"Answer","text":"A shared rectangle sampler caches each element's getBoundingClientRect() output, correcting positions by scroll delta every frame instead of re-measuring layout constantly; nearby cards refresh every frame while distant ones refresh once every 12 frames, staggered to avoid layout thrashing. The cached rectangle is written into a shader uniform (uRect) so a fullscreen mesh's UV coordinates align to the DOM placeholder without moving 3D geometry. Developers blending CSS layout with canvas rendering can track techniques like this on daily.dev while building hybrid DOM/WebGL interfaces."}},{"@type":"Question","name":"How do you make a glass shader look convincing in both light and dark themes?","acceptedAnswer":{"@type":"Answer","text":"For light backgrounds, tint color is derived from a Beer-Lambert-inspired transmittance formula, pow(tint, thickness), approximating how much color survives passing through glass. That same calculation looks too dim on dark backgrounds, so dark mode instead blends the tint using a Hard Light operation, with a uDark uniform mixing between the two approaches as an art-directed adjustment rather than a single physical model. Anyone tuning shader materials for theme-aware rendering can find shader breakdowns like this via daily.dev."}}]}
```

