return to table of content

So you think you know box shadows?

sunnyps
23 replies
1d1h

However, using a transparent color significantly slowed down the number that can be drawn too which doesn't make as much sense to me. I'd imagine that with hardware today transparency should be somewhat free.

That's because transparency limits how you can batch draws on the GPU. With opaque draws, you can use the depth buffer and draw in any order you like e.g. maximizing batching. With transparency, you need to draw things in the right order for blending to work (painters order).

dmazzoni
9 replies
18h25m

I think it's more complex than that. While web browsers do use GPU rendering, they're not game engines. They don't draw every single object on the screen every frame, that could easily cause lag on a large complex page.

Chromium in particular tries to minimize the total number of layers. It renders each layer into a pixel map, then for each frame it composites all of the visible layers into the final image.

That works really well in practice because you often have lots of layers that move around but don't actually change their pixels. So those don't need to be rendered (rasterized) every frame, just composited.

If you have a bunch of box shadows without transparency, Chromium will rasterize the whole thing once as a single layer.

If you have a bunch of box shadows with transparency, Chromium might create a separate layer for each one. That's probably suboptimal in this particular case, but imagine if your partially transparent box shadows had to also slide around the page independently.

forrestthewoods
8 replies
18h22m

They don't draw every single object on the screen every frame, that could easily cause lag on a large complex page.

Games draw every single object on the screen every frame. They don't lag, quite the opposite in fact!

eru
3 replies
14h50m

In fact that exact line of thinking was behind an effort to rewrite Firefox's rendering to be more like a game engine, a few years ago.

Not sure where that went in the end.

DaoVeles
1 replies
14h39m

That sounds like something from the shuttered Servo team. At least they rose like a phoenix - https://servo.org/

eru
0 replies
12h58m

Yes, that sounds about right! I remember a series of very interesting blog posts by them.

TazeTSchnitzel
0 replies
9h49m

It's called WebRender and it shipped in Firefox.

kalleboo
2 replies
14h11m

Games are expected to have sole access to your machine, so if they use all the CPU/GPU resources, nobody cares. If my web browser was burning up my battery re-rendering the page 90 times a second, I'd be livid.

forrestthewoods
0 replies
14h1m

I think “consumes too much resources” is a valid concern. But I think “could cause lag because too many objects” is totally bogus. Rendering a web page isn’t that complicated.

eru
0 replies
12h56m

Games are expected to have sole access to your machine, so if they use all the CPU/GPU resources, nobody cares. If my web browser was burning up my battery re-rendering the page 90 times a second, I'd be livid.

Games 20 years ago had sole access to machines that were much less powerful than even partial access to today's machines.

And eg Nintendo Switch games (or games on the Steam deck, or just mobile phone games) still deal with power limitations; people are very aware when their games burn through their batteries.

DaoVeles
0 replies
14h42m

I think the above was a simplification. GUI rendering is a good example of jack of all trades, master of none. It doesn't use tight render loops like game engines but it much more flexible in terms of UI possibilities.

There is also the issue that GPU's are oddly terrible at generating 2D elements of which a desktop has thousands of them. There are things like Glyph caching but they can only go so far.

Having the CPU doing the majority of the work with a few rasterization tasks to the GPU makes sense.

amelius
3 replies
1d1h

Can't you mathematically work out how to change the colors/opacity to rearrange the job?

Rapzid
1 replies
1d

Having that knowledge sounds just as expensive if the operations aren't commutative.

amelius
0 replies
23h37m

Yeah, somehow between comments I forgot this was about shadows and I was thinking more about drawing polygons. In that case, you can break up the polygons and work out the colors for each of the (theoretically 2^N) regions of overlap.

klysm
0 replies
1d

I think there’s still a dependency graph

Cloudef
3 replies
1d

GPUs also do not like overdraw, so it's generally good idea to avoid having many transparent elements on top of each other, its also the reason why drawing more triangles vs. transparent texture is generally better.

DaoVeles
2 replies
13h47m

My big take away with the whole City Skylines 2 performance issue and the lack of LOD was that geometry processing is so cheap nowadays. So long as you aren't too reckless with geometry in terms of sub-pixel rendering, you don't really have to worry about it too much any more.

It isn't like the Ps2 era when geometry time was a real concern on render times. Even a modern low end GPU could process a few hundred million polygons a second without sweating it, now getting the result son screen is a very different issue.

Cloudef
1 replies
12h55m

PS2 is kind of exception as it was a fill rate monster, and still even to this day is pretty impressive piece of engineering. (Mesh shaders say hi)

spookie
0 replies
5h24m

Yeah, PS2's Graphics Synthesizer had a fill rate of 1.2 GB/s. For comparison, the OG Xbox had 0.932 GB/s, and the GameCube had 0.648GB/s. Assuming only 1 texture here.

The Xbox was released 1 year later, for context.

Sony also demo'd the GSCube once, it had 16 Graphics Synthesizers, achieving a fill rate of 37.7 GB/s (no textures, half that with 1... I think). Eventually they ditched the idea in favour of Nvidia's solution.

o11c
2 replies
22h5m

Reverse-painter's-order beats painter's-order since it lets you skip fully-occluded objects:

  Start with a buffer that's fully transparent (α=0.0)
  for each face from front to back:
    for each pixel of the face:
      draw the pixel, blending 1.0-buffer.α of the new pixel into whatever's already in the buffer
      (if buffer.α == 1.0 you can just skip it entirely, just like for depth buffering)
  go back and double check your math relating to transparent objects behind other transparent objects
The tricky part is if you have faces that overlap in a cycle (can happen legitimately), or that penetrate each other (often avoidable if you think about it).

mabster
1 replies
19h43m

The game engines I've dealt with separate opaque and transparent geometry.

It is generally good to render opaque geometry back to front to reduce overdraw, but not going so far as sorting the objects. We would do stuff like render the hands first in an FPS or render the skybox last in most games.

Now for the transparent layer: First occlusion is handled by the z-buffer as usual. If you render from front to back I assume you render to another buffer first and then composite to the framebuffer? If you render from back to front you don't need alpha in your framebuffer and can assume each rendered pixel is opaque, not needing that composite.

There's also order independent transparency stuff though which IIRC does need another buffer, which requires a composite but then saves you having to sort the objects.

DaoVeles
0 replies
14h29m

I could be wrong, but I remember folks that worked on Dreamcast games that loved how you could just throw the geometry at it in any old fashion you liked and the GPU would just sort it all out as needed. Transparencies and all.

p_l
0 replies
10h55m

One more thing to consider is memory bandwidth, which can be limiting factor especially on mobile devices.

A non-transparent draw over another draw allows in best case to cull all overlapping drawing operations, in worst case means you only have to use as much bandwidth as the individual draws.

With transparency, especially if you can't somehow combine the operations together (from my understanding, very hard problem), it means you also need to read back the entire region you're overlapping with transparency - so every transparent draw involves at least twice the final framebuffer size bitmap going-over memory bus.

Now consider that many mobile devices had not enough memory bandwidth to do a full redraw (i.e. blit the full framebuffer image twice) of the screen in time to maintain 60fps and it becomes a considerable problem.

delusional
0 replies
22h31m

The "Ordering" step doesn't really matter that much. You're usually doing a sort anyway prior to submitting the drawcall. What hurts is the overdraw. If you're doing opaque rendering, you get to render front to back, rendering only what actually appears on the final framebuffer. The number of pixels (after the depth pass) is proportional to the framebuffer. When you're doing transparent rendering you render back to front, and you have to render a tonne of the scene that will eventually be (partially) obscured by other random polys. We call that overdraw. The amount of pixels through the shader pipeline balloons to be proportional to the size of your mesh.

If you're doing non-overlapping stuff, you'd actually expect (almost) no slowdown from transparency, since you'd have to touch every pixel once anyway, and the only thing that changed is the shader formula.

cchance
16 replies
1d3h

He said it might melt your processor... but on a macbook m3 in arc runs great, like every one of those was amazing.

layer8
3 replies
1d1h

M4 iPad Pro here started to freeze up on the Starry Night animation.

qingcharles
2 replies
1d1h

Weird. I'm on a 2011 Lenovo desktop with an i5 and it ran smooth as butter.

layer8
1 replies
1d1h

Probably Safari is at fault.

kalleboo
0 replies
13h59m

Yeah it was a slideshow in Safari on Mac, butter smooth in Chrome

magnio
1 replies
1d2h

Maybe the author tests it on some old device with outdated graphics driver, because they all run smoothly on my 5 yo Android.

tetris11
0 replies
1d1h

Chiming in with my Samsung J3 2016, it ran pretty well here too

dahart
1 replies
1d2h

On Safari iPad, I lose the ability to scroll or do anything somewhere in the middle of the article.

labster
0 replies
1d1h

Huh, I read the whole article and interacted with all the inline examples on my iPhone SE/2.

callwhendone
1 replies
1d

M1 Pro here and it ran completely fine.

llama_drama
0 replies
1d

That's weird because it completely freezes m2 ipad

tux3
0 replies
1d2h

Even on a 7 year old first gen AMD, it's smooth as butter. Looks like Stylo and Webrender doing a great job?

sweca
0 replies
1d1h

Worked very well on my Pixel 7 in Chrome too

sorrythanks
0 replies
22h44m

Firefox on an m2 has taken the news of these bouncing balls extremely poorly

mavamaarten
0 replies
1d

I ran it on my Pixel 7A and even the ray tracing demos ran insanely quickly. I seriously did not expect that.

jimmaswell
0 replies
1d1h

All the examples were good on my Samsung S22 Ultra too, really cool.

chuckadams
0 replies
1d2h

It's butter on my M1 Air too, in Chrome and Firefox. Surprisingly, it's a slideshow on Safari.

ctippett
10 replies
1d1h

I'm embarrassed to admit it took until the final paragraph before realising that 'gypity' is a reference to Chat GPT.

noqc
2 replies
1d

I took until here.

fitsumbelay
1 replies
1d

same

p0seidon
0 replies
22h37m

same

zarathustreal
1 replies
1d

Hmm.. I must be even further out of the loop than you, why would that be embarrassing?

hnbad
0 replies
8h20m

It isn't. They were being self-deprecating.

tracker1
1 replies
3h1m

Chad Gipity is a good guy... ;-)

tracker1
0 replies
2h50m

His significant other (Elle Elim) is pretty nice too.

krsdcbl
0 replies
20h15m

fun fact, this had me realise the term isn't some kind of in joke spawned of a colleague's mind, but actually a meme in the progess of becoming one

jbritton
0 replies
20h18m

Primeagen YouTube channel lingo.

gs17
0 replies
13h0m

Same, I thought it was some sort of tool related to gyp but for client side.

recursive
8 replies
1d

I'm totally down for some good old fashioned impractical hacking. But just remember, we already have canvas, which can do all this easier, faster, and better.

klysm
3 replies
1d

Canvas throws away a lot though, especially w accessibility

tkzed49
1 replies
20h48m

now I'm imagining a screen reader reading off the coordinates of 1000 box shadows

recursive
0 replies
17h48m

You could probably get it to png encode a canvas and then read it in hex too.

recursive
0 replies
23h29m

Really? I would have guessed that canvas provides pretty much exactly the same accessibility as a UI rendered entirely out of box shadows.

dmazzoni
1 replies
17h57m

Canvas is better...if you're trying to do something that stays within a fixed-size box.

kroltan
0 replies
2h59m

Canvas would still be faster even if you used a full-screen box. Just the string concatenation overhead of doing this with box-shadows is insanely wasteful.

Which isn't to demerit the hackish creativity of taking one thing and running with it! But if you wanted to do a ball painting effect like that outside this "what if" context, it would be technically irresponsible to do it with box-shadows.

hnbad
0 replies
8h18m

Sure, and we already have keyboards, so there's no need to use floppy drives or rubber chickens to make music either.

egypturnash
0 replies
1d

But with less comedic value. Doing this with nothing but box-shadow is funny, mostly because it is so impractical.

yesimahuman
3 replies
1d1h

It also turns out that some smart people figured out maths hacks to draw rounded boxes for super cheap which UI peeps love because with this hack boxes can be so round as to appear as circles

Any references to learn more about these hacks?

pmhpereira
0 replies
1d

Probably signed distance fields (SDF).

paulirish
3 replies
1d3h

Seriously fun exploration.

Layering. That is an important word.

Layering is also the key to the (silly but also sometimes good-looking) effects from my text shadow project from 14yrs ago: https://paulirish.github.io/mothereffingtextshadow/

rustystump
1 replies
1d

<3

sufehmi
0 replies
14h30m

Was confused because everything moved in 2 seconds per frame on M2 Firefox.

Switched to Chrome - suddenly everything is butter smooth.

Congrats on an article very well done!

breck
0 replies
19h0m

Layering. That is an important word.

It's almost like this post has many layers to it, and that it's not really about box shadows.

kristopolous
3 replies
21h55m

For the past 30 years I got good at programming but never really did graphics because I didn't like games. I now view it as a massive oversight and have been trying to catch up for over a year.

So hard.

hackit2
2 replies
18h5m

I did games first, then switched over to crud or simple oracle form programming. I tripled my original game programmer wage overnight.

kristopolous
0 replies
7h18m

Most of this is about the not-so-much-anymore-exotic art of GPU programming. It's becoming important in so many fields. The last thing I want to be is some foot-dragging old windbag who forgot to stay up to date.

eru
0 replies
14h46m

Well, games are seen as fun, so they can attract programmers even with low salaries.

Basically the same reason pet veterinaries and teachers and nurses and musicians and artists still attract plenty of candidates despite a comparatively low pay.

(Playing games is more fun than working with CRUD apps. But writing games and writing CRUD apps seem about equal in their probability distributions of fun.)

efilife
2 replies
18h3m

A great, possibly the greatest article I read this year ended with "your welcome" instead of "you're". Fix asap! Or maybe I didn't get the joke, that's a possibility

rustystump
1 replies
15h21m

nothing to see here...

efilife
0 replies
7h1m

I'm honored

develatio
2 replies
22h52m

dgerrells, please add RSS support to your blog!

rustystump
1 replies
20h34m

Done. Let me know if it works.

develatio
0 replies
8h36m

Sorry for the late reply. I just tried and it works perfectly! Thank you so much!

tracker1
1 replies
3h3m

Looking at the music visualizations was definitely cool. Really miss the old winamp days when you could play music and just run the visualizer full screen. I wish that streaming audio players did this today.

valbu
0 replies
1h37m

Still use Winamp (actually WACUP) with Milkdrop visualizations almost every day. But true that streaming audio players are so basic featureless pieces of software.

merceranthony78
1 replies
1d3h

Amazing. Is it possible to tell how much lag these would cause if used on a production website?

notpushkin
0 replies
14h37m

A lot. Please don't do this in production.

ulf-77723
0 replies
23h41m

Really great work, especially the music synced animation - could as well also be projected in an electro club

tompetry
0 replies
17h22m

This was awesome

theturtle32
0 replies
16h54m

THIS IS ABSOLUTELY EPIC, AND MY FAVORITE KIND OF WEB TECH DEEP DIVE! <3 <3 <3

pfannkuchen
0 replies
21h26m

Solid watch for rolling rocks energy.

nimish
0 replies
23h10m

Full color RGB flip dot display!

mediumsmart
0 replies
1h4m

I know not to use them without much thinking involved.

coding123
0 replies
17h58m

As usual, when will we get Quake or Doom ray-trace rendered using box shadow?

butz
0 replies
1d

But at the end of the day Firefox and Chrome are still rendering 1px box-shadow differently at 150% browser zoom. Best hopes for Baseline 2025.

anymouse123456
0 replies
5h44m

I love this kind of content. It reminds me of the early aughts when folks were doing a lot more of this stuff for fun.

akira2501
0 replies
17h30m

Instead of animating the color balls to music, it'd be nice if my manipulations of the color balls _created_ music.

adrianpluis
0 replies
1d3h

Well done with writing your experience.

SuaveSteve
0 replies
3h8m

So you think you know ((CSS FEATURE))?

Why would I know it? It's CSS!