Add BasePart.CullFace to hide specific faces of a BasePart

Hello, everyone!

Recently I got an idea that could greatly improve performance in games - especially building showcases.

Currently, you have to deal with a total of 12 triangles per part, which can quickly add up when building extremely detailed maps. For example, you have around 6000 triangles for just 500 parts - this is way too much for low end computers & mobile devices.

This property would allow developers to make a face of a BasePart, meaning MeshPart, WedgePart, CornerWedgePart, or a Part not render.

This can be currently achieved through the use of MeshParts by uploading a mesh with a missing face. However, this is not a dynamic approach and requires multiple uploads with different faces missing, rather than simply being able to Cull specific faces within Studio and perhaps even run time. Closest example I can think of that’s very similar in nature is the NoDraw texture from the Source engine, which makes it so the face it’s on is completely invisible.

With Roblox’s current direction going in the area of being an actual game engine, this is a feature that is needed so more detailed & expansive games can exist and be playable on all devices.

11 Likes

I get a feeling that hiding certain faces of a part would ruin part instancing.

Instancing only works when meshes have the same geometry and materials. The engine will have to batch each unique culled face combination in several passes instead of in one go.

I’m not entirely sure if it would, since you’re only hiding specific faces from rendering & not really changing anything else about the part.

Unless Part instancing is very picky about properties.

How is this functionality any different from the current streaming enabled? Also how is this functionality better in performance than streaming enabled other than obvious networking gains?

Essentially parts are culled or e.g doesn’t exist if you have StreamingEnabled until the part comes into streaming radius of the player. Also on the Road map they have an automatic level of detail system on the way which should allow mesh to perform better at a greater distance.

Can’t see this feature being beneficial to be honest. Though I do feel this could greatly support water culling.

2 Likes

OP wants a feature where certain faces of parts can be hidden. For example, if you have a map with a cliff comprised of a lot of parts, you can disable faces that the player will never see to (possibly?) improve performance.

I understood that, Was just wondering why this would be beneficial when compared to Streaming Enabled which removes the part altogether.

Or with an adjusted radius would still show up as he’s wanting. And when paired with Automatic LOD and Instancing.

https://developer.roblox.com/resources/Roblox-Platform-Roadmap

The performance gains would be negligible at best saving a few nanoseconds on draw calls. (Assuming the game only uses parts.)

1 Like

If you have triangle terrain that’s made up of around say, for some reason, 50,000 parts, that’s 600,000 triangles that everyone’s device would need to render, regardless if Streaming is enabled or not.

With face-specific culling, basically cull every face but the top face, you can bring that triangle count down to 100,000, still a high triangle count, but a massive improvement nontheless.

There’s even more of a reason to have this considering the simple fact that most maps aren’t going to take advantage of Streaming Enabled since, to my knowledge, once you have walked into an area that has loaded, it’ll never despawn again. Not to mention most maps are going to be too small to even use it.

If hiding faces on objects’ performance is negligible, why does every single game have culling for faces the player will never see?

2 Likes

Because that’s the way mesh works… Typically in your situation you would use a single faced mesh that doesn’t have any back faces. Which is still an option here.

Also if you are using 50,000 parts. You should be getting increased performance thanks to Instancing. However I can see where you may be getting some performance degradation when it comes to different properties on the parts causing them to be instanced differently.

Any who, you’ve already answered my question I was curious of, Though In my opinion I believe this is a specific use case thing though how many people are having issues with this use case is beyond me.

I don’t think it has something to do with the way the Mesh works - it’s a method used by game developers to cut back on resources being used by the renderer, thus allowing more graphical fidelity to be displayed on screen.

Also, as Roblox evolves more and more to being a professional program, it’s important that developers have every tool possible to optimize their games. Part Instancing won’t do much for really detailed places with around 12,000 triangles shoved into a scifi build. Being able to cull faces on parts would bring much greater performance improvements than Part Instancing or Streaming could ever dream of.

Take any EBR build for instance, the really detailed ones - even with Part Instancing, the performance is absolutely terrible since all 12 triangles in each part are still being rendered, quickly adding up to a lot of triangles with only around 1,000 parts. If bulders were able to turn off most faces, say, down to 1 or 2 faces, that’d only be 2 - 4 triangles per part, improving performance.

Of course, the problem with a lot of parts eating up triangles could be mitigated with unions, but unions are very limited in terms of maximum triangle count & collision fidelity, not making them worthwhile for actual game use.

4 Likes

Not really, it’s simply a method used by the video card to efficiently display mesh. I would argue here that building a mesh in your modern day 3D editor and omitting faces that’ll never be seen by players isn’t a method to cut back on resources but just common sense and industry standard.

The problem here is you want to cull faces on regular Roblox parts. Not custom mesh. As the option is already there for custom mesh. Probably due to the way collision works with meshes, and how its easier to make terrain out of parts themselves.

As I stated before though, this seems like a particular use case, how many people are struggling with this use case is beyond me.

You basically said the same thing I did - just in a different way. Better efficiency is less resources being used.

Also, as I said in my original post, uploading meshes isn’t a viable solution for standard Roblox parts, since they’re not dynamic any. Being able to toggle off specific faces in Studio would be a huge performance gain for places that are primarily made out of base-Roblox parts, and you wouldn’t need to upload meshes just to omit the top & bottom face, or all faces but the top & bottom, etc, or worry about broken shadows with MeshParts that have a massive shadow when they shouldn’t.

Parts have 6 faces, and every face needs 2 triangles. So basically, if you have a place with around 500 parts, each one is going to have 12 triangles, adding up to a total of 6,000 triangles, which is way too much for mobile devices and some older PCs to handle.

I’m also not sure how this is a “particular use case” either since this would improve performance for many different upcoming and current games that have detailed environments. It seems like a lazy argument to me.

1 Like

Roblox Parts are at its base meshes.

Also the difference between what you said, and what I said is, the optimizations you’re referring to is done at a lower level, where as you’re asking for a higher level implementation of optimization. Also I referenced the fact of hiding faces that would never be shown to the player. You want to hide faces that could be shown to the player at some point, but only if they are in view.

The fact you could achieve this right now without the feature request, but the feature request is here, is the specific use case I’m referring to. As this specific implementation is only necessary in your use case.

I was just wondering how the features in this feature request were more beneficial than the functionality Roblox has already implemented or plans to implement.

1 Like

Can’t you already achieve this using mesh? Your mountain example is bad because it takes about 5 seconds in blender to remove all the faces from 1 side of a mesh so that it can only be viewed from the other side. I don’t really see how this can be useful for regular parts and wedges seeing how robust mesh are.

3 Likes

Mesh also isn’t a good idea because of how limited Meshes currently are - very limited in terms of triangle count, collision fidelity, etc.

I’ve also explained multiple times in this thread that having all 6 faces on a part render at the same time is bad for performance, given the fact that if you have 500 - 1000 parts, that’s 6,000 to 12,000 triangles, that may or may not be crammed into a small space depending on if the place is detailed or not.

1 Like

That doesn’t change the fact that you’re wanting to hide faces on BaseParts which at its core is a Mesh itself. In fact even in Game Engines such as Unreal Engine 4, Unity, Frostbite, RAGE… Any engine you’d want to compare it to. Keeping your triangle count/polygon count low is industry standard. It’s part of the topology of 3D modeling mesh.

If you were to use meshes, putting collision aside, you’d end up with chunks of terrain in your specific use case with one sided faces that doesn’t need culling because it was like that by design.

What @wravager and I is saying is that the functionality you are asking for is already there. It’s just this specific use case that you’re asking for that isn’t supported. Even if you did end up with hundreds of meshes from these chunks that you inevitably split up you would have the performance gains of instancing considering the materials, opacity, and other properties are similar.

You simply want to use parts, and dislike the artifacts of using parts. Which is why I compared the parts you are using to the functionality that’s already been implemented in the engine. Such as automatic LOD (coming soon), Instancing, and Streaming Enabled.

As far as the feature request goes though. This specific use case and how many people are struggling with it. Is beyond me. But this doesn’t seem beneficial at all outside of your specific use case.

1 Like

A request like this was already covered in another post, and I replied to it in terms of why this wasn’t going to be a thing. There was somewhere else where an engineer (I think it was zeuxcg) said something about how it is a feature that isn’t going to be added because the stock instancing system already culls stuff that isn’t visible to the player (I need to find the source of that, but I can’t. I’ll keep searching.)

This is what I was pointing out (See Material for smooth terrain underside). Needless to say, implementing this wouldn’t really resolve performance issues.

Edit: Although this post primarily points out static lighting, this carries over to other render workloads in terns of Roblox’s system, just to clarify.

1 Like

So does the renderer automatically remove the faces the player can’t see?

1 Like

Yes, it does. I believe that if a face is cut off at an angle (e.g. a wedge against a solid part) it will dynamically cut the face, but I’m not 100% sure on this.