So here we are, six entries into this series and we haven’t really done much in the way of making software. I actually find this kind of liberating. In Project Frontier I felt driven to get my core features in there. I like that this project is more an excuse for endless digressions. It’s a lot easier to navigate when you don’t care where you’re going.
Still, I guess we’d better get started with the actual thing and stop whinging on about technology and development platforms. First, let’s look at texture mapping…
(We don’t have a lighting system yet, so I’m just painting the sides of cubes darker than the top. That’s close enough for now.)
I’ve slapped the default stone texture from Minecraft onto this landscape so I can illustrate the thing I want to work on. As in Minecraft, flat stone can look kind of dull if you see too much of it at once, and I’ve deliberately designed this scene to show us way, way too much of it.
This texture is kind of bland. I mean, it’s a scattering of grey values that barely deviate from each other. Of course, this is by design. Notch knew what he was doing when he made his textures. Some well-meaning modders come along and try to make the textures more “interesting”, and you wind up with:
Which sends you right into quilt-world. Sometimes people try to compensate for this by bumping up the resolution. That can mitigate the problem, but it’s not a solution. The issue at hand is that textures repeat exactly one per cube-face, so looking at lots of cubes means lots of repetition. This isn’t a design flaw or anything. It’s part of Minecraft’s distinctive look.
But what if we broke from that? What if textures covered larger areas? Let me grab a random texture from Google image search and set up the texture system to stretch the texture over 16 blocks. I’ll be using this texture:
And it looks like this:
You can see that spanning many blocks lets us have large patterns. We could use this to have colored strata of rock or variations in brightness. I know my texture here isn’t ideal, but I’m content that this would look better with more suitable art.
However, this leads to some problems mapping textures. All this fancy detail will work against us if we can’t get it to line up. Think of it like hanging strips of wallpaper. We can put two strips next to each other, and their patterns will line up to create a seamless whole. But if some deformation makes one part of the wall “longer” than the other…
At the top of the wall the two strips line up, but then the one on the left has to fill an alcove, which covers 3 meters of wall instead of just 1. By the time we exit the alcove, the strip on the left has run too long and there will be an ugly seam where it meets its neighbor.
Texture mapping theory can get kind of dense. It’s basically a more convoluted version of the age-old map projection problem. Or I suppose it’s the map problem in reverse: We have a square image and we want to project it onto a complex world with as little distortion as possible. It’s not a problem you “solve”, but a series of trade-offs you juggle.
In Half-Life 2: Episode 2, Valve actually created a custom shader that would wrap a texture onto the complex topology of a cave. They did this so that an artist wouldn’t have to drive themselves mad trying to get rectangles to line up on stalagmites and other topologically difficult items. It just smears a generic rock texture all over everything.
This works because “rock walls” don’t have an expected orientation, and are very forgiving with regards to stretching. (Nobody’s going to look at the wall and think the rocks are “sideways” or “too big”. If you tried this with a brick texture it would look ridiculous.
We are not going in that direction. We’re aiming for low tech. We’re aiming for simple. We want something that will produce working results on shapeless rock and dirt, and also on non-rotatable stuff like bricks.
So here is my super-secret ninja technique:
int u = x + y; int v = z;
I know, right? Brilliant. I’ve already filed for the patent and everything.
This is as simple as it gets. The texture follows the world coordinates. If you move one unit in the world, you’ll move one texture frame. Here, let me apply a test texture:
I suggest using a texture like this one whenever you’re dealing with texture mapping problems. It’s orient-able. (You can tell if it’s backwards or upside-down, which doesn’t matter in our case but can be a problem if you’re working on something where textures need to face a certain way.) The letters form a clear progression from left to right, so if your texture doesn’t line up you’ll see the letters stop following natural order. Same goes for the rainbow color-shift: If you see purple next to green, then you’ve botched something. If the textures are working right, both the lettering and color-change should progress naturally.
Let’s apply it to our world:
We’re just worried about walls right now, so I’ve made the floor solid color just to avoid confusion.
You can see the rows I’ve highlighted here. They line up whenever they meet, even though the walls have different shapes. You can see there’s a hole in the wall on the right, where an “N” block is missing. This means that row is longer than the other two, yet even then it lines up. The texture can wrap around a mountain, or a continent, or a one-meter pillar, and you’ll always be able to walk all the way around it without seeing a seam.
Here’s the backside of the hill:
Sure, the letters are backwards, but in the case of terrain textures this generally doesn’t matter.
The rule is simple: When we move east or north, increase the texture by 1 section. Corollary: If we move west or south, decrease the texture by 1. The only downside is:
Let’s assume we’re looking at a really big pillar from above. (Note also that the vertical arrow should point UP, assuming the top of the image is north. No big deal. The principle is the same.)
The problem areas are where you’ve got a wall running up one axis but down the other. It moves east, goes forward one letter, then it goes south, and goes back a letter, then forward, backward. It looks like this:
We we end up looking at repetition and mirroring. See what I mean about trade-offs? We’ve left behind the drawbacks of Minecraft’s texture system and are using a new set of drawbacks.
Lemme put a really busy texture up. Also, we’ll put a different texture on all of the surface blocks so we have even more contrast. Here are some high-contrast textures at work:
And here is the same hill from the “bad” side:
I’d say the texture itself is more ugly than the mirroring and repetition, so maybe this wasn’t an ideal test. Anyway. You get the idea.
Next up is something I’ve wanted to do for over a decade. Since my time at Activeworlds, I’ve always wanted to make a borderless tiling world. A world where you can go off one edge of the map and seamlessly enter on the other, where if you travel in a straight line you’ll eventually end up back where you started. The last time I saw that in a game was in Magic Carpet in the mid 90’s.
I like borderless environments so much better than games like Fallout 3 or Oblivion where it just puts an invisible wall around your playpen and tells you “NO!” when you try to leave. I also like it because it lets you walk around the world, which is kind of neat.
Let’s try it:
I guess… I guess you can’t show this off in screenshots. Oh! Unless I make the world really, really tiny. Let me adjust the size down, and build some distinctive landmark:
And if we look up:
The world map is 32×32 meters. Just enough space for a suburban house with a modest yard, I think. Our view reaches 144m in every direction. Keep in mind those question marks in the distance are the exact same question mark I have in front of me. They’re not copies. Those are the same polygons and blocks. If I break a block in front of me, I see it vanish from the pattern in the distance.
All three of my kids saw this in turn, and each one asked: Will you be able to see yourself like this?
Well, keep in mind that right now there IS no concept of a “self” model. Or any kind of model. There are cubes. That’s all we have, and there aren’t even any systems in place for drawing other sorts of stuff. (Items, foes, NPC’s, space marines, etc.) But if I keep with this project and if I follow the plan in my head, then looking all the way “around” the world like this would cause you to see everything except yourself. (Because your character model isn’t usually drawn in a first-person game.)
But this is academic. The point isn’t to make a bizzaro world where you can see things tile. The point is to make a borderless world, and this little stunt proves that it works.
PC Gaming Golden Age
It's not a legend. It was real. There was a time before DLC. Before DRM. Before crappy ports. It was glorious.
Good Robot Dev Blog
An ongoing series where I work on making a 2D action game from scratch.
A video Let's Play series I collaborated on from 2009 to 2017.
A programming project where I set out to make a Minecraft-style world so I can experiment with Octree data.
What is Piracy?
It seems like a simple question, but it turns out everyone has a different idea of right and wrong in the digital world.