Rendering Updates - April 2017

I guess if you’re fine with clipping issues on some devices, you wouldn’t need to know the clipping distance. Depending on what devices support the 0.1 near clipping, I might want to provide those users the next best thing. If only devices that can barely play the game experience the issue, I might not care, but otherwise 5% is still a lot of people for a popular game.

About that in regards to the particle limit, Ive come across times where I wanted more particles in my place but because of the limit I couldn’t get any more. Having it so the engine doesn’t load particles that aren’t in view would allow us to fit more.

The limit would still be there though, but whats happening now is lets say I have 30 emitters behind me and one in front, the one in front in restricted and produces less particles by the ones which aren’t even in view.

Now when more emitters come into view, less particles are shown as it reaches the limit.

1 Like

Thank you so much for this update! As far as I can tell it the update fixed all of my Z-Fighting issues even with parts that have a .005 scale difference and over 2k studs from the origin. bless up

Yeah I sort of understand where you’re coming from, I’m just not sure what exactly you’d do in case you’re making a game and we tell you 0.5.

Ultimately for games that want 0.1 it’s a tough call because unless you’re on a platform/API where we can switch to the new representation, you’re choosing between clipping (if near plane is 0.5) and really bad Z fighting (if near plane is 0.1). We’ll need to look into what exactly happens with smaller values on platforms that don’t support higher precision Z and what we can do about it.

@ScriptOn, we’re planning to switch to Metal on Mac this year but I don’t have a precise timeline and also I’m not sure how many issues we’ll see (I heard Metal is less stable on Mac compared to iOS, so we may have to work around some things) and thus it’s hard for me to predict anything here.

1 Like

With aiming down sights, I’d just push the weapon further from the camera. Would look a bit weird, but it’s definitely better than having chunks of the gun missing.

This is amazing!

This tunnel a couple dozen thousand studs from the origin looks beautiful now, and the cars look great this far out too! Everything used to be a garbled mess this far away, but look at it now:

Thanks guys for all your hard work!

18 Likes

I’m having a little bit of an issue with it.

Decals with transparency are drawn further back than transparent parts.

This update has actually made the near plane even farther than before on unsupported systems. I have a ton of clipping on parts even remotely close to my camera on Mac. Really hoping this feature makes it to Mac soon… is there an ETA by any chance?

Do you have a before-image?

So what this property could allow us to do is have a special state for cameras where there are clipping issues.

Like, this wouldn’t work very well in all cases but it would be somewhat functional; you could just move the camera back by 0.4 studs on devices with a 0.5 near plane.

But yeah, even though it’s such a seemingly small update, it’s very powerful and opens up a new world of potential for first person games. This is definitely one of my personal favorite updates to ROBLOX! Thank you so much!

This is the closest I have to a before image.

I specifically tried finding a camera angle that wasn’t screwed up when I took this, so the z-fighting isn’t obvious at first glance. You can see it in a few places:

  • Behind the fender of the white van in the oncoming lanes
  • The right brake light of the orange pickup truck in the right shoulder
  • The joints in the triangle terrain, especially between the tunnels
  • The lights in both tunnels
1 Like

Nvm.

I think near plane on Mac was closer than 0.5 before the update due to a bug and is precisely 0.5 after, matching all other systems that don’t support high precision depth.

This would definitely explain why I was never able to reproduce complaints about clipping. Does this mean Mac will remain at 0.5 now instead of the closer plane before this update?

This is amazing!

With the float point errors no longer showing up ~12k studs from origin, near infinite randomly generated maps will become a lot more viable!

1 Like

Hey @zeuxcg I’ve noticed an issue with terrain water recently, I suspect it may have came from these updates it’s a fairly big issue. When underwater you can’t see the surface of the water anymore so for example if there is a boat floating on water it looks like it’s hovering in blue fog.

Issue:

Here’s an old photo I found of the water somewhere:

As you can see something has gone wrong with the surface of the water.

1 Like

That’s definitely a regression; we’ll take a look, thanks!

3 Likes

Can you tell us how the z-fighting fixes work? Are you using a logarithmic depth buffer?

4 Likes

Hi @opplo, this will be fixed in an upcoming release. I’ll post here when the fix is live.

2 Likes

We don’t use a logarithmic depth buffer (it’s not supported natively by GPUs; you can emulate this with shaders but doing so either requires a reasonably high level of tessellation of all objects, which we don’t have and don’t want, or having pixel shader output the depth value, which breaks some important GPU optimizations).

The way standard rasterization pipeline with perspective camera works with depth is:

  • Depth is a 0…1 value stored in a 24-bit fixed point value; this means at any point on this scale your precision is 2^-24
  • Depth is computed from camera-space depth (let’s call it Z) using approximately this equation: 1 - znear / z (this equation ignores zfar but for typical zfar/znear it’s not very important). Note that this is 0 when z = znear, approximately 1 where z is big (zfar).

Because of this inverse mapping you have a property where the depth is mostly distributed near the camera. When z = znear depth is 0; when z = znear * 2 depth is 0.5 - so half of your depth range is right in front of the camera (in Roblox this is 0.5…1 studs before the update). Next doubling gives you half of the remaining range or 25% of the full range (1…2 studs); etc. You can see how for large z values you get smaller and smaller depth ranges in 0…1; since precision is always 2^-24 this means the further the point is from the camera, the larger the “error region” (the region where other points map to the same depth value) is in studs, hence z-fighting.

This is also why we can’t really give you near plane for tuning - notice that changing near plane shifts the distribution dramatically - making it 0.1 instead of 0.5 means your “high precision” regions shrink 5x, so if you had Z-fighting 1000 studs away from the camera now you have it 200 studs away.

What we did was two things - switch to a floating-point depth buffer and reverse the Z mapping. I’ll talk briefly about both.

Floating-point depth buffer stores a standard 32-bit depth value (well, 31-bit since sign bit isn’t used). Floating point representation is basically 2^e*m, where m is a 24-bit number between 1 and 2 (I am ignoring a lot of details here, no nitpicking please!). This means that in any region between two consecutive powers of two floating point numbers have the same precision which is 2^e * 2^-24. Around 1 your precision is still 2^-24, but it gets better when you get closer to 0 - when you’re in 0.5…1 it’s 2^-25, when you’re in 0.25…0.5 it’s 2^-26 etc.

So the first step is to use floating point depth. This gives us even more precision really close to camera (where depth is almost 0), and the same amount (24 bits) of precision far away. This alone isn’t interesting - we already had lots of precision close by and not much precision far away, so what’s the point?

Well, the point is that now we can flip the distribution around - instead of using 1 - zn / z, we’ll use zn / z.

With a fixed point distribution this doesn’t help - you have 2^-24 precision everywhere so it’s still get progressively worse the further away you go. But with a floating point distribution, the larger Z gets, the smaller depth becomes but this is precisely where floating point precision distribution shines.

If z is between zn and zn * 2, depth is between 1 and 0.5, with 2^-24 depth precision
If z is between zn * 2 and zn * 4, depth is between 0.5 and 0.25, with 2^-25 depth precision
etc.

Basically your depth precision for z between 2^k and 2^(k+1) is 2^-24 * 2^-k, which means that in terms of world-space units - z - it’s pretty much constant and also very high. And note how in the closest region it’s still not worse than it was - 2^-24. This means that z fighting behavior is uniform across the entire range (nit-pickers: I’m omitting details, it slightly fluctuates). Yay!

The fact that the precision of rendering improves compared to where it used to be if you’re far away from the origin is due to how projective transform works with floating point - basically some internal rasterization computations lose way less precision with the new transform. I’ll leave a description of this for some other time :slight_smile:

30 Likes