Jump to content

Displacement Vs. Func_detail - A comparative fps study


will2k

detaildisp_web.thumb.jpg.5416c2f8728c7e6

What is the question?

Ever since the dawn of humanity, this question was the center of a colossal debate. Greek and Roman philosophers tried to solve it to no avail. Alchemists in the Middle Ages gave it a go and failed miserably. Even Industrial Age scientists touched on the subject with no big breakthrough.

Luckily for everyone, I am here today to answer this question and put an end to a centuries-long argument: What is better in terms of fps, func_detail or displacement, in the context of the Source engine? If you were expecting an existential question, I am deeply sorry to disappoint you but hey, life is full of disappointment.

The study

This is going to be a short but sweet article; fewer words, more numbers and screenshots. The study is pretty straightforward and systematic. To make things fair and square, I will create 2 exactly identical test maps: In one, everything will be turned to func_detail while the other will have everything switched to displacements. I will then proceed to record the localized fps in these maps from a preset location and compare. Pretty simple, isn’t it? Well, it should be as the whole purpose of this study is to compare func_detail vs. displacement in absolute terms while keeping all other parameters constant.

The cases

The first map to test is the one made of displacements. Here is the screenshot showcasing the fps.

test2_disp.thumb.jpg.291d5a7cff52959bcaf

The map itself is very simple consisting of 7 identical houses placed at predetermined locations and surrounded by 4 walls. The houses are detailed enough to put some slight pressure on the rendering engine. For the skeptics among you, here is a wireframe in-game shot to show that everything is made of displacements.

test2_disp_wireframe.thumb.jpg.0a964abea

To refresh your memories, in Source engine wireframe mode, green is displacements, pink is brushes (world, func_detail, brush entity, etc…), blue is props, and yellow is decals/overlays. The recorded fps in this map is 289. We now move to the second map, the func_detail version to check how the frame rate is faring. Here is the awaited screenshot.

test2_detail.thumb.jpg.2d8e9872906c10bf3

Surprise, surprise. The fps is 330, much higher than the displacement version. Here’s the wireframe shot to put your mind at ease.

test2_detail_wireframe.thumb.jpg.4c8452f

Honestly, I was thinking the figures would be more on par as the engine handles both details and displacements pretty well, but in the end, Source is about BSP so I guess brushes would get a slightly preferential treatment over polygon meshes (conspiracy theory ensues).

The question that forces itself now is: Should we rely solely on func_detail in our maps? Of course not. Both func_detail and displacement have their advantages and inconveniences and leaning exclusively on one will inevitably lead you to a dead end. The best thing to do is get the best of both worlds by using them together.

In our little test map, how about we mix things up in a third version: let us make the house walls out of displacements while having the doors, windows, frames, and roofs made of func_detail. Incoming screenshot, brace yourselves.

test2_mix.thumb.jpg.7c63b3e2497518c2bf5b

Much better, isn’t it? We have now 311 fps, a very nice middle ground between the 330 fps of func_detail and the not-so-bad 289 fps of displacements. The mandatory wireframe shot follows.

test2_mix_wireframe.thumb.jpg.a5370572c6

So, what can we learn from all this? Well, apart from the obvious places where displacements are mandatory for the organic mesh sculpting (rock formations, cliffs, bumpy/twisted roads…), it is a good idea to spread some more displacements around your map to alleviate the total brush-count that you will inevitably hit the maximum in a highly detailed map. Your fps will remain high and you will enjoy the margin to keep adding structures to your map without fear of reaching the maximum allowed total brushes (substituting brushes with models/props is another viable solution that is not in the scope of this article).

I’m a man of science and I know that one example is not enough to draw conclusions. That’s fine, I have a second test map to investigate what we established before. The concept of having 2 identical maps is still the same, however, this time, we will spice things up by adding some static/physics props and some decals here and there. We will start with the displacement version.

test_disp_A.thumb.jpg.c8d80ad02fc01f641a

230 fps, not too shabby. Let’s check another angle.

test_disp_B.thumb.jpg.57bf635ca0ff8ce87e

220 fps, more or less, on the same level as the previous number. Now for the wireframe shot.

test_disp_wireframe.thumb.jpg.ed4a1540cd

The tree cards in the background are func_brush in both maps (the detail and displacement versions), so it’s a level playing field in this case.

Now for the moment of truth you all have been waiting for: will the detail version have better fps to support my earlier findings or will I be publicly embarrassing myself? A screenshot to the rescue.

test_detail_A.thumb.jpg.e6eb7ceb76e0c3a1

I knew I was right, never breaking a sweat (apart from the nervous cold sweat I just wiped off my forehead). 255 fps for the first location A. Let’s check the other angle or location B.

test_detail_B.thumb.jpg.37ec08c4ea21f8eb

250 fps. Bam, sweet victory…sorry I got carried away a bit. Ahem…Let’s get back to being scientific, shall we. Here’s the wireframe proof.

test_detail_wireframe.thumb.jpg.5adec97d

Let’s recap all the action and numbers in a nicely formatted table.

56b1205477ee5_2016-02-02_22_30_22-Tabell

You can notice the fps gap between the func_detail and displacement versions in both test maps whereas the “mixed” version considerably narrowed this gap. The numbers have spoken.

The bottom line

The bottom line is, if you rely only on func_detail, you will hit the maximum brush-count allowed in Source and severely limit your map and creativity. You might also run into T-junction issues as well as parts of your geometry flickering and disappearing from certain angles in densely func_detail’ed areas.

On the other side, if you stick to displacements alone, then you will have lower fps than a func_detail map version. You might also run into visible seams and un-sewn displacement issues.

Having a clever distribution of both func_detail and displacement in your map is the way to go. You will have high fps, better lighting around the edges, and organic sculpting while not getting anywhere near the total brush limit; the best of both worlds.

 


  Report Article


User Feedback

Recommended Comments

That's really neat! Well visualized.

Did you also test how much the power of the displacements affected the FPS?
Those in the screenshots seem to be power 4, so maybe depending on how you use them you could make them power 2 to save even more FPS?

Share this comment


Link to comment
Share on other sites

That's really neat! Well visualized.

Did you also test how much the power of the displacements affected the FPS?
Those in the screenshots seem to be power 4, so maybe depending on how you use them you could make them power 2 to save even more FPS?

Thanks Tyker :)

Every displacement in the screenshots is a power 3 (power 4 is better avoided in Source). Power 2 was also tested and the fps remained the same (in the range of 288-292).

Great stuff Will!

Any comment on preferential usage of func_detail vs displacements and their effect on vis? 

Jack :) thanks for dropping by.

Both func_detail and displacement versions had the same vvis time, visleaves and portals figures; they also had roughly on-par times for vbsp. There is no preference for vis since they are both ignored for visibility calculations.

Share this comment


Link to comment
Share on other sites

One thing comes to mind, did you construct every displacement face from each of their own brush? Like the rooftop on 2nd green wireframe image, the first house on the left. Did you do those from 4 brushes total or the displacements faces separately from 14 different brushes from which each you used only one face?

I think what i am trying to say is, making 1 brush with 6 sides displacement is more resource heavy than making 6 brushes and using only 1 face of each as a displacement.

 

Share this comment


Link to comment
Share on other sites

One thing comes to mind, did you construct every displacement face from each of their own brush? Like the rooftop on 2nd green wireframe image, the first house on the left. Did you do those from 4 brushes total or the displacements faces separately from 14 different brushes from which each you used only one face?

I think what i am trying to say is, making 1 brush with 6 sides displacement is more resource heavy than making 6 brushes and using only 1 face of each as a displacement.

 

Hi ics

For displacements, it is always a better idea to have some sort of "modular design" where different pieces make up the big structure. It is easier for displacements manipulation and texture application. The roofs you mentioned are made of 12 different brushes and the house body itself is made of many individual brushes turned-displacement, to make each wall side, door frame, window, etc.

However, from an optimization and frame rate point of view, it doesn't matter. If you make a displacement cube out of one cube brush (turning the 6 faces into displacement) or you make it out of 6 individual displacement faces sewn together, you will get the same fps.

I already tested this with 2 similar maps (1 modular and the other is block-based as in the house made of 1 brush and the roof as well); the frame rate is the same as Source renders the displacements faces in batches. One just has to make sure not to turn unneeded faces into displacements in both cases.

Share this comment


Link to comment
Share on other sites

@will2k thanks for your article.

It isn't entirely off-topic, but do you know how are handled displacement in the source engine? Does it convert it to displacement maps like some software do? I mean, displacement maps for texture appear to be alike to normal maps, excepting that there are far less restrictions about the depth of the relief you want to induce with those. I came to undestand that is something used a lot for current games, because in those game it is good for performances. Do you know why it isn't effective in Source while it is in other engines?

Share this comment


Link to comment
Share on other sites

@will2k Thanks man! That's a really helpful article and a fun read. I like your writing and those insights are highly appreciated.

@laminutederire I would guess that source does not handle displacements via separate maps but kind of does the math directly by subdividing the face by the number of the strenght you set for it and then pushes the vertices around by x units. Also if there were some kind of displacementmaps they would propably show up when packing the map? Just a thought.

Share this comment


Link to comment
Share on other sites

@will2k Thanks man! That's a really helpful article and a fun read. I like your writing and those insights are highly appreciated.

@laminutederire I would guess that source does not handle displacements via separate maps but kind of does the math directly by subdividing the face by the number of the strenght you set for it and then pushes the vertices around by x units. Also if there were some kind of displacementmaps they would propably show up when packing the map? Just a thought.

 

Yeah probably, that could explain the performances  :)

Share this comment


Link to comment
Share on other sites

@will2k thanks for your article.

It isn't entirely off-topic, but do you know how are handled displacement in the source engine? Does it convert it to displacement maps like some software do? I mean, displacement maps for texture appear to be alike to normal maps, excepting that there are far less restrictions about the depth of the relief you want to induce with those. I came to undestand that is something used a lot for current games, because in those game it is good for performances. Do you know why it isn't effective in Source while it is in other engines?

Thanks :)

This question is better directed to Valve :D but I believe that Source "piggybacks" the brush face directly like @esspho mentioned without storing an external displacement map. If someone has an in-depth knowledge of the inner workings of Source displacements, please chime in :) (I think a Valve programmer is here on mapcore but he doesn't visit anymore)

@will2k Thanks man! That's a really helpful article and a fun read. I like your writing and those insights are highly appreciated.

Thank you :) glad you liked it.

Share this comment


Link to comment
Share on other sites

Nice article Will2k! I like to use displacements whenever practical because of the texture painting abilities. I'll even make steps out of displacements for this reason. 

Thank you :)

Share this comment


Link to comment
Share on other sites


Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×