GraphicsMarch 15, 2006 12:42 pm

So the last few months (agh!) have had me coding monkey like at work and at home. The work stuff is finally getting there - we’re hitting beta in a fortnight. The home stuff is also finally getting there - that quality bar is hard to reach. Especially when the app you’re writing is so damn addictive you spend hours playing, getting lost in a four dimensional space looking for just one more funky attractor.

Clouded planet

(I hadn’t realised how much better the image quality was compared to my prototype until just now - looking at the Clifford in the previous post with no AA, no autocontrast etc. Yay!)

Anyway - interesting notes on the journey so far:

  • Chip away. Small goals keep you travelling in the right direction. You can only finish if you start.
  • Always start with something that works. The sample Managed DirectX GUI, for example, is horrible in places - but at least it works!
  • Don’t be scared to ditch stuff. My funky 6D GUI widget proved to be confusing. So I’ve nuked it for a 2D one. Mere mortals can use my software again.
  • Time stuff before you ‘optimise’. Drawing 100000 points is slow, right? Well not as slow as pulling a 2048x2048 texture from the graphics card, modifying it then chucking it back.
  • When things are hard, stop. Mysterious bugs become obvious after a bath, a walk in the park or a glass of wine.
  • Don’t overgeneralise. That 2D convolving interpolator wasn’t required in the end.
  • Look into existing solutions. That overly complicated special autocontrast routine is actually a gamma correction model in disguise.
  • Don’t be put off by competing products. There were MP3 players before the iPod.
  • Show off to people. Having others cooing over the software massages the ego and keeps you going.

So, now the hard bit. Getting to the destination and not getting sidetracked. So many of my projects die at this point - I start to worry that it’s going to fail when out of my hands, at least when stuff dies it’s failed due to me. A strange thought process, and one I’m trying to train myself out of.

For now though another snapshot for the road:

Red funnel

GraphicsDecember 3, 2005 9:35 pm

After a month of hectic Real Stuff I’ve finally got around to doing some of my own coding. And, as usual, it’s a work colleague’s fault.

I was speaking to Paul about general enthusiasm for coding and realised that sometimes naivity is great. When you first started coding and you’d just write something for the hell of it. You didn’t worry about overall ‘quality’ because you were doing the best you could imagine. I remember writing platform games, GUIs, Lorenz attractors - well, Paul has some bloody great attractor images from a few years ago. It managed to reignite my interest in the subject so I spent a couple of hours with some C#, SdlDotNet and Forms and managed to get a little app to render different types of Clifford attractors:

cliff

Nice, huh? Just 2d for now, and fixed to the single kind of attractor. Not a bad start though. And the best bit was the mindset I put myself into. Who cares if it’s one class? Heh, I don’t have to rename the GUI elements, so I won’t. It’s resulted in a hideous looking 508 lines of code, but a fully functional app. Now I can go back and rewrite the same functionality with a higher ‘quality’ bar and with more extensibility.

Graphics, Visual StudioOctober 3, 2005 10:38 pm

After using C++ in anger for about four years I’m constantly troubled by coding inertia - when you know you should create a new class/factor out a base class/extract a method - but it’s just a little bit too much effort. Especially when combined with CVS and multiple Visual Studio 6 workspaces/projects. Yagh!

So? Well, C#, Visual Studio 2003 and Subversion working together almost gets rid of this inertia. The only problem remaining seems to be me. I still put off (or at least overestimate and dread) what end up as simple, mechanical refactorings.

The motivation for this upbeatness is that I just managed to rip out the hardcoded particle generation and force application from my particles engine and add fountains that move in the wind in about 10 minutes.

fountains

Tomorrow, hopefully, I’ll get them reacting sensibly to some implicit surfaces (well, some kind of floor, to be precise). Oh, and they look better moving. Honest!

GraphicsSeptember 29, 2005 5:50 pm

Bumbling on with the particles engine has led me to pixel shaders in C#, using HLSL. I even have a book. Up until today however, I’d just fiddled with existing examples.

The code already had the alpha blending and coloring of the particles as a very, very simple pixel shader. It needed more per particle variables to find their way down to the shader (e.g. particle lifetime, coloring function etc.) - this requires using a custom vertex type and a corresponding vertex shader that mangles it into a sensible input for the pixel shader.

This is what I ended up with (the odd variables at the top are for EffectEdit, an application that comes with the DirectX SDK and compiles and displays effects. Definitely worth using to find mistakes in the shaders!):

// Stuff for EffectEdit
string XFile = "tiger\\tiger.x"; // model
int BCLR = 0xff202080; // background
float4x4 gTransform : WORLDVIEWPROJECTION;

struct VS_OUTPUT
{
float4 Pos : POSITION;
float4 Color : COLOR0;
};

VS_OUTPUT VS(float4 position : POSITION, float4 color : COLOR0)
{
VS_OUTPUT Out = (VS_OUTPUT)0;
Out.Pos = mul(position, gTransform);
Out.Color = color;
return Out;
}

float4 PS(VS_OUTPUT input) : COLOR
{
float4 result = { input.Color.r, input.Color.g, input.Color.b, 0.5 };
return result;
}

technique Monkey
{
pass P0
{
// shaders
VertexShader = compile vs_1_0 VS();
PixelShader = compile ps_1_1 PS();
}
}

Then the C# code is just:

m_effect = Effect.FromFile(m_device, "../../effect.fx", null, null, ShaderFlags.None, null);

m_device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Black, 1.0f, 0);
m_device.BeginScene();
m_effect.Technique = "Monkey";
m_effect.SetValue("gTransform", m_device.Transform.World * m_device.Transform.View * m_device.Transform.Projection);
m_effect.Begin(FX.None);
m_effect.BeginPass(0);
// Draw stuff
m_effect.EndPass();
m_effect.End();
m_device.EndScene();
m_device.Present();

And yeah yeah, it’ll just render something in a slightly wimpier color than the color specified for the vertex (due to the 0.5 alpha). The idea’s there though - more can be added to the VS_OUTPUT and vertex structure and the appropriate calculations can be done in the appropriate shader. With hindsight, many calculations that are per-particle can be done at the vertex shader level. Oh well.

As for the stuff that’s actually drawn, well the call to DrawUserPrimitives now uses a custom vertex array (all 6 vertices!):

struct MyVertex
{
public Vector3 Position;
public Vector2 TuTv;
public int Color;
}
private MyVertex[] m_quad_verts = new MyVertex[6];

The only slight faff is setting up the VertexDeclaration (not the VertexFormat, I believe that’s for the fixed pipeline, not shaders). This is done in the renderer construction, around the same time as constructing effects, fonts and the like:

VertexElement[] decl = new VertexElement[] {
new VertexElement(0, 0, DeclarationType.Float3, DeclarationMethod.Default,
DeclarationUsage.Position, 0),
new VertexElement(0, 12, DeclarationType.Float2, DeclarationMethod.Default,
DeclarationUsage.TextureCoordinate, 0),
new VertexElement(0, 20, DeclarationType.Color, DeclarationMethod.Default,
DeclarationUsage.Color, 0),
VertexElement.VertexDeclarationEnd
};
m_device.VertexFormat = 0;
m_device.VertexDeclaration = new VertexDeclaration(m_device, decl);

Slightly scary looking, but it’s just setting up offsets into a datastructure. The important thing is that the VertexDeclaration matches the layout in memory as MyVertex.

Graphics, Game writingSeptember 28, 2005 10:46 pm

The (small) game I’m currently working on needs some spit and polish. I’ve always wanted to write a simple particles engine. Looks like an obvious match to me.

My current tech is C#, Managed DirectX and some HLSL. The particles are alpha textured quads using DrawUserPrimitives. A tiny particle class manages some dumb Euler integration (I’ll crank this up if and when…) and everything, well, seems ok.

Currently I’ve got three sets of fixed particles launched up into the air and subjected to the whims of gravity. They start with random angles and magnitudes, so you get a rough fireworks display:

3 fireworks

Unfortunately I now need more information in my vertex structure so the particles can die off at different times - I’m already using color, texture and position. There’s a gap in my understanding between fuzzy-away from memory structures-managed-C# and hard-and-cold-HLSL. Time to tread into the unknown…