It is satisfying to feel my understanding growing, little by little. Each new task forces me into situations where I hit bugs, errors and crashes and, while trying to pull out as little hair as possible, I gradually figure out where I’m going wrong and what the individual API methods, parameters, enums and so forth mean, and how they are supposed to be used.
This time around I wanted to figure out how to render the same cube in multiple locations and give each instance its own unique positional data and animation parameters, which meant I had to figure out how to draw my triangles instanced, and how to pass individual parameters for each instance to the vertex shader so that the cubes could each be rendered with their own rotations. And as before, I have tidied the code up even more. It’s nice to see a very simple beginner’s 3D engine taking shape, little by little.
Some things I learned:
- Quarternions – not specifically the maths behind them, but their usefulness in representing a 3D rotational state. I also found handy methods to create matrices from a quaternions, which is what you need if you want to actually make use of the quaternion in terms of representing the vertex’s rotation based on the quaternion in question. It is because of these that my cubes now rotate in 3D space.
- Drawing instanced triangles – I pulled bits of information from around the place for this one, as it wasn’t particularly clear in any of my usual sources, or perhaps I was just impatient and if I’d done things in the order that the chapters are laid out, I’d have figured it out quicker. In any case, I learned how to use an instance buffer, and how it relates to the vertices it represents.
- Passing per-instance data to the vertex shader – This was a real pain, as it requires a deeper understanding of how input layouts work, and how their parameters represent the vertex shader’s function signature. Given that I lack (or lacked) the understanding, it took a bunch of trial and error and a lot of back-and-forth on a couple of different forum threads, both on gamedev.net and gamedev stackexchange, to finally understand what I was doing wrong, Now, I’m still by no means an expert, but I feel like it’s a little bit clearer now, so that if I want to pass more data into a shader, I’ll be able to with a bit more ease next time.
- DirectX debugging – You know, if I’d learned this one first, I’d have suffered a lot less during this task. I had to set my project to allow native debugging, and I had to initialize my device to enable the debugging flag. Once I did this, the debugger output window magically started telling me, very precisely, what I was doing wrong whenever my initialization code crashed! Very cool.
Oh, if you read my previous post, I also worked out why DrawIndexed was forcing me to specify three times the number of triangles as I actually had. Turns out the index buffer refers to the indices of each vertex, not the indices of each triangle. Who knew?
So here we go, a screen capture of my instanced cubes. To see them move, you’ll have to grab the source code and run it! Note that I’ve hosted the code on Github now, which is better for me, because source control is better than zip files.