Hello all! Chris, the graphics guy, here.
Firstly, a huge, gigantic, heart-felt ‘Thank You‘ to all our fans that downloaded, ran, crashed, swore, and then once again ran our Stonehearth Graphics Test! We’ve spent the last few days figuring out all the issues that need to be fixed, and have started squashing as many bugs as we can manage. As yet, there have been no reported wildfires conclusively attributable to the Test, so I believe we get to chalk this one up as a ‘win’ for Team Radiant.
We also want to let you know that we’ll be releasing one more version of the Test that contains a number of fixes (oh, mouse cursor: where art thou?) as well as some improved logging support so that we can have a bit more clarity into some of the more inconceivable crashes.
For this edition of Desktop Tuesday, we thought it might be fun to talk about one of the visual glitches people have reported in the Test, and how we’ll fix it.
This is the ‘texture issue’ people have commented on that occurs at some of the joints of our humans and bunnies. Amusingly, there are almost NO texture maps in Stonehearth. A texture map is basically an image that is ‘mapped’ onto a piece of geometry. (Imagine a blanket with a picture on it, and then wrapping that blanket over, say, a box. The blanket will fold around the edges of the box, and so too will the image on the blanket. You’ve now just ‘mapped’ that image from the flat blanket, onto the bent surfaces of the box. Current graphics cards do not, however, use blankets to perform texture-mapping.) Modern games may feature gigabytes of texture data that can be potentially rendered on-screen, but not Stonehearth. Aside from the user-interface and a few invisible textures (invisible–how mysterious! Perhaps, the topic of a future post?), nearly every object you see is composed of simple shapes with flat colors. Put enough of them together, and you get some nice, chunky, voxely characters and landscapes.
So, if Stonehearth isn’t using any texture-maps, what exactly is that weird graphics glitch everyone’s seeing? Well, the first clue is that we’re seeing this issue in many places where joints meet: two parts of a finger meeting at a knuckle, or at the bunny’s hind legs. This is a place where two pieces of geometry are overlapping. In fact, they are almost exactly overlapping. What does this mean? Well, when a graphics card is drawing a scene onto your monitor, it has to make sure that the parts of the scene that are far away from you aren’t drawn on top of the things that are very close by. In the screenshot above, for example, you wouldn’t want the ground that the bunny is resting on to be drawn over the bunny. The technique that your graphics card relies on is called ‘depth-buffering’, and it’s actually pretty simple: when drawing the scene, every time a pixel is about to be drawn onto your screen, first do a check to see if a pixel is already there, and if it is closer to you than the pixel you’re planning to draw. If so, don’t draw the new pixel. Otherwise, draw it, and record the new pixel’s distance (its ‘depth’) from you. And that’s it–you can now draw your scene in any which way you like, and this check will make sure that everything is drawn correctly.
Except…remember that I said this check compares the depth value of the old pixel and the new one? Well, guess what happens if two pieces of geometry overlap–occupy the same space, at the same distance from the viewer? Their depth values are going to be very, very, very similar. Identical, in fact! Or, at least, they would be identical, if computers were better at math. Sadly, certain calculations that computers do can end up incurring tiny errors in their results. This means that some values that should be identical differ ever-so-slightly. In the case of our graphical glitch, we have two overlapping objects that, because of these tiny arithmetic errors, end up being a little different, and so one object’s depth value will be a little smaller than the other’s, and will get drawn on top (it ‘wins’). Except, in the next pixel, maybe the second object’s depth value is smaller, and so that one ‘wins’. Do this enough, and you end up with a patchwork of pixels being drawn, some belonging to the first object, and some belonging to the second. This effect is called z-fighting, because the two objects ‘fight’ to be drawn at the same depth, but the poor graphics processor can’t resolve the dispute amicably!
What are we to do? It’s fairly straight-forward: we, the programmers, step in and resolve the fighting. Graphics processors have some techniques that allow us to basically say, ‘Whatever depth that pixel you’re comparing says it’s at, add just a smidgen to it, and then do the comparison’. This allows us to bias a comparison in favor of whatever we’re drawing, so that if two depths would otherwise come up almost the same, we can make sure one side always wins. And so, no more z-fighting! This can be complicated slightly when you have multiple models with many simultaneous intersections, but nothing a little elbow-grease can’t solve .
That’s all for now–stay tuned for our next Graphics Test, and big thanks again to all the testers out there for all your hard work!