Jump to content

Tree performance


Recommended Posts

So recently I've been working on implementing PCSS for soft shadow rendering, and I noted some performance issues when it came to trees. Ultimately I ended up disabling soft shadows for transparent models, but it's still apparent that trees present performance issues regardless of whether they receive soft shadows or not.

After tinkering around with the drawing process to see if I couldn't fix it, it became clear that the reason was that virtually all of the trees in 0ad use highly translucent leaf planes. What that means in a nutshell is that each tree might generate half a dozen fragments or more per pixel covered by its leaves, each with full lighting calculations applied. If you have more than one tree worth of foliage stacked up then the number of fragments can rapidly become unreasonable. Additionally, terrain drawn under the trees that may be obscured partly or completely also gets drawn with full lighting calculations, which in the case of PCSS are quite expensive.

Now ideally trees/foliage would be drawn with a depth-only prepass before terrain in order to early-z reject any terrain fragments or other foliage fragments that would be obscured, and then draw color and alpha blending in a second pass after terrain and water have been rendered.

However the current trees don't allow for that because for at least two major reasons:

1. LOD. When using lower mip levels more of the foliage becomes less opaque for trees with dense foliage. Actually these are the easiest to deal with by setting alpha test >= 0.5 and promote to 1.0 alpha, but it makes for a lot of special cases. Palm trees are even worse, since the spikes on their fronds will sparkle horribly from aliasing artifacts if alpha test/alpha promotion is used.

2. Leaf plane visibility. Leaf planes that are nearly perpendicular to the camera (ie edge on rather than face on) become dramatically more obvious when using alpha testing. That could be dealt with by multiplying the alpha value by abs(NdotV) before alpha testing, but again this leads to a lot of special cases since not all trees use randomly angled leaf planes and might look dumb if such a strategy were employed globally.

Also the vast majority of the trees look really bad when viewed from any angle besides top down, notably in water reflections. A lot of the trees also looked notably better with alpha test due to shadows being applied more consistently rather than being washed out by the lighting from the terrain behind the leaf planes.

So basically, for the sake of better performance and better looking trees I think it'd be worthwhile to look for a solution to these problems.

Any ideas?

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

2 hours ago, Sundiata said:

Lots of grasses, which are preferable for a realistic looking map, also cause lots of lag. Related? 

I honestly have no idea what you're talking about. I literally painted greek acropolis into a giant field of grass and could not produce any lag. :| I think grass might actually count as a solid model but I'm not really sure.

screenshot0041.thumb.png.acfaae7ff86f7ed7210e8a4369fcebf7.png

To be fair I was honestly surprised that it didn't lag hardly at all even after painting that much grass. It even receives shadows!

  • Like 2
Link to comment
Share on other sites

That's weird but not that weird. Trees have way much more polygons than grass. Around ten times more for some. 

I believe the grass Sundiata was referring to is the fancy grass terrain texture which is different. You can find it in Atlas.

@aeonios what kind of suggestions are you looking for exactly ?

Link to comment
Share on other sites

15 minutes ago, stanislas69 said:

That's weird but not that weird. Trees have way much more polygons than grass. Around ten times more for some. 

I believe the grass Sundiata was referring to is the fancy grass terrain texture which is different. You can find it in Atlas.

@aeonios what kind of suggestions are you looking for exactly ?

The fancy grass textures are weird, but not particularly laggy that I can tell.

Basically, I'm wondering if we should be looking for new art (probably?), or looking to create more specific shaders for different types of transparent models(maybe?), or some combination of the two or if someone knows of another approach to getting good looking trees without eating your gpu.

  • Like 1
Link to comment
Share on other sites

1 hour ago, aeonios said:

I honestly have no idea what you're talking about. I literally painted greek acropolis into a giant field of grass and could not produce any lag. :| I think grass might actually count as a solid model but I'm not really sure.

Huh... Interesting... I could have sworn grasses caused lag. Guess not, never mind me :mellow:

In that case, a lot of maps need to make much more use of grasses (that screenshot is pretty) :), maybe some new types as well (shorter and longer grasses).  

Link to comment
Share on other sites

5 hours ago, aeonios said:

After tinkering around with the drawing process to see if I couldn't fix it, it became clear that the reason was that virtually all of the trees in 0ad use highly translucent leaf planes. What that means in a nutshell is that each tree might generate half a dozen fragments or more per pixel covered by its leaves, each with full lighting calculations applied. If you have more than one tree worth of foliage stacked up then the number of fragments can rapidly become unreasonable. Additionally, terrain drawn under the trees that may be obscured partly or completely also gets drawn with full lighting calculations, which in the case of PCSS are quite expensive.

How did you check that exactly the fragment shader is most expensive (the grass has transparent things too as mentioned above)? Could you post you profiler.txt results here?

Link to comment
Share on other sites

1 hour ago, Sundiata said:

Huh... Interesting... I could have sworn grasses caused lag. Guess not, never mind me :mellow:

In that case, a lot of maps need to make much more use of grasses (that screenshot is pretty) :), maybe some new types as well (shorter and longer grasses).  

I take that back, with the ridiculous amount of grass I spammed it does in fact lag fairly significantly, although it's still less than the lag caused by the palm tree spam on gold oasis or siwa oasis. I'm glad you brought up grass though. Not only is it freaking gorgeous but it also highlights some interesting lighting concerns that have convinced me of the need for custom shaders for different kinds of transparent models. In particular the dark lines you see on grass when looking straight down at it are caused by using NdotL lighting on grass, which is dumb given how translucent real grass is and bad because all it does is highlight the grass model's true shape, which is undesirable.

screenshot0046.thumb.png.220b216fa5e584b0fa59f4fe20cde750.png

The same thing but with the sun directly overhead:

screenshot0045.thumb.png.17e5781abb77fa191c7708079f74dbd0.png

As for increasing grass usage, now I'm seriously thinking about implementing a grass map feature so that you can paint and unpaint grass/flowers/etc as easily as you can do with terrain texture. Having nicer grass models/textures would also be nice. A lot of the current textures use fake lighting where the grass is darker towards the bottom, which also creates ugly grey lines.

1 hour ago, vladislavbelov said:

How did you check that exactly the fragment shader is most expensive (the grass has transparent things too as mentioned above)? Could you post you profiler.txt results here?

A fancy profiler wasn't necessary. If I enabled soft shadows for transparent objects I literally got zero fps when panning over the trees in the center of gold oasis, and when I disabled soft shadows for transparent objects it became playable again. They work fine for terrain and solid models.

  • Like 2
Link to comment
Share on other sites

11 minutes ago, stanislas69 said:

See #2103

For grass type foliage I actually want something more specific, with a uniform spacing but random rotation and different grass field sizes available for controlling density and handling smaller spaces. The main motivation for using a texture to store the distribution is ease of instancing and overwriting the existing distribution to replace certain elements with others to create variety. Ultimately it would allow for more compact storage and would also serve as a source of randomization inputs for the model rotation that could be fed directly into a shader.

Link to comment
Share on other sites

27 minutes ago, aeonios said:

A fancy profiler wasn't necessary. If I enabled soft shadows for transparent objects I literally got zero fps when panning over the trees in the center of gold oasis, and when I disabled soft shadows for transparent objects it became playable again.

Hm, so currently your patch can not be applied as is because of lags. But, we can a little bit optimise it or add an options, which algorithm to use.

6 hours ago, aeonios said:

Leaf plane visibility. Leaf planes that are nearly perpendicular to the camera (ie edge on rather than face on) become dramatically more obvious when using alpha testing. That could be dealt with by multiplying the alpha value by abs(NdotV) before alpha testing, but again this leads to a lot of special cases since not all trees use randomly angled leaf planes and might look dumb if such a strategy were employed globally.

I'm not sure, that it's the major reason, because for near to perpendicular triangles only a pixel line will be rasterised.

I think there is a reason, why it's slower than it can be up to 2x times: many transparent things have a bigger (up to 2x times) transparent area, than it needs. Example: palms.

Also did you test shadows with discard-like way? When you don't calculate shadows when the pixel is fully transparent.

Link to comment
Share on other sites

3 hours ago, Sundiata said:

Huh... Interesting... I could have sworn grasses caused lag. Guess not, never mind me :mellow:

In that case, a lot of maps need to make much more use of grasses (that screenshot is pretty) :), maybe some new types as well (shorter and longer grasses).  

It does in mass amount, if a huge amount of grass its going to be added it will need to have some slider or setting controlling the amount of grass i've tested in skyrim Grass Performance mods and the vanilla as well tweaking the grass amount and texture resolutions from 2k to 128 (Its very easy to tweak when it comes to graphical settings) they have quite low plane polys for flowers and basic grass with some 512 or 4k texture resolution, and i imagine this is what any1 wish to achive "Video link" but it drains too much fps when the amount is too much even at low resolutions i hope that will not be the case in 0 AD.

  • Like 2
Link to comment
Share on other sites

7 hours ago, vladislavbelov said:

Hm, so currently your patch can not be applied as is because of lags. But, we can a little bit optimise it or add an options, which algorithm to use.

I just made it so that transparent models use regular pcf rather than pcss and it works fine. It's not ideal but until a better solution becomes available..

7 hours ago, vladislavbelov said:

I'm not sure, that it's the major reason, because for near to perpendicular triangles only a pixel line will be rasterised.

That's only an appearance concern, not a performance concern. The grazing edges of the planes are normally nearly transparent but if you use alpha test they become very obvious and it looks bad. It's the planes facing the camera that produce lots of fragments and perform badly.

7 hours ago, vladislavbelov said:

I think there is a reason, why it's slower than it can be up to 2x times: many transparent things have a bigger (up to 2x times) transparent area, than it needs. Example: palms.

The issue with palms is just that the sharp edges of the fronds look really really bad when using alpha testing, especially at lower mip levels. Trees aren't supposed to sparkle.

7 hours ago, vladislavbelov said:

Also did you test shadows with discard-like way? When you don't calculate shadows when the pixel is fully transparent.

The transparent shader already does that, but that's not the issue. The issue is that the more opaque parts of the leaves are actually partly transparent and use alpha blending, so they produce a ton of fragments even though you might not be able to see through them very much.

6 hours ago, Alexandermb said:

It does in mass amount, if a huge amount of grass its going to be added it will need to have some slider or setting controlling the amount of grass i've tested in skyrim Grass Performance mods and the vanilla as well tweaking the grass amount and texture resolutions from 2k to 128 (Its very easy to tweak when it comes to graphical settings) they have quite low plane polys for flowers and basic grass with some 512 or 4k texture resolution, and i imagine this is what any1 wish to achive "Video link" but it drains too much fps when the amount is too much even at low resolutions i hope that will not be the case in 0 AD.

It didn't seem to be that bad unless the density was excessive, which it tended to be since I didn't have much control over it using the standard prop placing method. It lagged more in game than in atlas, which suggests that a lot of the cost was CPU bound, which could be reduced a lot through instanced rendering and a coarser frustum culling method. Of course that's another motivation for using a grass map, ie the ability to control the density or to disable grass entirely. The texture size didn't seem to be much of an issue, nor did enabling shadows for grass change the performance noticeably.

Link to comment
Share on other sites

Some grass and some trees use alpha blending (necessary for making leaves look halfway good). This means we render them twice, and once with transparency enabled.

Furthermore, the game has no real instancing (we merely sort stuff in a semi-clever way) so lag is to be expected, we start doing a looooot of draw calls.

 

edit: btw you can disable the alpha blending somewhat easily, and you'll see that our leaves are horrible without it. There might be some trick to that, but I don't know it.

  • Like 1
Link to comment
Share on other sites

15 minutes ago, wraitii said:

Some grass and some trees use alpha blending (necessary for making leaves look halfway good). This means we render them twice, and once with transparency enabled.

Furthermore, the game has no real instancing (we merely sort stuff in a semi-clever way) so lag is to be expected, we start doing a looooot of draw calls.

Yeah, openGL3 is still beyond what I'm prepared to do right now. I'm not really sure whether the lag from grass is draw calls or fragment writing or what though. That'd be a good candidate for profiling.

16 minutes ago, wraitii said:

edit: btw you can disable the alpha blending somewhat easily, and you'll see that our leaves are horrible without it. There might be some trick to that, but I don't know it.

 I've been editing model_transparent.xml for that. Actually depending on how you set it up they don't necessarily look that horrible. Well, technically I didn't completely disable alpha blending, I just turned it off for the opaque pass. There are lots of different ways of going about that, although none of them work particularly well.

15 minutes ago, wowgetoffyourcellphone said:

Here's a tip if you don't already know it: Use this in local.cfg for performance testing alpha test.

forcealphatest = true

I actually saw that, but from the searching around I did I couldn't actually locate anything in the code that would use force alpha test. It doesn't seem to be implemented.

  • Like 1
Link to comment
Share on other sites

6 hours ago, aeonios said:

The transparent shader already does that, but that's not the issue. The issue is that the more opaque parts of the leaves are actually partly transparent and use alpha blending, so they produce a ton of fragments even though you might not be able to see through them very much.

Hm, about transparency, you can try to reduce number of probes for low alpha: make a function like f(alpha) that returns a number, how many shadow texture the shader should do.

1 hour ago, aeonios said:

Yeah, openGL3 is still beyond what I'm prepared to do right now. I'm not really sure whether the lag from grass is draw calls or fragment writing or what though. That'd be a good candidate for profiling.

@wraitii, it'd be good to think about dropping the older OpenGL versions and leave only 3.3+.

6 hours ago, aeonios said:

That's only an appearance concern, not a performance concern. The grazing edges of the planes are normally nearly transparent but if you use alpha test they become very obvious and it looks bad. It's the planes facing the camera that produce lots of fragments and perform badly.

It's only for low angles. right? For usual playing angles it's not really visible, at least shouldn't be.

Link to comment
Share on other sites

2 hours ago, vladislavbelov said:

Hm, about transparency, you can try to reduce number of probes for low alpha: make a function like f(alpha) that returns a number, how many shadow texture the shader should do.

Unfortunately there is no direct relationship between the tex alpha and the number of fragments that it will end up generating per pixel. Basically any alpha < 1.0 is a potential offender.

2 hours ago, vladislavbelov said:

It's only for low angles. right? For usual playing angles it's not really visible, at least shouldn't be.

The angle in question is the angle between the trees' foliage planes and the camera. Since the foliage planes are nearly randomly oriented in most trees there's no escaping it. There will be at least one leaf plane at a low angle no matter what angle the camera is at.

I decided to pull up f11 and do some comparisons to see if I couldn't determine more accurately what exactly I was dealing with. It seems that fps may fall based either on the number of triangles being drawn or on the number of draw calls per frame, whichever happens to be worse. The number of draw calls seem to be high on some maps and not on others for reasons I don't understand. Some maps have particle effects which makes sense, but sicilia produces tons of draw calls and doesn't really have any major use of particle effects as far as I can tell. Grass produces a ton of draw calls which isn't all that surprising, and with my awful manual grass spam it tends to be overdense so the number of triangles is also pretty high, but with a proper grassmap that fixed the spacing and kept the density only as high as necessary I doubt the number of tris from grass would be too excessive.

In terms of tris I found that there are two types of trees that are serious offenders.

The king offender is the cretan date palms, which seems to use around 7000 tris per tree. Maps that make heavy use of them can end up with over 3mil tris on screen even though the number of draw calls for them is very modest. I'm not entirely sure where all of those tris are coming from, although the leaves definitely use a lot it doesn't seem to account for the total. There seriously has to be some way to reduce that without making them look worse.

The second major offender is the aleppo pines. They seem to use about twice as many tris as an average tree, although I'm not sure if that fully accounts for the lag they produce. The aleppo forest on the west side of sicilia produces notable camera drag.

I'm honestly not really sure how bad the fragment overdraw from normal trees is, or if it's really enough to be a blocker for pcss. For the worst trees it definitely is though. Also grass doesn't seem to suffer any loss of appearance from using alpha test > 0.5 with blend disabled for the opaque part of their draw cycle. In fact it actually looks a bit better that way.

EDIT: The aleppo pines and cretan date palms both use 2000 tris each (6000 for a cretan palm patch). That's nearly 10 times as many tris as any other type of tree, and three times as many as the other non-cretan types of date palm. There are a couple of other trees like that but I don't think they get used much.

Edited by aeonios
Link to comment
Share on other sites

5 hours ago, Nescio said:

OpenGL 4.0 was released eight years ago ...

True, but we have old and Intel video cards unfortunately, also many users may not update their drivers. We're working on actualising feedback statistics, but it's not enough to decide about supported versions. Because we also have potential players, who didn't enjoy this amazing game yet or didn't send statistics.

5 hours ago, aeonios said:

Unfortunately there is no direct relationship between the tex alpha and the number of fragments that it will end up generating per pixel. Basically any alpha < 1.0 is a potential offender.

I meant to calculate a end pixel shadow color with different number of probes that depends on the alpha value. It's not exactly what did you say about, but just a near idea. Because for more transparent pixels we can have a lower quality of shadow, because it's less visible.

5 hours ago, aeonios said:

The number of draw calls seem to be high on some maps and not on others for reasons I don't understand.

There're many reasons to have so number of draw calls.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...