惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Jina AI
Jina AI
MyScale Blog
MyScale Blog
量子位
月光博客
月光博客
J
Java Code Geeks
A
About on SuperTechFans
H
Hackread – Cybersecurity News, Data Breaches, AI and More
U
Unit 42
WordPress大学
WordPress大学
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
腾讯CDC
G
Google Developers Blog
博客园 - 【当耐特】
Engineering at Meta
Engineering at Meta
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
宝玉的分享
宝玉的分享
IT之家
IT之家
N
Netflix TechBlog - Medium
Microsoft Security Blog
Microsoft Security Blog
博客园 - 叶小钗
B
Blog
Martin Fowler
Martin Fowler
P
Proofpoint News Feed
B
Blog RSS Feed

Codrops

Drawing With Light: An Exploration of Lit GPU Tubes with TSL and WebGPU | Codrops Building a Real-Time 3D Face Mask with MediaPipe, Threlte and Three.js | Codrops Building an Infinite Loom: Unravelling Images into Threads with Three.js | Codrops Beyond the Luminance Ramp: A Shape-Aware ASCII Renderer in Three.js | Codrops More Three.js Speakers, More Ideas from Paris | Codrops Breaking the Frame: Building a Real-Time Datamosh Effect with Three.js | Codrops Bend, Aim, Fling: Turning the Eiffel Tower into a Catapult with Three.js | Codrops Volatile Nexus: Tinkering with Glass, Caustics, Cubes and Sound in Three.js | Codrops Goodgrowth: Boot Sequences, Spinning Discs, and the Art of the Portfolio | Codrops Building a Mouse-Following Square Lens Effect with Three.js and GLSL | Codrops Blender to Three.js and Back: 10 Tips for a Better Workflow | Codrops Sixty Frames for the Record: A Three.js Game, Seven Fly-Throughs, and a Wall of CRTs | Codrops Run Rob Run: Building a Music-Reactive Goo with Three.js and WebGPU | Codrops Relighting Images with Depth Maps and Three.js | Codrops Building an Animated Testimonial Hero Using the GSAP Timeline and Dynamic CMS Data | Codrops Creativity at Enterprise-Scale, Without Compromise: The OFF+BRAND. Story | Codrops Inside HAOQI.DESIGN: Letting DOM and WebGL Share a Retro-Futurist Stage | Codrops From Motion to Meaning: Denis Avramenko’s Approach to Interactive Design | Codrops Creating an Interactive 3D Cluster with Three.js, TSL and Three Start | Codrops Exploring Procedural Geometry with Three.js and WebGPU | Codrops From Brand Systems to Cultural Worlds: Inside Antinomy and 27b | Codrops Designing a Flexible Digital Archive for Chems.Studio’s Creative Practice | Codrops The Department Is Open: Building the PX PUSH Website | Codrops Garden Anomaly: A Tiny WebGPU and TSL Experiment | Codrops A Canvas for Individuality: Creating Websites That Feel Unmistakably Human with Readymag | Codrops Building an Endless Interactive Glass Xylophone with Three.js | Codrops The Story Is in the Interaction: Bonhomme’s Digital Experiences for Luxury Brands | Codrops Building an Infinite GSAP Scroll Gallery with Parallax and Flip Transitions | Codrops Studio Freight: Moving Missions Forward | Codrops Between Print and Digital: The Making of MERSI’s Website | Codrops
From Rays to Meshes: Building Vercel’s Prism with vgpu | ...
By Matias Gonzalez Fernandez · 2026-09-04 · via Codrops

A look at how Vercel’s vgpu creates a performant prism effect using shaders, geometry, glass, and adaptive rendering.

3D glsl WebGL

vgpu is the open-source library we built at Vercel to create performant shaders for the web. After months of using it internally, we were finally getting ready to release it. We had the library. We had the landing page. But one important piece was still missing.

One week before launch, the vgpu landing page was still missing its hero. The team suggested bringing back an iconic Vercel visual: the glass prism splitting light into red, green, and blue.

I first saw the prism at Next.js Conf 2022, before I joined Vercel. It completely blew my mind. Now it was time to build my own version and somehow make it live up to the original.

I started with the most literal approach: simulating the physics of light. For every pixel on the wall, I cast rays backward through the prism and checked whether they reached the light source. Each successful ray contributed color to that pixel. To keep the shader manageable, I used only 16 samples, jittering them on every frame and accumulating the results over time.

This was quite expensive and didn’t look sharp, so I kept studying the effect. I asked GPT to draw an SVG of the effect to explain to me how it worked, and it did this:

Seeing the light spread outward in straight lines gave me an idea: I could draw it as a 3D mesh. A mesh is a group of points connected to form a surface. By placing those points along the light’s edges, I could draw the whole beam as a set of shapes.

First, I calculated how each wavelength would refract as it entered and exited the prism. Because the prism bends each wavelength by a slightly different amount, the paths spread into a fan of colors. I represented those paths as lines, producing this first wireframe:

At this point, these were still only lines; they had no surface for the GPU to shade. To turn them into a visible beam, I connected neighboring paths to form the triangular faces of a mesh, generating a much smoother (and cheaper) result.

With the light mesh working, the scene was still missing something: the glass! Luckily, I had already built a glass shader for the eve.dev hero that I could adapt.

The shader uses an environment map to capture the surroundings of the glass. Imagine placing a camera at the center of the scene and taking six pictures, one in each direction. Together, those images form a cubemap: a 360° representation of the environment.

With this technique, you can easily fake reflections from an environment.

With the glass shader in place, I added bloom and floating particles to complete the dark-mode scene:

Now it was time to work on light mode. Light mode is always a challenge; adding light to a white background doesn’t make sense (unless you go HDR, and Twitter will roast you for that). So the solution is to darken the background, leaving room for “light” to show up.

I started by generating some concepts with GPT, eventually creating this AI-generated image:

Once I had the concept, I started working backward from the final image. I broke it into individual elements and figured out how to recreate each one in the scene.

For example, the wall has light and shadows coming through a window. It also has a subtle texture that makes it feel like a real wall. The prism casts a shadow and has subtle shading inside it.

Since this was a really complex composition, I created a visualizer for the render pipeline. You can think of creating a shader as mixing a bunch of images/math together, so a graph like this helped me understand how I was “mixing the things”.

Let’s break this down:

The prism casts a shadow. My first thought was to calculate a real-time shadow, but that can get expensive; since the prism doesn’t really move, we could draw the shadow by pasting a texture onto the wall.

Next, I focused on the wall details. In the concept image we can see small “bumps” in the wall. We can achieve this effect by generating a normal map.

A key performance optimization was to render the normal map to a static image, so the expensive noise calculation only runs once at startup.

The node has a control to edit the strength of the normal map, allowing me to set it exactly as I wanted.

Then I added shadows to the wall by layering an AI-generated image over the lighting information. The controls let me fine-tune its appearance.

Together, these assets resulted in the hero we see today.

You can access the debug mode at https://vgpu.sh?debug. If you switch between light/dark mode and high/low quality, you’ll see the graph change.

Adapting to each device

Even with these optimizations, the hero was still too demanding for some devices. To address this, I built lighter versions of both shaders. They use fewer samples and less detail while keeping the overall effect visually similar.

The rule is simple: start at high quality, then switch to low quality when necessary. The system uses three signals to decide:

  • GPU tier: If the device has a low-tier GPU or is a mobile device, the hero starts in low-quality mode.
  • Battery level: If a laptop has less than 30% battery and is not charging, the hero switches to low-quality mode to reduce power usage.
  • Frame rate: If the device cannot maintain a stable frame rate, the hero switches to low-quality mode.

This lets more powerful devices render the full effect while keeping the experience smooth everywhere else.

In the end, building a hero like this is all smoke and mirrors. It is about balancing performance and perception. It does not need to simulate reality perfectly. It just needs to look convincing and run smoothly.

The code for this hero, along with other examples, is available in the vgpu GitHub repository.

Matias Gonzalez Fernandez

Matias is a graphic designer that shifted into web development. He works as tech lead at basement studio where he blends knowledge from design and development to help creating immersive experiences. He’s always trying to find room to play and experiment with new technologies, currently obsessed with WebGL.

Creative Spotlights

Inside the journeys and portfolios of today's most inspiring designers and developers.

Studio Stories

Discover how studios & agencies started, how they work, and what they've built.

Case Studies

Discover the ideas, design, and craft behind today’s most inspiring web experiences.