Bryan Taylor is a user on You can follow them or interact with them if you have an account anywhere in the fediverse. If you don't, you can sign up here.

Bryan Taylor

`float u = (float)x / img.width - 1`

Why, yes, they let me teach people about math, why do you ask?


If `quat * vec` transforms a vector, `vec * quat` must be a compile error. If you overload the second to transform by the inverse, you are technically correct but seeding awful, non-obvious bugs.

Same goes for matrix / vector multiplication, by the way.

The best mornings are when you wake up having figured out how to solve a problem.

Second best are when you wake up having figured out what the problem *is*.

Steam Stuff Show more

So, turns out: there aren't any fringing artifacts. Not exactly.

The sun light is bright. The decals are highly saturated. When they blend together, there's enough of each channel for the tonemapped color to peak at white. But the colors on either side have one really dominant channel, so they *don't*. Ergo, you get white fringes between two highly saturated colors.

Clearly I'm doing *something* wrong. Premultiplied alpha is supposed to get rid of fringing artifacts, but all my decals have white fringes. (Why white? Shouldn't they be black, since the clear color is 0,0,0,0?)

TIL Unity 2017 *still* defaults to gamma-space rendering -- despite cameras now being HDR by default.

Which means a lot of my lighting work from a few weeks ago was *completely and totally wrong*. And seems to have hidden some blending artifacts in my decal rendering.

Character modeling is hard. Humans are weird shapes and they get even weirder when you have a bad sense of proportion.

Me, Sunday: I have an idea for a playable demo to show off this tech! Shouldn't take more than a few days to put together, just need some basic assets first...

Me, Today: I have spent half a week in Blender and have nothing.


Figured out a much, much simpler method of wrapping splats around edges:

decal_normal = normalize(-ray_direction + surface_normal)

(Previous implementation iterated all faces within a particular radius and averaged their normals.)

Less "clean", causes the decal to stretch along the ray direction, but that seems correct for impact decals? Certainly cheaper (by, like, 0.8ms).

While working on writing up this decal system, realized the problem with UV seams *isn't* texture filtering. It's rasterization.

Which means conservative rasterization should fix the seams without doing the image-space expansion. (Saving an extra draw call and render target per update, as well as the UV mask texture.)

So now I get to figure out how to turn that on. Or if I even can.

My demo spends 70-80% of a frame waiting for (60Hz) vsync.

And yet. A GC bubble still makes it drop a frame every few seconds. Extremely irritating to see the profile spike when *most of the spike is sleeping*.

Bet your deferred decal system can't do this. 15k+ decals in the view frustum with no performance hit. *

*Some restrictions apply.

Amazingly, it works! Doesn't blur the texture but fills the seam.

Extra texture is an issue. On the other hand, the seams were most notable at lower resolution. So adding another texture in exchange for the ability to reduce the *size* of those textures is probably a win overall.

UV seams are a problem.

Fixing this is interesting. Blurring causes more damage than good. (Would need to blur on each splat, which means the existing splats get progressively blurrier.)

Could bake a secondary UV set that expands island borders?

Gonna try rendering a mask (1 for every pixel covered by UV, 0 elsewhere) and use that to grow the borders in image space. Would rather not need the extra texture, but...

Getting splats to wrap around corners nicely is trickier than it looks.

Spent all day chasing a bug and getting nowhere. Closed-source means I can't even validate my theory about what's broken.

Extremely frustrated. This was supposed to be straightforward. I can't even get to the "hard part" of the problem because I'm now blocked divining the inner magical workings of this black box.


It should not have taken all day to implement the naive version of this, but I did it anyway.