Welcome! This is the public, open development site for The Nut, a game about building things (every things) being developed by one person, me. I'm doing this because there doesn't seem to be a lot of information around about this process and its many issues. |
Home
Nocturne
Woops! I never meant to take such a significant break. The Nut got foundered in some difficult problems, and I went off and did a bunch of other stuff for a few years. I decided to go with a simpler, more readily achievable game, and it came to me in kind of a flash. I can't remember why, but I was thinking of an extraordinary scene in My Neighbour Totoro, a Japanese film by Hayao Miyazaki. The focus of the film is on these two tiny little girls, I think around five and three, that have just moved into the country with their father. It follows them naturalistically, allowing us to learn more about them simply by what they encounter and how they behave, which is remarkably true to children of their age. The twist is that they're neighbours to a forest spirit, a great big bear monster called Totoro, that they befriend. Well, they plant a bunch of nuts and seeds Totoro gives them in their garden, and one night he brings them out to make them grow. What follows is startling, awe-inspiring, and almost religiously intense. Unfortunately I could only find it with the English dub, which plays down some of the sounds and voices.So why not make a game out of that? A game where you sing and roar and clap and the world changes around you? That's the basic idea of Nocturne. I don't plan to make a story out of it, just give you a sandbox where you're a disconnected voice who can manipulate your environment by making noises into a microphone, sometimes guided by other voices who teach you new songs to create plants and change the world around you. This presents a pretty linear set of pieces that need to be developed to make it into a game. They are: I'm currently at 2, looking through fluid simulation papers and adapting them to shaders.
|
24-bit Dithering
A widely-held misconception is that 24-bit colour (16.7 million colors) is enough to make gradients imperceptible to the human eye. This may be correct if your gradients are red, green, and blue. But any more complex gradient, or any compositing of gradients, will very quickly become visible and annoy the hell out of anyone who can see it. Correcting for this in computer graphics is kind of stupid easy. Take a texture, fill it with random values. When you are about to return the color from the shader, do this: float4 output; ... output.xyz += (tex2D(RandomSampler, ScreenPosition.xy * Scale).xyz * 0.5) / 256; return output; Where "Scale" is some factor that splats the texture evenly over the entire screen. This randomly pushes components up or down half a 24-bit RGB boundary, so that when it's subsequently rounded, it acts as a dither. Here's an example of the result: The banding on the green is harder to see (as it's one of the primary RGB colors, and so is closer to the ideal) but it's certainly there; these are both very close to ideal conditions for gradients that minimise the error, and to me they're plainly visible. Normally you'd need to do all sorts of fancy tricks to hide patterns in the dither or to avoid a weird feeling when the camera moves that the screen is covered in dust. But because this is so subtle, you don't need to do anything else. One step does it all. Five minutes to implement. (Yes I'm working on The Nut, I just saw a post on The Witness blog I wanted to comment on.) |
Voxels on my brain
Whoops! Got involved in a weekend project that became a weekday project; a voxel engine. There's some pretty sweet tech behind this, but my favourite point is when I got it to this stage: Yes, making it look worse is a huge improvement. Because the earlier one took the voxels and transformed them into triangles. The latter renders the voxels directly using raytracing. It took no time at all to do, and is actually so fast (on both the PC and the XBox) that it looks completely viable as the rendering method of choice. But it IS a weekend project, and it doesn't have a purpose, so I'm setting it aside now and getting back to The Nut. I'll still plug away at it on weekends, but that's it. |
Generic Constraints
No screenshot today since my circuit simulating code is doing little more than pumping out some matrices, but as I was working on the matrix library I thought I'd talk a bit about .NET generics. Before this year, from late 2001 my language of preference was D. D's templating system is close to C++'s, in that it's little more than a macro system. Most importantly, it's not type safe; it's never possible to prove that it's correct, and instantiating it in the wrong way can easily break the code (this is the primary source of C++'s dreaded spagghetti template errors). One interesting power, though, is static if blocks, where you can optionally insert code based upon certain specific conditions: struct Vector(T, int D) { static if(D == 3) T CrossProduct(Vector other) { ... } }; It's a powerful mechanism, but it makes maintaining the code confusing because it's harder to read and it makes documenting the code very difficult. A more structured mechanism could handle the most effective and important uses of this while making it clearer to the reader what's happening. One way to partially do that is how .NET does it, by using constraints: struct Foo<T> where T : IEquatable<T> ... The only way you can use a type parameter is by the constraints you've defined; so I can't just use "T a = ..., b; a += b;" and hope that the user supplies a type that can handle arithmetic. This means that the generic constructs are proven, and you know they'll work with any valid input. Good stuff.When you do something like this, it behooves oneself to have a rich and consistently applied interface set so that the constraint system can be used effectively. You also want to use methods to implement operations on your objects rather than something silly like Java's Math static function library class, which would be useless to generics. Guess what? .NET has only IComparable and IEquatable as effective constraint supplements, and it has a dumb Math static function library class. The constraint system remains useful, but its uses are very specific, and not nearly as important as the uses it has locked out. The upshot is that I would like to have something like: class Matrix<T> where T : INumeric, IArithmetic, IFractional... Which would then allow me to cast from numbers, perform addition, and be assured that division won't be unduly rounded. I have none of that, and implementing something like this requires tricks. For the matrix library, what I'm doing is deriving from an Implementation class I've defined that has some common functionality - it has a static dictionary of implementations by type, a function to return one or a dummy implementation, and some other folderal. The implementations have a set of methods that take and return objects, and in their bodies will perform the desired operation in a type-specific form. In the types themselves, I perform common checks, then grab an implementation and execute it like so: static MatrixImplementation Implementation { get { return MatrixImplementation.Find(typeof(T)); } } public Matrix<T> Multiply(Matrix<T> other) { if(other == null) throw new ArgumentNullException("other"); if(other.Rows != Columns) throw new ArgumentException("other.Rows must equal this.Columns for matrix multiplication."); return (Matrix<T>)Implementation.Multiply(this, other); } This is a bad hack - it necessitates code duplication with all its sundry problems and it makes understanding the code more difficult - but it's what's necessary. It's a shame that .NET is still so crippled by its earlier version limitations and underconceptualization. One workaround I would like to see is declarative interfaces - that is to say, I claim that this type implements this interface, and if this actually is true, then I can cast an object of this type to this interface even though it wasn't declared to be a member of it. But OO languages are not very good about understanding that library implementors often forget important things that have enormous consequences to their users, who are the ones the language should be serving first as 95% of the code will be written by library users, not implementors. Alas, language design is still treated as an art rather than an engineering problem where you can absolutely declare that one way to do things is better than another. |
Octopus Taming
Here we go (and here I realise Google reencodes pictures after uploading them). Better curves, better tangents, little exposed wire ends. I'll revisit this code much later to optimise the interpolation and give more variety to the attachment points, but it's mostly done for now. Now to make those wires actually mean something by starting in on Electronic Circuit & System Simulation Methods. The book, that is, not the movie adaptation. |
Benefits of anti-swimming with shadowmaps
I wanted to get a YouTube! account working along with the movie-posting workflow, so I made a quick video showing the importance of anti-swimming your shadow maps: The core problem is that you need to move your shadow projector with the viewpoint in any complex or large environment, but if you don't anti-swim you're going to cause aliasing artefacts aplenty. The solution is simply to round the target offset in shadow space, as with this pseudo-code: Texture ShadowTexture; Matrix BaseShadowMatrix = LookAtMatrix(from: -LightDirection * 100, at: Origin, up: UnitY) * OrthographicMatrix(...); Vector3 ViewTarget = ...; // A point in front of the viewpoint camera. Vector3 ShadowTarget = BaseShadowMatrix * ViewTarget; ShadowTarget.XY = Round(ShadowTarget.XY / ShadowTexture.Size) * ShadowTexture.Size; Matrix ShadowMatrix = BaseShadowMatrix * TranslationMatrix(ShadowTarget); Simple! |
Electric Octopus
The tangents are the worst, but getting that right is a fiddly process. A Flash prototype I made several years ago used anchor points that I could direct to face away from the component as appropriate; it then chose tangents by extrapolating those to a distance appropriate to the length. I should use something like that. The good news is that this code is oddly very fast and can update the wires smoothly. |
Welcome!
Hello there, and welcome to the website. I just thought I'd put up a screenshot to show that there actually is a program being discussed here: I've mostly been working on the rendering engine and menu system. It's very simple, with elements that are easy to peel off as needed. So I could make the background a pre-blurred cube map, not blur the reflection, and remove shadows. On the components side they're all built in 3DS using shapes that can be triangulated at lower detail or replaced with simpler approximations, like switching out a cone with a texture map for the coils. The LED digit thingy uses a baked ambient occlusion map process I'm working out that allows the entire thing (aside from coils) to be drawn with a single rendering call, so simplifying that further would be difficult. The simplistic background is also intended to bring attention to what you build rather than getting the eyes or attention lost in pretty sparkly lights and spinning things going WHEEEEEEEER and a clown bouncing in front of the screen. That was my first idea, but this is much easier to build. |
1-8 of 8





