Max Liani

Max Liani

@maxliani.bsky.social

Tracing rays at NVIDIA. Former lighting artist, working on computer graphics rendering tech for all humans and robots alike. I mostly post stuff about light transport simulation, and my hobby project Workbench.

1.1K followers51 following607 posts

It's a rainy day, and I haven't done anything in a while. So, I coded some tiny transition animations on the Workbench manipulators. Low effort, kind of fun.

So apparently ChatGPT invites people to generate 80s pictures. I wasn’t one of the cool kids, so I thought this generated alternate take was fun enough to post.

I haven’t developer much lately, too busy at work. But perhaps I could post some light reading about some of the stuff I have done in the previous year… Anyone interested in how to design a good unit testing framework? One for lightweight white-box testing (my favorite style).

Max Liani reposted

TinyBVH has just been 𝘂𝗽𝗱𝗮𝘁𝗲𝗱 𝘁𝗼 𝟭.𝟴.𝟬. For CPU ray tracing, it is now the fastest option in most cases - Outperforming Intel Embree and Madmann91 for BVH build time and single-ray performance. On GPU, performance exceeds 4B rays per second - 4 rays per pixel at 4k/120Hz. github.com/jbikker/tiny...

People who bought SpaceX thinking what they bought is an aerospace company 🤦🏻‍♂️ What they got instead is a tiny share of xAI, and a minuscule one of aerospace sector.

Do they need to have tried and failed? To qualify, I mean… Does music education at school count? My literature teacher told me many times I will never write anything in my life. I guess the music teacher thought that too.

Yining Karl Li@yiningkarlli.bsky.social

Hey now, that's an unfair characterization, I never even tried to be a musician. Instead, I became a software engineer because I was bad at drawing.

Maybe I see this in rosy retrospection, but I feel that the work I did many years ago to create the Glimpse production renderer still feels to me the most insane project I ever started.

I always had some envy about people who can read books, novels before going to sleep. If I read something I find myself immersed in, goodby sleep, I won’t be able to sleep at all.

About 3.5 years ago I did some experiment to improve the behavior of microfacet normals at glancing angles. Many surfaces become highly reflective even though having high roughness. Check the discussion in the thread. Here is my implementation reusing equations you already have:

Yining Karl Li@yiningkarlli.bsky.social

There's a neat short paper from Eurographics this year that evaluates how well microfacet shading models actually predict measured reflectance. The answer is: not nearly as well as one would hope! (1/3) ssteinberg.xyz/2026_surface...

Cut tool. It does more or less what you'd expect from a cut tool. Snap to points and edges, fractional placement, cut across faces, slice. No support for edge loops yet.

Add Polygon second pass: "predictive snap points" and numerical input to finetune distance and direction of the current point position in respect to previous.

I need to revamp my modeling operators, especially those that require user interaction. Here is first attempt at the Add Polygon operator. It's a first pass; it needs some work, but I feel it's not a bad start.

It allows to attach to existing points, control the projection plane, using exiting points as hinge. Holding shift it helps draw orthogonal and 45deg edges, and snap along constrained directions on existing points nearby. It uses color for winding order feedback.

Alright, I made some further improvements to the tree view, which now draws in constant time (in respect to the scene complexity). Here is a test with 16 million transform nodes viewable in the scroll area. Without screen recording, the whole app renders at 8kHz.

I had to create a flat cache for the line drawn and that lets me jump to the visible band of TreeNode lines I need. I still rely on the nested structure, so it isn't a flat list... but a few hops in the cache reconstruct the nesting context to initialize ImGui::TreePush/TreePop

With that many nodes it takes a sensible fraction of a second to invalidate and rebuild the cache when the scene structure changes, or a node is expanded/collapsed, changing the flattened list.

I played a bit with the UX of interacting with the tree view. The common operations are selection and re-parent. I want to control both with the same gesture. So, if the drag&drop is mostly vertical -> reparent. If it widens to the side, it becomes marquee selection. Yes, no?

The typical implementation requires one to click-drag on empty space to start a selection marquee. Somehow that feels ok for a file explorer window, but I find it annoying and limiting in a scene hiearchy tree view.

I recall in Maya left-click-drag is always select, for drag&drop one has to use middle-click-drag. Never liked that much either, it's not very laptop friendly.

I am not sure why I am doing this, but I optimized further the scene tree view as it was getting a bit slow and clunky to operate when I had many nodes expanded. It's not cheap, it's still the most expensive part of the program to draw.

That's a test with 1 million lines in the tree view, which is likely much more than one can reasonably expect to interact with. I am happy my take on multi selection works and feel zippy.

dear imgui offers a convenient ImGuiListClipper to draw only a range of a long list. In this case I am not relying on that because my data structure is not a flat list. For widgets out of view, I call a cut down version of TreeNode I call TreeNodeSkip, and that feels good enough for now.

A long time ago in a galaxy far away (circa 2011) I came up with a distant rect light for my lighting crew. I can't remember how I did it, but I am trying to recreate it. Here is a test for the light sample distribution in the hemispherical domain.

It's not a uniform distribution. Well, it is relatively uniform if at least one of the angles is small. It creates 4 singularities when both angles approach π. But that is outside the intended use because there are easier ways to cover the entire hemisphere :D Here is the result in render.

After how many years? I added code for distant area lights. Some call it "directional". The control "scale compensation" is meant to preserve the light power (radiant flux), so as the emissive area increases, the intensity decreases.

What are distant lights good for? Not for the sun, you get much better result with a HDR map. They are good for fill, rim, modeling lights, especially when the characters move around in the sequence and you need to maintain shot-to-shot consistency.

Some times you want the character feel moving through the environment, so practical lights and indirect illumination covers that. Some time you need to highlight a feature and keep it stable -> distant lights.

I cut down startup time by deferring DLSS initialization. The first second of images rendered are noisy, until DLSS init is complete, at which point I accept a one off 40ms hiccup to allocate buffer resources and begin denoising. I'd say it's decent enough!

DLSS in workbench. The quality of 1spp rendering is way higher compared to the other built-in denoisers, and for half the cost. The comparison changes at higher spps.

On the flip side, DLSS takes about 2.5 seconds to initialize, which alone is 5x longer than the rest of the app. Going from a startup time of 0.5 seconds to ~3 seconds doesn’t feel great 🫤

I am trying to add DLSS-RR mode to Workbench. In theory I already have most things from the renderer, exception made for the specific pixel jitter and the motion vectors… It shouldn’t be too hard for me to add either of those. I am curios to compare DLSS with the other denoisers

Last weekend I refined the scene tree view in Workbench. I used the drag & drop support in dear imgui to implement DAG reordering and reparenting, plus renaming. Custom behavior and drop region draw to show where the node would be inserted, and display where and why it cannot.