Cityscape – update 9

June 4th, 2009

Not a terribly coherent entry, this one. And no pretty screenshot for you to look at either, I’m afraid – in fact, it’s not going to be very exciting at all. I’d skip it if I were you.

However, if you’re determined to know what I’ve been up to lately, you’ll find the following bits and bobs in the latest revision.

  • Cylindrical buildings – and therefore, also, a new cylindrical primitive type. I tried to get this working in such a way that I could carve off sections to give a more modern, building-ish look, but I had trouble getting the surface normals to behave. The way I’m doing it at the moment, I generate vertices around the central point, with the normal for each vertex pointing outwards, and then generate the polygons by sharing the vertices. The problem comes when you slice a bit off, and the normals become interpolated across the face, thus:


    The led to some weird lighting artefacts and the only solution I could see that would eliminate the problem simply would be to stop sharing vertices and rework the whole cylinder geometry generation code. Which is a job for another day, I think.

  • Manchester “Beetham Tower” style buildings – This is quite an iconic building in Manchester and a simple enough one that I figure it’s worth putting in – it’s basically a simple block skyscraper with an overhang halfway up:

    Simple as it may be, though, it took me quite a while to get my textures to line up, and it’s still not right – also, the tower has quite characteristic window patterning that I should perhaps attempt to replicate. Still some work to be done here, I think.
  • Lastly, I’ve factored out a lot of the building builder classes into separate files – the Building.cs file was getting unwieldy and awkward to navigate, so now it’s much simpler.

I’m still not happy with the buildings: the big problem at the moment is a lack of detail: the buildings are all too uniform and the flat walls-of-windows lack any sort of visual interest. I’ve got a couple of ideas to add more interest – adding black columns to break up the walls of windows, a bit of rooftop furniture and more detailed buildings, that sort of thing – and hopefully I’ll find some time to add that sort of thing soon; it requires quite a bit of reworking of the BuildingBuilder, though, so it might be a while before we see any real results from it…

We’re up to revision 25 in the repo now. I wouldn’t check it out, though, as I seem to have forgotten to add a file to the commit. Bugger. I’ll sort that out when I get home tonight.

Cityscape – Update 8

May 27th, 2009

Unfortunately, today’s minimised screenshot doesn’t look so hot (I guess it’s something to do with Flickr’s contrast enhancing algorithm), so if you want to get an idea of the latest developments, you should probably click through to the original image on Flickr to see it properly.

The big news this time is that I’ve added lighting attentuation and fogging – cities are big, nasty polluted things, and it’s rare that you can see more than a couple of blocks anyway – plus, it means that when I add in distance culling in a while, I we hopefully shouldn’t see things pop in and out too obviously 🙂

Lighting attenuation is just the light falloff as things get further away from the light – I’m not 100% convinced it’s worthwhile at the moment, though. Fogging is very similar: a gradual blend towards the fogging colour (in this case, it’s the same colour as the sky) as distance from the viewer increases.

Both of them are very simple to implement in our shaders – a couple of parameters to control falloff and fog colour, and a little bit of extra code to calculate the light falloff/fogging amount – basically, 1/(distance * k), where k is a more-or-less arbitrary fudge factor. The actual fog blending has to be done in the pixel shader, as we need to interpolate between the final resultant colour, lighting, texture and all, and the fog colour. This unfortunately utterly kills framerate on Intel integrated graphics chipsets; their poor little pixel pipelines just can’t take it. There’s actually a better way to do fogging than this on shader model 1.1 chipsets – the shader model actually supports fogging parameters – so I might implement a version for Intel chipsets that uses this mechanism and see if it improves matters.

I’ve also changed the building generation code: I’ve factored out an IBuilding interface and a BaseBuilding that can be simply inherited from to create different building types – I’ve renamed my existing building class UglyModernBuilding, and added a SimpleBuilding (a straightforward single block building). I’ve also factored out the actual geometry generation methods into another class, BuildingBuilder. I’m beginning to think Building.cs is getting a bit unweildy now, so there might be more changes/tidyups to come.

So, you’ll notice the polys/sec is well down: about 8 million polys per second now. I’m not entirely sure what’s causing this – turning any one of my individual effects off doesn’t seem to recover the framerate so it’s probably something more subtle. I’m not that worried about this right now, as 8 million polys per second is still pretty respectable, but I’ve got plans for more complex buildings pretty soon, which is going to eat into that budget pretty quickly, and necessitate either finding some more polys/sec, or implementing some sort of distance culling or LOD twiddling fairly soon.

Anyway, the latest bzr revision is 23; have a look if you like.

Cityscape – update 7

May 25th, 2009

So, one of the things the project I’m ripping off did to add variety was to make some buildings slightly yellow, and some buildings slightly blue. Yesterday’s update was still looking a bit homogenous, so in the spirit of ripping off everything, I decided to implement the same thing. And it now look like this:

Now, this took a bit of doing. Because we batch up all our rendering, we try to change as little state during rendering as we possibly can – so, for example, we could have added an extra parameter to the shader to add a tint to everything rendered. However, this parameter would only have been changable between batches, which means we’d have to batch like-coloured buildings together – which would be entirely possible, at the moment, but later on I plan to exploit spatial proximity between buildings to produce batches for culling, and having to produce three batches per region would add complexity and potentially reduce performance.

So, the other place we can pass in static data? In the vertices. Each vertex could have a colour attached to it – this way, so far as our batching is concerned, all buildings are still equal. The downside is, there’s no space in our current vertex format (VertexPositionNormalTexture) for this information. One possibility is to turn off lighting (the city is at night-time, remember?) but I’ve got other plans for that, too, so the best option seemed to be to roll my own vertex format – VertexPositionNormalTextureMod – which simply adds another Vector3 to VertexPositionNormalTexture. Then it’s just a case of changing all my buffers over to use this format, add the relevant extra data and make the appropriate changes to the shaders to do the actual tinting.

Pleasingly, this didn’t seem to affect framerates at all (at least, not on the number of buildings I’m working with at the moment), and the effect is quite lovely – it adds some much needed variety to the scene.

The latest revision is 21 in the repository – there wasn’t a trunk revision attached to update 6, but you can check out revision 7.1.13 if you want to have a look at that.

Cityscape – update 6

May 24th, 2009

Right, I’ve made definite progress towards getting things looking a bit better. It turns out that it doesn’t really matter than my buildings are ugly as hell, because buildings actually are ugly as hell – at least for the most part.

The first thing I needed to do was make the textures more interesting. And, again, I just went straight ahead and nicked the technique used in TwentySided‘s blog, althought it took some tweaking. In each window, I’ve darkened a random selection of pixels in the lower half of the window, and then addded a small colour modulation.

The next thing to do was to make the buildings more interesting. Currently, a building consists of a central main tower, and then on one or more of the building’s faces, a smaller sub-tower. This took a ridiculous amount of work to achieve, and several iterations of the maths concerned – and I’m probably still going to throw it away once I think of a nicer way of doing it. But it’ll definitely do for now.

The last thing this update adds is a movable camera – the spinny-round camera was handy for testing performance and getting an overview, but it was seriously limiting in terms of making cool screenshots 🙂 It’s pretty simple – we have a position, a rotation around the y-axis and a rotation around the x-axis. The WASD keys move the position, and the arrow keys affect the rotation. We generate a look vector by transforming a view straight down the Z-axis by the two rotations.

Oh, and I made the background darker and added a black base, to make things a bit more city-like. If I’m honest, the dark blue sky is the thing that adds most realism out of the entire update 🙂 One last screenshot:

Next, we make things a little less homogenous, and discover that it’s not as simple as we might think.

Cityscape – intermission

May 21st, 2009

I’ve not updated recently, but that doesn’t mean the project isn’t ongoing. I’ve been fiddling around trying to draw better buildings, but the problem – not to put too fine a point on it – is that everythign I’ve tried so far looks like total ass. I just can’t get something that looks convincingly building-like out of it. That, combined with the Cambridge Beer Festival sapping all my tuits, means that I’ve got very little to actually show you – there’s been updates to the repo you can look at if you like, but they’re not very exciting, and there’s some really, really ugly maths in there.

I think I need to take a few steps back and try some different approaches, but I promise I’ll have something new to look at soon.

Cityscape – 360 video

May 17th, 2009

Also, Sony Vegas Movie Studio is vastly better than Adobe Premiere Elements.

Cityscape – update 5.3

May 17th, 2009

Well, I spent ages fighting with Windows Movie Maker but couldn’t make it do what I wanted, and it seems Adobe Premiere Elements 2 really doesn’t like Vista, so the video I wanted to put up of this will have to wait for a little while.

This basic gist is that I’ve ported the project to the XBox 360, to finally make some use of that Creators Club account I’ve been paying for but getting virtually no use out of for the last couple of years. The code isn’t publically available as it contains a couple of dirty hacks and I haven’t cleaned it up such that it doesn’t affect the Windows codebase yet.

I hit a couple of… interesting issues. The first was that if you set invalid parameters on the vertex/pixel shader or graphics device state, then your first render call will bail out with a driver error indicating that something is wrong, without being terribly helpful about telling you what; it took some experimenting to figure out exactly what combination of parameters the XBox was happy with that didn’t also look like total ass. The other big problem I had was that the XBox version of XNA doesn’t support the GenerateMipmaps() function on textures, which means that if you generate your textures at runtime, you either have to downsample them yourself (and I’m not sure if XNA supports manually generated mipmaps – I’ll have to read into that some more) or have horrible shimmery textures. I eventually went for the third option, which is to cheat and use a premade texture generated by the PC version, and used the content pipeline.

Anyway, the upshot is that it all works – not hugely fast; getting the same sorts of numbers as update 5 on my laptop, but work it does, and that’s quite satisfying, at least.

I really will get some work done on making the buildings look more realistic next, I promise.

Cityscape – update 5.2

May 16th, 2009

Okay, the 16-bit/lack of Intel compatibility thing was bugging me, so I fixed it, and got, uhm, a few more polygons out of it as a result. How many? How about ~18.5 million polygons per second?

So, what have we done now? Well, I’ve changed the BuildingBatch class so instead of a single huge batch, it creates a bunch of smaller batches of a few thousand (the exact value is easily configurable – the parameter passed into UpdateGeometry() is the number of maximum number of vertices per buffer). This means I can both change the index buffer type back to 16-bit, which means it works on Intel graphics cards again and also squeeze even more performance out of the graphics card. The reasons why a single massive buffer is less efficient than a number of smaller-but-still large buffer is complex – it’s generally agreed that an optimal number of vertices is around the low thousands, though, and experimenting with my buffer sizes bears this out, and if you want a play, you can check out revision 15 from the repository and tweak this batch size in Game.cs – I’d be interested to hear what works best for your graphics card.

I’ve got another update coming shortly, but it’s sort of tangential to the main project, so I’ll stick it in another post.

Cityscape – update 5.1

May 15th, 2009

So, yeah. I figured out why it didn’t work on my NC10, and it’s for reasons I’d hoped I wouldn’t have to worry about just yet.

See, XNA and DirectX like to pretend that all graphics hardware is equal and can all do the same things and that. And it does quite a good job, so long as all you want to do is draw a few boxes, which is, uh, what we’ve been doing so far. Unfortunately, not all graphics hardware is equal, and actually, there’s some fairly big differences between them.

For example, index buffers. Index buffers are simply a list of numbers that represent indexes into your vertex buffer. You can pick between two formats – 16-bit and 32-bit. With 16-bit, you’re restricted to a maximum vertex index of 2^15, or 32,768 (because, for some reason, they’re apparently signed values, even though a negative index makes no sense). A 32-bit index buffer gives you indices all the way up to 2^31 about 2 billion – far more than you’re likely to need. Previously, I’ve been using 16-bit index buffers, as my vertex buffers have been small and so I didn’t need to capacity of a 32-bit buffer. However, with the change to one single, huge vertex buffer, I needed more than 32,768 vertices and thus switched to a 32-bit index buffer.

Unfortunately, the Intel drivers (the vertex shadey part of the equation actually happens in software on Intel chipsets, although they do have hardware pixel shader support) don’t seem to support 32-bit index buffers. I can create it, stick my indices into it and even successfully call DrawUserIndexedPrimitives<> – but nothing appears onscreen. Culling the number of buildings and using a 16-bit vertex buffer means it works fine.

Again, there are things I can do that will help this – split across several 16-bit index buffers, for example – and it’s actually not necessarily the most efficient thing to render using a single, massive vertex buffer, either: but there’s some optimisations I want to do later than will probably allow me to switch back to using 16-bit index buffers anyway, so for the moment, I’m sadly just going to ignore my little NC10 and stick to developing on machines with more grunt. Ah well.

Cityscape – part 5

May 15th, 2009

Get a load of this:

See that? That’s a 41×41 city, with 4 boxes per building – a whopping 80k polygons in total – running at our nice full 60fps. That’s over twice the polygon budget of the best of our previous versions, and dramatically more frames per second. How is such dark magic achieved?

Well, remember what we talked about last time? How graphics cards are much happier if you just give them a load of polygons and let them render them without interruptions? That, in a nutshell, is exactly what I’ve done here. Rather than rendering the buildings one at a time in a loop, we take advantage of the fact that buildings basically don’t move that often, and batch them all up into one big array as soon as they’re built. Then, instead of having to loop through a whole bunch of buildings, we just render the one buffer – much better.

Code-wise, we’ve had to do a bit of refactoring here – Buildings are no longer XNA GameComponents, and instead we’ve got a BuildingBatch DrawableGameComponent to handle that side of things for us. We create our buildings, add them to the BuildingBatch, then tell the BuildingBatch to update its geometry – whereupon it iterates through its collection of buildings, grabs their geometry and stuffs them all up in a single vertex/index buffer.

Inevitably, there’s some tradeoffs: by doing our heavy lifting upfront, we limit the amount of stuff we can do once the game is running. So, there’s no easy way to do, say, object culling or dynamic level of detail using this sort of scheme – the time taken to copy all the buildings into the batch buffer is about 150ms – not long, but much more than we’ve got available if we’re trying to render 60 frames a second. And as our buildings get more and more complex, we’re inevitably going to hit an upper limit for which this approach also no longer works – but I’ve got some plans for how to deal with that, too.

Additionally, our buildings are all looking very uniform – as there’s no way to change shader parameters between each building, there’s no way to, say, pass in a custom colour modifier to liven things up a bit – but again, there are ways around this that I’ll talk about at some point later on.

We’re up to bzr revision 14 now – and for some reason, this latest version doesn’t work on my NC10. I am investigating why and should hopefully have a fix soon.