XaiJu
FuroticVR
FuroticVR

patreon


The Performance Update!

Hey guys,

There've been quite a few changes, some of which you can see in the above screenshot!

The obvious change you'll notice, is everything is now lightmapped. Why did I make this change? Why didn't I make it sooner?

Well, the reason I didn't make this change sooner is because I didn't want to set expectations too high. You see, I'd been considering the possibility that with characters that can grow and shrink, I might want them to be able to push things out of the way or knock them over as they get larger. But that wouldn't work with lightmapping, which is static. I may have set my ambitions too high there however. When I get to implementing growth mechanics, I can revisit this issue, but it's clear that performance was already suffering, so physical simulation on that scale would be out of the question, and animating it all would take a lot of complex scene setup which simply isn't realistic for me to consider doing right now. There's still a ton of other more important stuff to add to the game, and I can still have giant or growing characters in these scenes without going bonkers with the animation complexity.

But why did I make this change now? Well, primarily for performance reasons. A lot of folks have been complaining about the game's performance, and I've noticed it getting worse myself. So I wanted to do something about that. And switching to baked lighting where ever possible, rather than relying on real time shadows, would help with that.

That wasn't the original plan though! The original plan was simple: I'd create a bunch of trigger volumes and use them to hide objects that couldn't be seen from that location.

But that solution turned out to be unweildy to set up by hand. One volume per room would not be enough to hide many objects. I'd have needed to split each room into more like four volumes, and outdoors would require volumes all the way around the house and then another layer of the same high above the ground so be able to hide the objects in the first and second floor selectively. And at once point I accidentally deleted all my work setting them up.

So I decided to give Unity's built-in occlusion culling system another try. The first time I'd attempted to use it, it didn't cull much of anything no matter what settings I used. But I thought I must have overlooked something. And overlook something I had! While Unity's documentation does not cover it, I found this blog post from 2013:

https://blog.unity.com/technology/occlusion-culling-in-unity-4-3-best-practices

This blog post contained the critical piece of information I was missing. Unity's occlusion system doesn't operate on occluding polygons. It voxelizes the polygons, turing them into little cubes that represent them, like Minecraft. And therein lay my problem!

Unity's occlusion baking system includes two parameters: Smallest Occluder, and Smallest Hole. The manual states that Smallest Hole is "The diameter of the smallest gap through which a Camera can see, in metres."

Naturally, I assumed I needed to consider things like windows when deciding on how small to make this number, and that if I didn't make it small enough, the worst that would happen would be too many objects would be culled. But I was having the opposite issue, of too few objects being culled. So certainly my problem was not that this number wasn't small enough!

Except that's EXACTLY what my problem was!

Because the scene was being voxelized, and the walls in my house are thin, they appear to have been excluded with Smallest Hole set to the default of 0.25 meters. That parameter, which should have been named Voxel Size, needed to be much smaller, 0.05 meters, for the walls to be included as occluders. And once I figured that out, the built-in occlusion system began working beautifully. You can see it at work by sticking your head partially through the walls when you're inside the house. You'll see the rooms still, but all the objects and avatars inside them will have vanished!

Or so it would seem...

For you see, there was another issue implacting performace that I was not aware of until just recently, and it has to do with lighting. Or rather... shadows!

In Unity, there are many ways to set up your scene lighting. You can use all baked lighting. You can use all realtime lighting. Or you can use mixed lighting, which combines the two. And mixed lighting comes in two varieties: Shadow Masking and Distance Shadow Masking.

My game uses mixed lighting, and until this latest build, Distance Shadow Masking was enabled. With Distance Shadow Masking if you have a meadow you can have trees in the distance cast baked shadows on the ground, and trees up close cast real time shadows which animate as the leaves move in the wind. It's the best of both worlds. With Shadow Masking, you'd have to choose between having trees cast baked shadows everywhere, or cast dynamic shadows up close and no shadows in the distance. That wouldn't look good. So I assumed Distance Shadow Masking was always the way to go so long as I could afford dynamic shadows on my trees up close.

Except there's more to it than that.

Another feature of Distance Shadow Masking is that all objects will cast shadows onto dynamic (moving) objects, including those which cast baked shadows onto static objects.

What this means in plain english is that if I have a static unmoving bedside table casting a baked shadow onto the ground, with Distance Shadow Masking that bedside table will also be casting a dynamic shadow onto any dynamic objects that move into the region it's shadowing. And dynamic shadows are expensive. Dynamic shadows cause the object and all its polygons, to be rendered twice in the scene.

I couldn't easily see that this was happening unless I had a character or another object intersect one of these shadows, so I didn't know all the objects in my scene were casting expensive dynamic shadows!

One I figured this out, and I researched the shadow modes for mixed ligthing some more, I switched the mixed lighting mode to Shadowmask which does not cast dynamic shadows from nearby static objects, but does cast dynamic shadows from moving objects. And I set everything I could to cast baked shadows, leaving real time shadows enabled only for the avatars, trees,  and objects the player can pick up (which right now isn't anything, but I've still got them enabled for the fleshlight in the garage).

Making all these changes, to the occlusion culling, and the method of rendering shadows, has reduced the polycount of the opening scene, with no avatars visible, from 8M down to 3M!

Oh, and I forgot to mention that in addition to the above changes, I also went in and deleted a ton of polygons from objects that were half underground, and I removed a lot of unecessary objects in the house, rearranging the others here and there. I did this before I figured out the occlusion culling though. I might not have bothered otherwise because now they're all hidden when you're in another room.

Anyway, with all these changes you should see a signficant performance improvement with this latest build!

And if it's still not fast enough, well, whenever I get to implementing the menu to let you choose the one or two characters you want to interact with, I can tell you from testing that that'll itself bring a huge performance boost. My framerates were double with most of the avatars hidden!

Hm... Let's see, what else have I gotten done this month?

Well, I improved the lighting some more!

I discovered that instead of changng the bounced light multiplier globally in Bakery, I could set it per light source. So I tried enabling that only for the sun, to brighten the inside of the house above what is naturally possible to better simulate how our eyes see, and that greatly improved the look of the dining room and the computer room above it because they were no longer being absolutely blasted by blue light from the skybox. They're still pretty blue, but it's more tolerable to look at now.

I also found that increasing the intensity of the sun light slightly while playing with the parameters of the post processing allowed me to improve how the outdoors looks to you when when you're inside the house. Meaning, it's less over-exposed, and the sky is a bit bluer rather than white. Paradoxically, the outdoors is also now exposed a little less, because even though the sun is brighter, the auto exposure is adjusting that down a bit. Again, a little tweak just to make things easier on your eyes. It's a difficult balancing act making it both look properly exposed outside and inside at the same time!

Oh, how could I forget!

I've also switched all the materials over to Silent's Filamented shader. This is a shader they designed for VRChat which is based on Google's research, and it has two important features. First, it has specular antialiasing, which works to remove bright edges around things that are glossy, like the vases, or the car. And second, it has reflection probe occlusion, which hides reflections in areas which are dark. This helps combat "Unity sheen" in dark scenes. Its particularly helpful with the shiny wood floors I have.

There's some other stuff I've been working on too, but this update is extremely detailed already, so I'll leave that for the next one, which hopefully will be later this month. Some big news coming with that one!

Anyway, that's all for now. The new build will be posted shortly!

PS:

Almost forgot! The beds are taller now! I realized they needed to be if you're gonna have a character laying on them which you can thrust into while standing next to them! I'll adjust the models later so the backboards are lower. And there's a new object in the guest bedroom that I'll leave as a surprise. :)

The Performance Update!

More Creators