· Hasan Alp Güngör
How I turned my logo into 3D glass that breaks apart as you scroll
What went into the glass logo on my portfolio: tracing the logo, splitting it into seven pieces, getting the glass to work and keeping it smooth on weak phones.
- Three.js
- React Three Fiber
- GSAP
- GLSL

My portfolio started with a 3D game controller. Then I decided to use my own logo instead, and I wanted this: when the page opens the logo is intact, as you scroll it first cracks, then breaks apart, and every piece shows one of my skills. This post is about how I built that.
1. From an image to a shape
All I had was an image of the logo, and 3D needs corner points. I turned the image black and white with OpenCV, traced its contours, simplified away the extra points and scaled everything to 2.6 units tall. What was left was one outer outline and the eight holes inside the logo.
Cutting the logo with straight lines looked fake, so I drew jagged "crack" lines and split the logo along them with shapely. That gave seven pieces that look actually broken: web, C# and Java, 3D, Python, game development, hardware and backend.
I gave each piece depth with three.js's ExtrudeGeometry and added a bevel to the edges. Those rounded edges are what catch the light in the glass effect.
2. Glass with nothing behind it
For the glass I used drei's MeshTransmissionMaterial, which fakes glass by bending the scene behind it. But there was a problem: the site's silver background isn't in the 3D scene, it's drawn with CSS. The 3D scene behind the logo was empty, so the glass had nothing to bend and looked like flat gray plastic.
My fix was to redraw a lookalike of the background with a shader. Every frame I hide the logo, draw that background into an off-screen buffer (an FBO), and hand the buffer to the material as what's behind it. Now the glass bends the silver light behind the page. On top of that I added a separate fresnel shader that makes the edges glow white.
3. The scroll story
I tied the logo's pose to the scroll position with GSAP ScrollTrigger. There are a few key poses (intact, cracked, exploded, turned) and scrolling moves between them. The labels on the pieces are plain HTML: every frame I project the piece's 3D position onto the screen and move the label there.
The most annoying bug showed up here: scrolling back to the very top made the logo disappear. The cause was setting the ScrollTrigger start to "top top". At scroll 0 the trigger wasn't considered active, and I stopped rendering while it was inactive. Changing the start to "top bottom" fixed it.
4. Weak phones
This glass effect is heavy, so when the site opens it looks at the device and picks one of three quality levels:
- High: the full glass effect at a sharper resolution
- Medium: for phones and devices with 4 GB of memory or less; the glass uses fewer samples
- Lite: when data saver is on or the device is very weak; a simple translucent material instead of the glass effect
In case that guess is wrong, after a few seconds the site starts watching the frame rate, and if it stays under 30 frames per second it steps down a level on its own.
tsfunction detect(): Quality {
const nav = navigator as Navigator & { deviceMemory?: number; connection?: { saveData?: boolean } };
const memory = nav.deviceMemory ?? 8;
const cores = nav.hardwareConcurrency ?? 8;
if (nav.connection?.saveData || memory <= 2 || cores <= 2) return 'lite';
if (matchMedia('(pointer: coarse)').matches || memory <= 4 || cores <= 4) return 'medium';
return 'high';
}5. Glass that ripples under the cursor
Finally, I wanted the glass to ripple when the cursor is over the logo. I cast a ray from the pointer and check whether it hits the logo. If it does, I push the coordinates around the cursor with a sine wave in the background shader. Since the glass refracts that warped background, the ripple shows up inside the glass.
glslvec2 toMouse = (uv - uMouse) * vec2(uAspect, 1.0);
float dist = length(toMouse);
float wave = sin(dist * 70.0 - uTime * 7.0) * exp(-dist * 7.0) * uHover;
uv += normalize(toMouse + 1e-5) * wave * 0.03;To see the result, just open the home page and scroll down. All the code is open on GitHub.

