I’ve been on holidays for about two and a half weeks now, and in a few days I’ll be back at uni, doing what I do. For the most part my holidays have been rather unexciting though I’ve been working on a few things to pass the time.
Just before the holidays started I decided to take a look at Haskell. To most this would probably seem like an odd move, as Haskell isn’t exactly the most mainstream language, and from what I’ve read, it’s never quite been able to escape realm of fringe languages. But that hasn’t stopped Haskell-aficionados from trying. I’ve heard quite a lot of good things about Haskell and functional programming in general, and I’ve noticed a few functional concepts sneaking into languages I already know (D is a primary example) so being able to understand and use functional concepts effectively, I think, would be very useful.
Needless to say, Haskell is very different to anything I’ve ever programmed in before. Learning Haskell is so far a lot like learning programming from scratch; there are so many new concepts to get my head around, and the mode of thinking required to use Haskell is leagues different to what is required for any imperative language or even stack based language. It’s quite a strange feeling to be honest. So it was (and still is) baby steps. I set up my environment just how I like it so I didn’t feel completely lost: sublime set up to trigger make, a make file to compile/run Haskell programs and a terminal on the side for messing with a Haskell REPL.
I started with basic math, made some very simple functions, then learnt about lists and tuples, and some standard functions for manipulating those. So far not so bad. I’m only just starting to understand how to use the fold* functions but still not so bad. Then I moved on to pattern matching and guards, and currying. These are a bit different to what I’m used to but I got the hang of these pretty quickly. Then it came to trying to write actual programs. Everything that has something to do with input or output is wrapped in something called an IO monad, which took some getting used to. And when I went to write my fibonacci sequence generator I hit a bit of a wall where my regular and efficient for loop method didn’t quite work. I tried first to write it as a recursive function but quickly found that the way I was trying to do it was O(n^2) complexity and took exponentially longer the larger the element that I wanted. I went back to try and understand the standard functions a bit more and ended up with an implementation that used foldl and a tuple to store the accumulators.
fib x = fst $ foldl (\(a,b) _ -> (b, a+b)) (0, 1) [1..x]
I’m sure there’s a much better way to iterate over a sequence than generating a list, but this is what I came up with given what I had, and it doesn’t freeze up when I give it a large number. It’s not exactly complex, but I’m happy that I was able to understand some functional concepts enough to implement something. And despite my troubles, I can definitely see how one could use Haskell to do much more complex things.
As well as trying Haskell, I also started a small project that initially was to see how far I could get with an OpenGL application without copy pasting code from all over the place and googling tutorials. It went pretty well for the most part. I had to consult documentation a couple of times just to get argument types/orders for some functions right (I always forget the arguments to glTexImage2D and glVertexAttribPointer), but I was able to get things rendering pretty quickly. I started with the popular red triangle and quickly moved on to cubes. I managed to get a grid of cubes each with their own colour and transform matrices rendering pretty quickly. Also to jazz it up, I rendered all the cubes twice with a different scale and with transparency enabled.
I was pretty happy with my progress so I decided to try and smarten it up a bit. Initially, every cube was a separate draw call with two calls to glUniform* for colour and transform. So I went down the instancing route. I created two array buffers, one for colours and one for transform matrices, and I modified my `Draw` function to fill those instead of uploading uniforms. I modified my shader to accept colour and transform as attributes instead of uniforms and finally replaced my numerous draw calls with two instanced draw calls (one for the opaque cubes and one for the transparent cubes). This gave me a HUGE speed boost, as expected.
After that I started messing with framebuffers and postprocessing. During my experimenting I finally figured out how to recover world coordinates from the depth buffer. This let me do some pretty cool things.
So that’s just messing with colours based on depth and time + a very basic outline using fwidth on depth. With a bit more messing around and some googling (I’d given up on not googling by this point) I managed to implement gaussian blur. It took some playing to get it performing alright, but here’s an example of what I managed.
I set it up so that I could perform multiple passes of the blur kernel. After some optimisation, I managed to get about 20 passes of a 5×5 gaussian kernel at a descent framerate. In the above screen shots, I also added some tinting to make it look a bit nicer. I also tried modifying the postprocessing shader to just displace fragments instead of blur them. These are the results.
To bring it all together, I’d like to point out that I used Haskell to calculate the 5×5 kernel.