E-Satanism   Leave a comment

How many devils can dance on the head of a 40-nanometre transistor?

On Saturday the 3rd I wanted to get shopping over and done-with quickly (partly so I could get on without interruption, partly because Lidl’s weekend half-price offers don’t always hang around for long, and it was a good one this week – low-fat mince – and I didn’t want to miss it), so I had to go out before having any coffee, as a pot wouldn’t stay warm for long enough, and it would delay me too much to drink it all before going.

But this meant I could come home and get on with my main job accompanied with a full cafetiere (not espresso? No, I wanted to use some normal ground coffee up while it was still nice).

I was doing some graphics programming, so this is going to be unavoidably technical. Oh well! Sorry if it makes even less sense than usual.

Background: I’m making a 2D engine. DirectX has got rid of all its 2D stuff (modern graphics hardware can do the same jobs faster in 3D) bar the GDI (despite NOD’s lobbying), and as the GDI’s rubbish, that means you have to do everything using a 3D API. I’m using Direct3D, because I usually use OpenGL and fancied a change and to re-learn it.

The upside is you can use all the 3D tricks like transparency, texture blending, vertex and pixel shaders, hardware-accelerated scaling and rotation (indeed, getting sprites’ pixels to appear 1:1 is the hard part) and so on.

So what I’m doing is rendering specially-blended light sprites to a screen-sized texture, and then using that texture as a lightmap for everything else.

The first problem: light textures were blurry. They were the right size, but they clearly weren’t mapping exactly 1:1 and some sort of texture filtering was kicking in. Usually the problem is simply that things are half a texel off (in Direct3D pixel centers are whole numbers, but their corners are offset (-0.5, -0.5) from there, so when you care about direct mapping you have to take that into account because texture co-ordinates don’t work that way. See this if you care.), but after a lot of fiddling with pixel offsets I’d not solved the problem.

Eventually, after much searching and by luckily noticing differences in other parts of the code that did similar things properly, I spotted two mistakes: I’d not loaded the texture with the appropriate “this texture isn’t a power of two” flag (it was 100×100), so it was being filtered up to whatever it was being stored as (128×128, I’d guess), then filtered down to the original size when being rendered. But on top of this, I was only passing (X, Y, Z) co-ordinates, so something was being transformed somewhere. I started passing a RHW co-ordinate of 1 for each vertex, and ta-da! Proper sharp light-map textures.

Then I started fiddling with vertex shaders, and getting the GPU to transform the vertices and calculate their lightmap texture co-ordinates. Unfortunately, it wasn’t calculating quite the same co-ordinates as were used in the normal fixed-function pipeline; the lightmap seemed slightly squashed. But when I made the program fullscreen the problem went away.
Long story short: in windowed mode, the clipping plane is slightly smaller than the window size (because of the title bar and borders), and that is what you request, not the view size. So mapping clip-space co-ordinates onto the lightmap texture causes it to be squashed because it’s the window size, not the view size. An intermediate step transforming from model to pixel co-ordinates, and using those to calculate the lightmap texture co-ordinates before transforming the vertex to clip space.
If you can find out the exact dimensions, in pixels, of the clip-plane you could make the texture that size, which would be faster.

Both cases of the devil being in the details.

So that was fun (really!), and a decent day’s work on the project.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s