- Jul 6, 2009
- 261
- 110
Well, I've recently faced the dreaded "Too many T-junctions to fix up" error. Since I had to deal with it, figured I'd share the knowledge I got from the experience.
What causes the "Too many t-junctions to fix up" error.
As explained by Valve's own Jeff Lane, T-Junctions appear mostly when func_details meet up with world geometry, in order to avoid "cracks".
That said, it's not T-junctions themselves that are a problem, it's waterindices. You can have a million t-junctions and it's all good, but go over 100% waterindices and you'll get that error and fail to compile.
So when do you get waterindicies? When the engine fails to compile a junction into a fan-like tesselation it seems to turn all the verts created into "waterindices". (You can check using mat_wireframe 2 in-game).
In other words, waterindices are NOT t-junctions, but they're the value you need to keep your eye on to avoid the error. You can keep track of it in the post-compile report. Go over 100% and your map won't compile.
How to fix it.
I did some searching and the most common solution was "Turn some func_detailing into models". This is a very good solution if:
a) You are a modeler or have someone that will do it for you.
and
b) Your func_detail in question repeats itself several times throughout the map (like a wood beam with the same exact dimensions).
In this case, a model is much more efficient, as it's ignored by vBSP -AND- you only have to render it once to be cached for further uses.
That said, not all of us model or have someone willing to model, and sometimes it's just plain inefficient. So these are a few tricks you can do to greatly reduce the number of t-junctions. I managed to reduce my t-juncts up to 10% and improve my optimization (and I'm not done yet).
1 - T-Juncts are ONLY formed if the func_detail and the world geometry actually touch.
This is actually a great way to save up t-juncts. Just moving the func_detail 1 pixel away from the brush will prevent any and all t-junctions from being formed. Now, obviously you want to avoid pulling this in places players will be looking at very often (like door and window frames, or wall details in very traveled places), but a single pixel isn't very noticeable if you're not looking directly at it.
You can easily pull this stunt in things like ceiling beams players won't look sideways too, details outside the map players can't get close to...etc. It's easy, fast, and saves a ton of t-junctions on high func_detail areas.
2 - MORE func_detail. Func_details are NOT world geometry.
This seems paradoxical at first, but it's actually amazingly obvious and efficient.
"Well...Didn't too much func_detail cause t-junctions in the first place?"
No. Too much func_detail touching brushes did. func_detail touching func_detail does fuck all.
This is part of normal optimization, but look at your map. If you CAN func_detail a wall (if it has a lot of windows, for instances) stuffed full of func_detail, do so. That means that suddenly, all those details touching brushes that would create so many obnoxious t-juncts, suddenly create 0.
If you're wondering whether or not you should func_detail a wall or ceiling, or whatnot, you should definitely look into interloper's guide.
Keep in mind, however, that your new func_detail will most likely be touching some geometry of it's own. It's not worth it detailing a wall with 2 func_details touching it, only to realize there are 5 other brushes touching your new func_detail.
3 - Displacements are NOT world geometry.
There's two ways you can use displacements to reduce your t-junctions.
First is by using them on the world brushes. Much like above. Func_details touching displacements do absolutely nothing as far as t-junctions go. However, it has it's own particular advantage and disadvantage.
The advantage is that it does not create any other t-junctions even if it's touching a million other brushes.
The disadvantage is that displacements are heavier on the engine, since they force you to render each face individually (and entirely, regardless of visleaves) every time... It's acceptable if it's only 1 or 2 faces small/medium, but throw in a big and complex brush and this won't work well.
Edit: Apparently, according to Booj, the only time displacements become "heavier" is if it's a small object with a lot of faces. So... Seems like the only real disadvantage is that it will act like a func_detail in the sense that it will not break up visual LoS... So you want to avoid doing it to things you shouldn't func_detail in the first place.
Second, by turning a func_detail into a displacement. This shouldn't be used as a general rule since, as mentioned above, this means your detail will become considerably heavier on the engine (depending on how many faces it has/how complex it is). However, in a pinch it's acceptable for small, simple, individual stuff, and you can even take the chance to do some very small morphing to natural materials to make them look more organic and less rigid. Edit: See above.
That's all for now, 3 simple steps that can save you a lot of grievance. Ultimately, models can be more efficient most of the time, but sometimes you can't have a model (extra size, time, inability to model) and these should cut down on your t-junctions without affecting your map's visuals or performance.
What causes the "Too many t-junctions to fix up" error.
As explained by Valve's own Jeff Lane, T-Junctions appear mostly when func_details meet up with world geometry, in order to avoid "cracks".
That said, it's not T-junctions themselves that are a problem, it's waterindices. You can have a million t-junctions and it's all good, but go over 100% waterindices and you'll get that error and fail to compile.
So when do you get waterindicies? When the engine fails to compile a junction into a fan-like tesselation it seems to turn all the verts created into "waterindices". (You can check using mat_wireframe 2 in-game).
In other words, waterindices are NOT t-junctions, but they're the value you need to keep your eye on to avoid the error. You can keep track of it in the post-compile report. Go over 100% and your map won't compile.
How to fix it.
I did some searching and the most common solution was "Turn some func_detailing into models". This is a very good solution if:
a) You are a modeler or have someone that will do it for you.
and
b) Your func_detail in question repeats itself several times throughout the map (like a wood beam with the same exact dimensions).
In this case, a model is much more efficient, as it's ignored by vBSP -AND- you only have to render it once to be cached for further uses.
That said, not all of us model or have someone willing to model, and sometimes it's just plain inefficient. So these are a few tricks you can do to greatly reduce the number of t-junctions. I managed to reduce my t-juncts up to 10% and improve my optimization (and I'm not done yet).
1 - T-Juncts are ONLY formed if the func_detail and the world geometry actually touch.
This is actually a great way to save up t-juncts. Just moving the func_detail 1 pixel away from the brush will prevent any and all t-junctions from being formed. Now, obviously you want to avoid pulling this in places players will be looking at very often (like door and window frames, or wall details in very traveled places), but a single pixel isn't very noticeable if you're not looking directly at it.
You can easily pull this stunt in things like ceiling beams players won't look sideways too, details outside the map players can't get close to...etc. It's easy, fast, and saves a ton of t-junctions on high func_detail areas.
2 - MORE func_detail. Func_details are NOT world geometry.
This seems paradoxical at first, but it's actually amazingly obvious and efficient.
"Well...Didn't too much func_detail cause t-junctions in the first place?"
No. Too much func_detail touching brushes did. func_detail touching func_detail does fuck all.
This is part of normal optimization, but look at your map. If you CAN func_detail a wall (if it has a lot of windows, for instances) stuffed full of func_detail, do so. That means that suddenly, all those details touching brushes that would create so many obnoxious t-juncts, suddenly create 0.
If you're wondering whether or not you should func_detail a wall or ceiling, or whatnot, you should definitely look into interloper's guide.
Keep in mind, however, that your new func_detail will most likely be touching some geometry of it's own. It's not worth it detailing a wall with 2 func_details touching it, only to realize there are 5 other brushes touching your new func_detail.
3 - Displacements are NOT world geometry.
There's two ways you can use displacements to reduce your t-junctions.
First is by using them on the world brushes. Much like above. Func_details touching displacements do absolutely nothing as far as t-junctions go. However, it has it's own particular advantage and disadvantage.
The advantage is that it does not create any other t-junctions even if it's touching a million other brushes.
Edit: Apparently, according to Booj, the only time displacements become "heavier" is if it's a small object with a lot of faces. So... Seems like the only real disadvantage is that it will act like a func_detail in the sense that it will not break up visual LoS... So you want to avoid doing it to things you shouldn't func_detail in the first place.
Second, by turning a func_detail into a displacement. This shouldn't be used as a general rule since, as mentioned above, this means your detail will become considerably heavier on the engine (depending on how many faces it has/how complex it is). However, in a pinch it's acceptable for small, simple, individual stuff, and you can even take the chance to do some very small morphing to natural materials to make them look more organic and less rigid. Edit: See above.
That's all for now, 3 simple steps that can save you a lot of grievance. Ultimately, models can be more efficient most of the time, but sometimes you can't have a model (extra size, time, inability to model) and these should cut down on your t-junctions without affecting your map's visuals or performance.
Last edited: