Fixed AGZ is very bad

Status
Not open for further replies.

Fred

Member
Yay! I found an embl- OH GOD

agz_hom_1.png


I know that "AGZ abuses the software renderer to do things it was never ever intended to handle" doesn't even begin to describe it, but these are all over the place and often obscure entire parts of the level:

agz_hom_2.png

agz_hom_3.png


This one in particularly was really scary because I know there's supposed to a secret area behind it, but there's no way to know for sure *where* it is besides jumping into Glitch City and hoping for the best:

agz_hom_4.png


(That's RedXVI's house, by the way. RIP in peace Red.)
 
Last edited by a moderator:
Yeah, these happened to me as well. Gladly, it didn't make me end up dying or anything, but it's something that's hard to ignore.
 
We obviously knew about these before release, but they're hard to fix so it wasn't a priority. I definitely want to get those blatant ones fixed, though.
 
I did notice these while writing the emblem hints. At first I thought it was because all of the outermost linedefs don't have Impassible (Effect 6) checked, but that turns out to not exactly be the case, since going about fixing that didn't change diddly.

Then I noticed ZDBSP fixes some of the more glaring ones with ease, and a lot faster than ZenNode compiles the map, too. The problem there? Too many nodes; SRB2 immediately crashes after loading the stage. We'd have to support ZDoom's Extended NODES format for that fix to work.

So, yeah, that's where we are right now.
 
Recently I went HoM-hunting in AGZ, and this is what I found...
AGZ-HoMs.PNG

Red circles mark the HoM locations. And yes, they all lie in a straight line.
 
I'd like to take this opportunity to provide a fun lesson on the software renderer, why these particular glitches currently happen, and the silly little hack I applied that will fix them for 2.1.13. Feel free to ignore this post if you're not a dork.

Now, as Iestyn's image notes, all of the big problem spots in AGZ lie on a straight line. Here's an exercise: boot up SRB2 right now, go to one of the problem spots in AGZ, and figure out what position you can place the camera in that prevents the visual glitches from happening. (You should probably turn chasecam off.)

I bet the solution you found was to move the camera anywhere north of the red line marked here:
LjRQpLL.png


Now, there's a reason for that. This line is the dividing line for the root node of the map's BSP tree; this basically means it's the first place where the map is divided in half. (If you can tell it apart from the rest of the line, the part toward the left of the screenshot in orange is the exact linedef the nodesbuilder used to get that dividing line.) Quite frankly, that's kind of an odd place for it to be IMO, but that's not important.

All of the nitty-gritty on how the software renderer works is explained on this page much better than I could do so, but the gist of it is this; each section of the map is constantly split into half along various linedefs until each leaf on the "tree" consists of no more than a single subsector. (Subsectors are areas of a sector split into convex polygons.) There's some extra stuff about linedef splitting and balancing and such that nodesbuilders worry about, but that's all besides the point of this explanation.

So how does this cause the visual destruction seen here? Simple; the way the software renderer works is that, while the lines and planes are being drawn, no pixel on screen will be drawn to more than once per frame for the sake of performance. This is done by rendering everything closest to the camera first, and the method used involves those handy nodes created earlier. Each rendering pass starts at the root node, and recurses through the BSP by running the closer half before the farther half. (This is determined with the dividing lines; whichever side you're on is the side closer to the camera.) The snag is that the engine has to go through every part of one side of the tree before it can go to the other side. For performance optimization, the renderer checks the bounding box of a node (this is the smallest box that holds everything in that node) to make sure anything there can display on-screen, and skips the entire node if that's the case.

So let's use an image to illustrate:
MG9RAdY.png


The camera sits somewhere in that blue box, staring north. Due to the way AGZ's BSP was built, everything south of the green line must be run through the rendering checks and process before anything north of it can be. So it runs through the entire tree, checking a bunch of little stuff from the closest to the furthest. (Ignore the bounding box checks for now; we'll get to them in a moment.) Eventually, it gets to the area somewhere around the red box above. (That's probably not an exact node, but that's beside the point; the point is that general area's being rendered.) So the renderer will do some math with angles to figure out whether it's on-screen and what to do with the lines, etc etc.

So what's the shortest path from the camera to that red box? The answer may surprise you:
gPnY5BH.png


The software renderer uses fixed-point math for all of these distance, angle, etc checks. This means integer overflows are very possible; a large enough negative value becomes a positive value, etc. The distance/angle checks basically ends up cutting across the map boundary lines (which are really just indicators of the integer limits associated with the Doom map format) to connect the two points. So now the renderer thinks that part of the map way behind your camera is actually in front of your camera, so it renders it there.

So now the renderer's finished checking the bottom half of the root node, so now it's moving onto the half that contains the rest of the level in our camera. Unfortunately, something's already rendered over the area that this part of the map intended to render over, and as per the stipulation mentioned earlier, we won't render over anything that's already been rendered, as it's assumed anything already rendered is what should show up on the final screen. So the game decides it doesn't need to render this part of the level. That results in the issues above.

"But why don't the bounding box checks catch this and stop that from happening?" The bounding box checks have the same integer overflow problem as all of the other distance/angle checks, so they draw the same incorrect conclusion.

The fix is kind of a hack, but it works; for the angle checks associated with the bounding box checks, I divide all of the position values used by 2 before feeding them into R_PointToAngle. This makes the numbers just small enough that integer overflows resulting from subtraction won't happen, so the back half of the level that should be completely off-camera is properly discarded.

SpectacularEthicalArrowworm.gif


IN CONCLUSION: AGZ is way too fucking big for the software renderer to properly digest, so it ends up spitting up a garbled mess instead. Programatically shrinking parts of it into easier-to-swallow chunks helps the poor renderer handle its job slightly better.
 
Last edited:
Status
Not open for further replies.

Who is viewing this thread (Total: 1, Members: 0, Guests: 1)

Back
Top