16BPP.net
 
Book Review: Unreal Engine 4 for Beginners

I like to call myself a "hobbyist game developer."  One, because I'm very interested in video game design (mechanics, art, story, structure, etc.) and development (software implementation, physical hardware, etc.).  Two, I don't do it professionally.  And three, I kind of always approach things the wrong way.

One of my game design "documents."
One of my many fantastically
detailed game design docs.

Sure, I do like to draft up design documents of how I'd like the game to function.  But I have this really bad notion of "I'm going to do everything by myself, and do it The Hardcore Way!"  Which always ends up (probably,) being that wrong way.  What is The Hardcore Way™ you might ask?  That's the little evil voice inside my grey matter saying such adorable things like "You should build your own game engine & framework around low level libraries!  It would be way more efficient and fun!!"

Well, I don't think he's completely incorrect.  But it's something I need to stop doing if I actually want to make games.  A few weekends ago I was participating in the Linux Game Jam 2017 where I made Pucker Up.  I decided to build the thing in Nim w/ SDL2 and raw OpenGL calls.  And since Nim is quite young, I also had to make things for myself like a geometry and collision system.  There's a common joke in the game dev scene, is that when you're at that tier, you're not even making a game.  For a good two thirds of the jam, that is what all I was doing; no actual game mechanic implementation, just framework stuff.  It sucked.  And because of that time sink, I had to forgo adding a lot of content to Pucker Up that I wanted.  All I could do were the basics.

I've always had the idea of sitting down and taking some time to learn an off the shelf game engine.  But my experiences with the LGJ2017 is what prompted me to actually now try that.  I know Unity is very hip and hopin' with the young and popular cool kid indies.  Though playing games made with the engine, I have always had some issue with it running under Linux.  So: pass.

What other engine has a massive following, loads of documentation, spectacular tooling, great performance, works on Linux and commercial success?  Unreal.  As a bonus, Epic Games is nice enough to let people peek into the source!  Pretty cool.

Unreal Engine 4 for Beginners Book CoverI'm also someone who likes to learn from taking classes or reading books.  I'm not totally adverse to reading online tutorials, but I don't mind paying money for words.  After taking a few minutes to query the Amazon for "Unreal Engine 4 book,"  I found this; Unreal Engine 4 for Beginners.  It's written by a David Nixon.  He looks quite young and it seems like this is his first book that he has ever written.  Props to him doing that so early in his life.  I couldn't find too much more about him online except for this snippet:

David Nixon is a professional software developer and amateur game developer who holds a degree in Computer Science from Florida Atlantic University. He started his career developing websites and providing SEO services for companies nationwide. He then dove into the world of mobile gaming. Recently, he worked as a web developer for a major SaaS company.

It was $50 for a print copy or $10 for a kindle.  Being cheap, I went for the later option.  Here's a special feature about the Kindle Edition of this book: You cannot read it in the Amazon Cloud Reader; you have to use a physical device.  Normally when I'm reading a book that I assume has code samples, I like to read it on a computer and have it side by side with my text editor.  I tried using emulation systems such as Shashlik and ARChon, but none of them worked.  I wanted to try to contact the author, asking him why this was so or if he could provide me with a non-kindle copy, but he doesn't have a personal website setup or any public email address.  I'm lucky enough to have a tablet where I was able to read this on, but this really sucks for programming books.

Anyways, so what is actually in the book?  Here is the table of contents:

  1. Getting Started
  2. Basic Concepts
  3. The Level Editor
  4. Actors
  5. Blueprints
  6. Players & Input
  7. Collisions
  8. User Interfaces
  9. Audio
  10. Additional Topics

All of the chapters have the same structure:  Introduce the chapter topics, divide into sections, then divided into further subsections, maybe a small example, and a quiz at the end.  That's it.  Rinse and repeat nine more times for nearly five hundred pages.  That many pages might also seem like a lot but to be honest, I think I read the entirety of the book in less than an hour and a half.  If you're wondering how I did that so fast, take a look at page 20:

 

Page 20 of Unreal Engine 4 for Beginners
This page can be freely read on the Amazon page via the "look inside," thingy.

 

I think this page is the one that has the most text on it, and it's not that much.  Many of the other pages contain a lot of spacing for headers, paragraph breaks, images, section spacers, etc.  If this book were to be in something like pt. 12 font size Times New Roman, I think it could be pegged at 150 pages maximum.

As for the actual quality of the content, there is not that much I can really say for it.  It was an underwhelming read for me.  Aside from the quizzes there was no engagement with the reader whatsoever.  Sure there were some examples but they were sparse and all of them were with using the Blueprints Visual Scripting (more on that later).

I bought this book expecting it to be a sort of in depth tutorial.  Every other game development book I have bought in the past 10+ years has been walkthrough where you build a game from the ground up.  Unreal Engine 4 for Beginners left me with nothing other than a few common mechanisms (e.g. how to do simple character movement).  Most of the content too was just mentioning what something does for you; not really much how to use it along with other things.  The entire time I felt like I was reading simplified reference documentation.  Nothing was detailed or highly constructed.

Now about the Blueprints.  I'm not going to lie and say I'm fond of visual programming languages; I am very much so not.  All of the entire code for this book was with Unreal's Blueprints.  I was hoping to do some of that C++, but nope.  It was dragging nodes and connections all of the way.  I can understand the importance of visual scripting languages for people who work with Unreal yet don't have a traditional programming background but it was a real disappointment for me.   On top of that Chapter 5, which is dedicated to introducing Blueprints was 1/6 of the entire book.  And by no means is it a good introduction to how programming works.  Most of the sections of this chapter would simply state "This is an <x> node, it functions like so."  Most sections didn't have an example tied to them to better explain how the statement would work.

And… That's all I can really say about the actual content of the book.  There was nothing that really made me a massive impression on me or gave me a good insight on how the Unreal Engine works or good practices with using it.  Most of the information presented could have been scoured from the official UE4 documentation.  In fact, I would say that this book was nothing more than a light reference manual than an actual tutorial.  I really wanted to have this book show me how to build a game with Unreal; it did not do that.

I don't feel as if I got my money's worth out of this purchase.  It was only $10 so it's not too much out of my wallet.  But do avoid dropping $50 on the hard copy.  I will cut Nixon some slack because this is his first book and does seem like a recent graduate.  I wish him the best.  He does also offer a course on Udemy about UE4, but I have not paid for it so I can't judge the quality of the content.  

My conclusion is that I don't recommend getting it.  I'll be looking for a different Unreal book in the future.


Tags: Computer Graphics, Video Games, Book Review

I Wrote an Article on How Random Art Works

As of the past year Glitchet has been one of my favorite parts of the week. It's a mini newsletter that covers all sort of futurism and computer arts thing that I'm interested in. A While back (seven months actually), I contacted the curator of webzine and told him he should do an article on Random Art. I didn't hear back from him until a few days ago.

He asked me if I was willing to write a piece on how it works. Everything was fresh in my mind from my Nim port of Random Art, so I agreed. Over the weekend I came up with this. It gives you a simple overview of how the process works and where these pretty pictures come from. If you don't understand anything, I'm sure you'll be able to grasp something at least.


Tags: Computer Graphics, Nim, Art, Procedural Generation, Tutorials

HTML5 Canvas Bindings for Nim's JavaScript Target

It seems like every one to two weeks I've been writing a new package for Nim.  I've been playing around with the JavaScript target.  There is some basic stuff there in the dom module for HTML manipulation but I noticed something very important was missing; the canvas tag.  So well, I added a thin wrapper for it (GitHub mirror).  It's available under the html5_canvas package in nimble.

When I first heard about HTML5 and read the spec a little, I think one of the most important things that was added was the canvas tag, and along with it a JavaScript API for all sorts of drawing operations.  Interactive content for the web that was being made with technologies like Flash and Java (applets) could now closer to the browser level (and have better performance to boot)!

The only thing is that I don't really like writing JS code; it's my least favorite language out there.  But you know we live in a time where you don't have to write JavaScript to write JavaScript anymore!  While Nim's JS backend is still marked as experimental I think that its nice enough where we can still make some cool stuff with it.

I tried to keep the API as close as possible to the one listed in the Mozilla docs.  Though I did have to make a few changes.  One of those in particular are the fillStyle and strokeStyle getters and setters.  The problem with these two fields of CanvasRenderingContext2D is that they can be one of any three different types (see here).  Nim being a strongly typed language wouldn't let me put those properties right under the type ... object definition.  Luckily though there is still a way to keep the API so it looks like we're setting a field instead of having to add a setFillStyle() proc.  Taken from the source, look a this:

proc `fillStyle=`*(
  ctx: CanvasRenderingContext2D;
  color: cstring
) {.inline.} =
  {.emit: [ctx, ".fillStyle=", color, ";"].}

# Can do this now!
ctx.fillStyle = rgb(255, 0, 255)

But as for the getters I had to do this:

proc fillStyleColor*(ctx: CanvasRenderingContext2D): cstring {.inline.} =
  {.emit: [result, "=", ctx, ".fillStyle;"].}

There's one for Gradient and one for Pattern as well.

For some extra fun, I ported over my 3D Canvas Cube from Dart (another language that compiles to JS).  I've put the source up in my toybox repo.  What's also pretty cool is that the compressed JS output from dart2js was about 90 kilobytes, where as Nim's compressed JS is around 20 kilobytes!  Originally when when did full imports (i.e. import math) I was getting 124 KB compressed, but when I changed to selective imports (from math import Pi, sin, cos, floor) I was able to drastically reduce the size.

 

 

I was able to get the animation to work by adding a mini proc to wrap JS's setTimeout() function:

proc setTimeout(function: proc(); ms: float) =
  {.emit: ["setTimeout(", function, ",", ms, ");"].}

If you're bored with 2D graphics and want to do something 3D in Nim (and in the browser), take a look at stisa's nice WebGL wrapper.

Here is the link to the repo for this again (GitHub mirror).  It's also on nimble under html5_canvas.  Have fun!


Tags: Computer Graphics, Nim, JavaScript

Random Art in Nim

A Random Art Example

 

Edit (Jan 30th, 2017): I written an article on how Random Art works.  You can read it here.

Have you ever heard of Random Art before?  If you don't know what it is, the short and skinny is that it's a program that will generate some really stunning images using a randomly generated math equation.  That's what the image above was made with.  The original program was written by Andrej Bauer.  The Random Art website uses an OCaml program that been compiled to JavaScript.  Unfortunately the source for that is not publicly posted (which is a shame because it makes some of the best pictures), but a simple Python implement is available.  Going off from that, I decided it port it over to Nim and add support for rending with OpenGL (and make a few other changes I see fit).

Well... actually I ported that to C++ (& Qt) first about a year ago, then I did another port over to C# four months later.  The C# one was a little more interesting because it was a distributed rendering system leveraging cloud services and RabbitMQ; I ended up using it on a film I was working on.  Pretty cool.  Those... I don't really feel comfortable sharing the source to right now.  But I'll give you a Nim implementation instead.  : P

You can find the application over here on GitLab (or GitHub if you prefer it).  To compile the thing, your going to need GLFW installed as well.  It can run into two modes: CPU bounding rendering and GPU (via OpenGL).  There is a lot more info the in the Readme, but here is the usage message:

 

Usage:
  ./random_art [input] [options..]

  input : a path to an equation file, or provide `stdin` to read input
          from standard input

  Options:
  -r, --renderer : cpu | opengl
                   render on the CPU or with a GPU (using OpenGL)
  -s, --size     : <width>x<height>
                   the dimension of the render, must be a positive int
  -b, --bounds   : <xMin>,<xMax>,<yMin>,<yMax>
                   the bounds to use to render, must be a float
  -o, --output   : <filename>.png
                   the file to save the render as, must end with .png

 

If you run the application without providing an equation, it will think up one for you.  Writing your own equations has this Scheme-like syntax.  It's pretty easy to understand, but also to parse.  The equation below makes the image to the right.

A Simple Random Art Example

 

(mul
  (var y)
  (mod
    (sum
      (var x)
      (var y)
    )
    (const 1 0.7 -0.1 0.95)
  )
)

 

I plan on working on this some more down the road.  You can already see some of my changes showing up (e.g. an alpha value).  I'll keep you guys posted.  Once again, the code is available here (GitHub mirror).


Tags: Computer Graphics, Nim, Art, Procedural Generation, Projects

Ray Tracing Book Series Review & Nim First Impressions

This is going to be a little different than only a usual book review; in fact, it's going to be a review of three books (that were part of a series).  They are Peter Shirley's Ray Tracing mini-books. If you've been following my blog for the past few entires you may of noticed that I've been on a bit of a Nim binge lately.  I've only been at it for about two months.  So in an effort to learn the language better and to go through the books at the same time, I decided to write the book's code in Nim instead of the original C++.  It turned out to be smoother than expected (though with some troubles along the way).

 

What is Nim?

I first heard about this language from the /r/programming subreddit.  Every few weeks or so I'd see a link entitled "Nim v0.x.x released," or something like that.   I didn't take a look into it until I saw a few of those and said to myself,  "Alright, I think it's time to actually take a look at it."  Since then, I've been doing most of my free time stuff in Nim.

The best tl;dr I can make to describe Nim would be "It's a python-ish language that compiles down to C/C++."  There's definitely a lot more to Nim than just that.  Reading from the project site is what really piqued my interests other than the native backend and syntax.  There are features that give you a lot of control over the language.  For example, you can use constructs such as macros and templates to define your own extensions to the language.  One of it's most powerful aspects is how easy it can talk to C/C++ because well, Nim turns into that at the end of the day.  Nim is able to take advantage of most of the existing C/C++ libraries with minimal effort.  There already exist bindings for things like OpenGL and libSDL.  There's even a framework to do web programming too.

I've seen a fair bit of comparisons with Mozilla's Rust and Google's Go, but I don't want to talk about that. The community is not crazy active like many other languages; it's more cozy if anything.  Keep in mind that Nim is still very young, yet it's highly impressive what they've been able to do without any massive corporate backing.  Yet.

 

Finding a Ray Tracing Book

Yeah... it looks like crap.
We were trying to do that famous Kajiya image.
It didn't turn out so well for me.

In my last semester of university I took a grad level course in Global Illumination.  With the Ray Tracer that I made, I wasn't too happy with the final results.  I wanted to give it a second shot.  So I headed to Amazon to look for a book.  Yes, yes... I know there is a lot of good information out there already free on the Internet, but for some reason I just seem to learn better from reading in a book format.  Anyways...

I saw a book called "Ray Tracing in one Weekend," at the top of the search.  It caught my eye because:

  1. It was short
  2. It was inexpensive, three bucks (that's less than a cup of coffee)
  3. The code was in C++, and OS independant
  4. It mad the promise of building a functional Ray Tracer
  5. It came in a three part series.  If I didin't like the first one, I could always ditch the second two books to find something else

I was sold.

 

Book 1 - Ray Tracing in One Weekend

Ray Tracing in One WeekendAt the beginning of the book you will first have to set up your rendering infrastructure.  All of the code makes no use of external libraries (except for one in the second book).  That means having to build a 3D vector class, Rays, and other geometric goodies.  Nim does come with it's own built-in 3D vector object, but I decided to forego using it so I could get the "full experience."

Now you might be saying "So how did you save renders then?" PPM.  On standard out.  Yeah, it's not my favourite image format either, but it got the job done and it is probably the simplest format to export without any extra libraries.  And if you have a tool like ImageMagick converting it to something that people actually care about (e.g. PNG,) is trivial.

What's really nice about this book is how the author goes through step by step with you to build each component one at a time.  I've had one too many tech books that I've slapped down $50 (or more) to only give me half-assed partial snippets and no walkthrough.  Peter Shirley did a very good job of avoiding that.  The code in this book had very few errors to none at all; a very great thing.  With the amount of code in the book, I'd say you should be able to go through it in about three to six hours time.

I really wish I read this book before taking my course in Global Illumination.  It would have made my life much easier and saved me a load of time and frustration.

A render from the main test scene

 

Book 2 - Ray Tracing: the Next Week

Ray Tracing: the Next WeekThis is the book in the series that I learned the most from, but it is also the one that cost me the most agony and time.

A lot of that could contribute to the fact that I was porting the code to a language that I was new to, but this book did have it's share of errors and missteps.  For example, there were a few times where Shirley forgot to mention to make a change to something; one of the things that drives me up the wall when reading a tech book.  Despite all of this I was able to get through the book, but it took way more than a week (the titled lied to me,) and I had to manually trace things through in the original C++ repo more than I should have.

Annoyances aside, this book goes over things like texture mapping (on spheres only), perlin noise, interpolation,  BVH trees, and other stuff.  What's more exciting is that actual emissive lights get introduced.  In the first book there wasn't really any lighting, it was all ambient and sun-like.  Now, we had real lamps.  There are also a lot more scenes constructed in this book than the last.  Including that famous Cornell Box.  There is an external library introduced, but luckily it's stb_image.h; one of those magical single header file libraries.  Binding it to Nim was a sinch.

I'd only recommend reading this book if you really are interested in Ray Tracing beyond what was presented in the first.

A Perlin Noise Render.

 

Book 3 - Ray Tracing: The Rest Of Your Life

Ray Tracing: The Rest Of Your LifeThis one ended up being a lot more math and theory based, as you refactor the Ray Tracer into a Monte Carlo one.  And... that's really much it.  Every single scene that is rendered is based around the Cornell Box.  It would have been nice to have a little more diversity rather than replacing a box with a glass sphere or making one a mirror-like surface, but it doesn't take away from what's talked about.

What's really nice about this one is that it was a much quicker read for me than the second, less frustrating, the images rendered way faster, and ended up looking much better to boot.  There was only one problem; in the final chapter the author did that thing again where he forgot to tell you to update something.  I don't think it would have been so bad if I did the thing in C++ instead of Nim.  I'll get to why later...

All in all, I would actually recommend this one over the second just a little bit more.  Some of the things in it could fly over your head, but there were next to no errors in the book (just one).

 

Book 3 Render

 

Book Series As A Whole

As I said before, I wish I had a copy of the first book before going into my course where I had to build a Ray Tracer.  It covers many of the necessary basics plus some extra fun things.

All of the issues that I bumped into in the second one were quite jarring.  I've sent a laundry list of them to Peter Shirley.  He's been very responsive to all of my emails and has fixed issues with his books in the past.  Expecting him to clean them up during the Thanksgiving-Christmas-Hanukkah-Kwanzaa-Festivus-New Years blitz (a.k.a. November & December) is not a fair demand, but he should eventually.  Once these get fixed up I think it will be a much stronger series.

Except for the errors, the source was of a good quality.  It was mostly clean, readable, and simple.  The only thing that I didn't like was the organization of the code.  I know you get what you pay for ($3) but it wasn't really that well structured.  It made the software engineer in me hurt a little.  The code was also provided as one big lump in a GitHub repo.  Other tech books I've read have been nice enough to divide up the progress from each chapter in their own separate folder.  This would have been good to do instead.

I'm a little saddened this didn't go over other things like the BRDF or a bit of ray marching.  It would have been better to have more in the third book than only a Monte Carlo renderer.  I also don't think the title of the last book is really accurate if you choose to do more Ray Tracing after reading it.  This book series should not be treated as a replacement for a university course; I learned a lot more about ray tracing and computer graphics at school.

With these negatives, I think the positives out way them and make the series worth the money to pay for it.

 

What it was like doing this in Nim

There always seems to be a relevant XKCD for every situation.  In the realm of compiled languages Nim really made me feel like I was flying again.

As I said before, I did this book in Nim as an excuse to learn the language better.  I've made a few toys with Nim prior, but I felt working on a larger (iterative) project would force me better understand the language.  At the end, I did learn a lot more..

Translating between C++ and Nim wasn't that difficult at all.  The book's source wasn't complexly constructed in areas of OOP, and Nim's OOP functionality is still fairly basic, so there was almost a one to one correspondence with what I would have to write.   When there was a C++ class, I would typically turn that into a type CLASS_NAME = ref object of RootObj.  It would hit most of my needs but one time it came back to bite me in the butt.  Looking up witch Nim proc to use in place was something a pain, as Nim's documentation isn't the best at the moment.

Things always felt very fluid and fun for me.  It felt a lot like I was writing Python code that was type checked.  The operator overloading is also some the easiest I've seen in any language.  And because of having to use stb_image.h I got a taste of how to work with the foreign function interface.  Heck, I even ended up doing a proper wrapper of the library.

So how that ref object of RootObj got me...  I would translate all of the C++ classes using this.  That would create reference counted pointer to an custom object I defined.  Upon object creation, which would be stored in dynamic memory.  When I was first working on the Cornell Box I got this:

A bad Cornell Box render.

Yeah, that's pretty bizarre.  That back box is off to the right (through the wall), yet it's shadow and diffuse reflections are on the room walls and floor.  After pulling my hair out form running through the code I finally figured out that ref object of RootObj was what perpetrated it (or how I used it), along with this snippet:

 

method hit*(ry: rotate_y, r: ray, t_min, t_max: float, rec: var hit_record): bool=
  # I thought this was copying the vec3 data, but it wasn't.  It was copying the pointer...
  var
    origin = r.origin()
    direction = r.direction()
    
  # origin and direction are modified after this which caused the issue...

 

I wasn't creating a copy of the 3D vector, I was modifying the original vector…  After that I changed that vector class over to a simple object.

Another problem I had with Nim is that it doesn't yell at me as much as C++ does.  When I was working on the last book, my renders were coming out like this:

A Cornell Black Hole...

"How the heck is that glass sphere turning into a black hole?" went through my mind.  This also made me spend too much time chasing the errors down in the wrong places.  Partially, this issue stemmed from Peter Shirley not reminding me in that last chapter to update the dielectric::scatter() method.  But when I changed the prototype for the base method material::scatter(), Nim didn't yell at me to fix the child methods too.  It just used the base method instead, which would return black.  When you change a base method's prototype in C++ the compiler will remind you to change all the children too.  For once, I wish I was being screamed at. 

There is also some other odd behavior I want to look further into too.  In the second book we built a BVH Tree hierarchy to store the scene info, as to make the ray collisions much faster than checking each object one by one.  Storing the hittable objects in a sequential list was faster than searching the BVH Tree.  It could be my implementation of a bounding volume hierarchy, but I'm sure it's functionally correct.

As for the performance of the Ray Tracer.  It's not as fast as the C++ one it was ported from, though it is  still pretty good.  If I were to have written this in Python (what Nim resembles), I think the images would still be rendering well into my 80s.  The port that I have is definitely not the most riced thing possible.  There's probably a ton of other optimizations that can be made.  But here are some comparisons:

Some Benchmarks

Commit was: "fd77499840b4a93441b4c9d772258da85fecc265".  Resolution was 1280x800.  "ns," stands for number of Rays/Samples per pixel.  All were done on a Desktop Intel i5 machine, single core w/ no threading.  The Linux "time," utility was used to benchmark.  I think the performance slowdown with book 2's Nim implementation has something to do with the BVH node.  I'll be investigating it and hopefully fixing it.

 

Nim is still very young so I don't think it's fair to be overly critical, and I'm also very new to the language myself.  I will continue to do more things in Nim as I really like it.

If you want to learn more about Nim here is the website and here is a good place to start.  You can find the Nim Ray Tracer here (GitHub mirror).  And if you're interested in the books, here are their Amazon pages:

  1. Ray Tracing in One Weekend
  2. Ray Tracing: the Next Week
  3. Ray Tracing: The Rest Of Your Life

 

A Cornell Box which is all glass.

 


Tags: Computer Graphics, Nim, Book Review

An OpenGL Shader Example in Nim

It's been a while since I've posted something.  It's mainly because I've been busy for the past couple of weeks.  I've had to put my C# Networking Tutorials series on hiatus for the time being.  But I do have plans to finish it with about three more articles (they'll cover things like async).

In the meantime, I've been playing around with this language called "Nim."  I first heard about it from /r/programming.  It was popping up every so often so I decided to finally check it out about two or three weeks ago.  So far, I've found it very pleasant to work in despite being fairly young.  I've been reading through Peter Shirley's Raytracing Minibooks but writing the code in Nim instead of C++; it's been pretty good so far (I'll post about that on a later date).

You probably can guess that I really like graphics.  So one of the first things I looked for were OpenGL examples.  I had a lot of trouble trying to find a solid sample that showed you how to use shaders, so I made one myself.  You can find a link to it here, but the source for it is also included in this post.  I've tried to keep things as simple as possible, so there is duplicate code (e.g. the shader construction code), but it makes it easier to follow.  You can compile the program with nim c nim_opengl_shader_example.nim.  I built this on Linux so I also had to add in a {.passL: "-lGL".} call at the beginning.  Change it for the platform of your choice.   It also uses this GLFW binding, though it should be simple to change it out for SDL2.  It should show a colourful rotating hexagon.  You can change it's speed by passing in a non-negative float at the command line, e.g. "0.5," or "10".  Pass in "0" to make it not rotate.  If you want anti-aliasing, add "aa" to the command line arguments.  Here is what it looks like:

Edit: The official opengl package handles the linking for you.  If you're using a different OpenGL binding (like those from nimios,) you'll need to add the passL in manually for your OS.

 

OpenGL Shader Example in Nim

 

And the source:

 


Tags: Computer Graphics, Nim

Blit, A Retrospective On My Largest Project Ever

Before I begin, you can find the source for Blit over here.

I want to talk a little bit about a project I worked on every day from July 2014 till the end of August 2015. You may have seen a few entries about it back on earlier posts; that project was something I called “Blit.” If you’re wondering what Blit was, it was my attempt at trying to make an Animation focused art program. It was pretty ambitious for someone like me at the time.

 

Blit's Main Window

 

There were two main reasons why I started to work on it:

  1. Back when I was an undergraduate, I was part of a student group were we had to do these things called “major projects,” each year if we wanted to retain membership. They usually are of a technical nature (programming & engineering). This is where my initial drive came from
  2. I’ve never worked on a “large,” or “longterm,” project before. Everything else I’ve done up till that point were small things like class assignments, course projects, or tasks for my internships. I had friends who had worked on their own projects for two or three years straight and made some really cool stuff. I really wanted to be able to tell others (mainly prospective employers) “Yeah, I’ve been working on this thing for over year. Want to take a look?” Other than just “having something,” I also wanted to learn how to manage a larger and lengthier project.

The “major project,” was something that was pretty easy to fulfill. But for the second I did something kind of stupid, but worked well for me. I told myself “Alright, I’m going to work on a project that will have a 365 day long GitHub streak.” In reality, git streaks are a silly thing to track progress. I was working on Blit in a private repo, so the outside world would not see my streak at all. I feel bad for the people who have the need to maintain one. For me it was a reminder to build on Blit each day. It worked.

Whether it be programming, logging issues, source code cleanup, design & planing, writing documentation, etc., I had to minimum goal of one meaningful commit per day. Normally I would spend an hour on Blit per day (more on the weekends). I would keep at it until the kitchen timer to my side beeped. Somehow that little thing was able to keep me focused for a straight hour.

 

So What Is (or Was) Blit?

I’ve always been someone who’s liked art and programming. Especially combining the two. One of my favorite genres is pixel art, or sprites as they are also known. I’ve dabbled in making a few other art programs before, but nothing like this.

Originally Blit supposed to be only a sprite animation tool that had a modern look and feel, but my ideas for it grew greater (*sigh* feature creep). There are many other sprinting tools out there like GrafX2, Aseprite, (and other 2D animation programs like TVPaint). I’m not saying that it’s wrong that they make their own GUI toolkit, but it feels kind of odd. I really wanted to bring these types of programs out of the days of the Amiga. After doing some initial research, I settled on using Qt. Here are my reasons:

  1. It’s cross platform. I work on a Linux system, but I want my Windows and OS X friends to be able to use what I make
  2. It’s a C++ library; my native tongue. But there exists bindings to other languages, such as Python
  3. There’s a lot more to Qt than just widgets. It really is a fully featured desktop application framework
  4. It has a massive community around it and it’s very well documented. So if I ever ran into trouble I’d be able to find some help

Before I move any further, you might be wondering where the name “Blit.” came from. Since it had a focus on 2D graphics, the name came from the “Bit blit,” algorithm. I used to do a lot of programming with libSDL, so the function SDL_BlitSurface() has been burned into my brain.  I thought it would be a cute name too.

I also wanted to keep more of a “traditional animation,” approach to Blit. Instead of drawing on images there were “Cels.” Layers were called “Planes.” Instead of a Dope Sheets I had “Exposure Sheets.” I didn’t call it “onion skinning,” but “turning on the Light Table.”

 

Starting Out

As mentioned before, I was focused on sprite animation (originally). I wanted to keep things as easy as possible. While I did consider using Qt’s native C++ libraries, I decided on making the program in Python with PyQt. Scripting languages are typically much faster to write code for. I felt as if I would be able to get more done in less time. I didn’t think that there would be too many computationally intensive procedures to worry about. In the event that I needed some performance boost, I could always write a C/C++ extension for Python.

After choosing my tools, the first thing I did was draft some design documents. These included a user interface mockup and an initial file format structure. I started to log tickets on the GitHub issue tracker. I had an miniature road map to start from. Within a month and a half, I was able to load up one of my files into Blit, do a little simple Cel & Frame editing, and then save it. You couldn’t do too much with it, but I thought it was a good starting point.

 

Blit's Python Version

 

During my initial research of Qt, I discovered something called the “Graphics View Framework.” There were a lot of widgets that I had to custom make such as the Timeline or the Canvas; it made my life much easier. It really is one of the nice features of Qt. If you’re making a heavily graphical application you should take a look into it.

Despite being able to get a basic animation loaded, edited and played back, I was starting to run into some issues with the development language: Python. I had issues with things like circular imports and nested imports (python files imported from many directories deep). I don’t want to go into the details of how they were affecting me and the project, but all I can say is that they were driving me up the wall. So I devised a solution: Switch to C++.

Now, switching development languages is not always something that’s advised. But at the point where I was, it was feasible to do and would possibly have a better impact on my project. Nested imports are a non-issue in C++ and the circular imports are fixed with simple include guards. On top of that, I wouldn’t have to use PyQt’s bindings anymore and Python would not be a performance bottleneck since it would be gone. Working at my usual hour a day pace, it took somewhere between two and three weeks to port everything I had to C++. I wasn’t happy about losing that time to work on new features, but I think it was a better choice in the end.

I didn’t entirely ditch Python & PyQt. If I needed to prototype a widget, I would use those tools. It helped to realize ideas pretty quickly, then later I would integrate it into the C++ source.

 

Feature Creep, “Future Planning,” and Broadening Horizons

In the first couple of months that I was working on Blit, more ideas started to pour into my head of what it could or should be able to do. We all know what this is; Feature Creep. Whenever I though of a cool new thing I wanted to add, I usually weighed the cost of adding it in within my current milestone, the next, or burring it in the issue tracker. This is where I developed the “Future Planning,” tag. If something popped into my head, almost 95% of the time I would not mark it under any milestone and put it under that tag. It was a good way for me to tell myself “Alright, I think this would be a good thing, but I need to focus on other stuff right now.” This worked actually pretty well for me. At all times, the most populous tag in my issue tracker was the “Future Planning,” one.

 

A Pen & Eraser Tool

 

Around 100 days into the project, I felt like I had a good direction that I was going in. I was nearing the end of my (second) internship and I would be left with nearly two months before classes would begin again. With all of this free time, I set myself the goal of “Be able to draw a bouncing ball animation and export it as a Spritesheet,” before Christmas hit. I achieved that.

 

100 day long streak

 

A Bouncing Ball (spritesheet)

 

By this time you could move Cels around on the Frames, move the Frames on the Timeline, and adjust their hold values. I think I focused more on the staging of objects rather than editing them. To work on this shortcoming, I decided to start work on a Tool interface. I had the idea that editing tools should be plugins and people should be able to write their own; a very common idea in art applications. Instead of only “put pixel,” and “erase pixel,” I added line/shape drawing, filling, and was working on a soft brush tool.

 

Fun issues with debugging the Color Palette Widget

 

When I got back to school I fulfilled that first goal of passing it as a “major project,” in my student group. It was well received for what it was at the time, a very simple pixel art animation tool. Though, I started to think more beyond simple spriting. Not only do I consider myself a fan of Animation, but someone who really enjoys making it. I started to ponder “What if Blit could be used for all sorts of 2D animation, not just pixel art?”

 

200 day long streak

 

I didn’t think it would be too hard to add a camera hookup to the program (something that I’ve done with Qt before), so Blit could be turned into an application to do pencil tests, capture paper drawn animation, or even stop motion. My rule became “If it’s Bitmap based, Blit should be able to do something with it.” I also thought that there wasn’t a good free (both as in beer and speech) software solution to 2D computer animation. TVPaint, Dragonframe, and FlipBook were used a lot in the animation department. I can understand the expensive cost of them for professionals and that it’s niche software, but it really sucks for students who want to learn how to animate, but already were paying a small fortune for their college tuition.

To make Blit more generic, it had to undergo something I called dubbed “The Grand Refactoring.” The whole animation module was like this: an Animation owns an XSheet, which owns a list of Frames, where each Frame owns a list of Cels. No reuse. This was good to get started with, but pretty bad since in the real world animation is reused all of the damn time. So I devised up this system instead:

 

The new and improved Animation module

 

As it would force me to fix up almost every single thing in the program that touched the Animation module (including the file format), I set this to be its own “half milestone.” It took about a month and a half to complete. It really sucked not being to add any new features for that time; only endless refactoring. At the end of that, all the logic was in the code to be able stage the same Cel across multiple Frames, or instance a Frame multiple times in the Timeline. Though, because I was focused on fixing things up, I didn’t add in an interface where the user could actually reuse Cels and Frames. If they wanted to, they would have to edit the sequence.xml file. So it was there, it worked, but wasn’t usable by the layman.

While taking classes and juggling other (smaller) projects it sometimes became difficult to make meaningful contributions to Blit. I tried to stick to my “one hour a day rule,” but that became hard. Also, refactoring isn’t fun. You don’t get to see new features, you’re restructuring stuff that already exist. You might also break things and then have to spend time fixing them. It’s hard to stay motivated when nothing is new or exciting.

My brain was fried after writing code for my class assignments. I found that (better) documenting the source code, reviewing issue tracker tickets, and revisiting design documents wasn’t too hard. If I recall correctly there was a two week stint were that was all that I did.

 

GitHub Streaking...
I cut that one really close.  I swear it was a meaningful commit.

 

Despite all these speed bumps, I got to do something really cool with Blit at the end of the year. If you’ve read some of my older blog posts, you may have seen this thing I made called MEGA_MATRIX. For those of you who don’t know what it was, it is a 24x24 LED Dot Matrix display. I actually developed it in tandem with Blit during the early days of the application. Anyways, at the end of the year my college hosts what is essentially a campus wide show and tell day. I thought it would be neat If I could let people doodle animations in Blit, then upload them onto MEGA_MATRIX. Turns out it was. I made a special fork of Blit called “The MEGA_MATRIX Edition,” where I only let users draw in two colors (red and black), preview their animations, and then upload them to an Arduino to drive the display. One of my friends said it was his favorite thing at the festival because “[I] practically made a hardware implementation of Mario Paint.

 

The MEGA_MATRIX Edition

 

 

Altered Scope, One Full Year, and the End of Development

At the beginning of 2015’s summer, I was off to my next internship. During the day I would write C# code for a rendering infrastructure. After work I would exercise, watch some TV, play a few video games, but also work on Blit, for well, at least an hour a day.

 

301 day long streak.

 

After “The Grand Refactoring,” and the MEGA_MATRIX Edition I was able to get a few more features out of the way. Changing the Canvas’ backdrop color, pixel grid, selective playback, a color picker tool and more. One of my favorite additions was onion skinning (I called it the Light Table). Thanks to the newly redesigned Animation module, it actually made it pretty easy to implement.

Then sometime in mid July I hit my second goal; hold onto a GitHub streak for one year straight.

 

The full year streak
I thought it was going to be 365 days long, turns out 366 is what fills up all of the blocks.

 

The code for Blit was starting to get really huge at this point. I still was able to manage it myself, but it started to become a bit of a chore too. I also spent a lot more time refactoring and fixing existing code rather than working on new features. I feel like I lost a little of my drive then. As my two initial goals were achieved I could have stopped here. But for some reason, I didn’t want to. I kept on pushing.

My internship came to an end, I had a week at home, and then I was off to another internship. All of the previous places were I interned let me work on outside projects if I wanted to. As long as it wasn’t during work time, with work equipment, or a competing product I was free to do what I want. This time around, my employer asked me to stop working on outside projects all together.

 

3001 commits

 

While I felt that work on Blit was starting to go stale I still didn’t feel to happy about having to quit development. I could have worked on it in secret, but that didn’t feel right to me. So, right before leaving for the first day of work I made an early morning final commit to the Blit repo. It was kind of poetic that my ending streak was exactly 400 days long.

 

400 day long streak

 

In the month that followed, I was bummed that I wasn’t able to add an interface for the reusable Cels/Frames, the Brush and Resize tools were still unfinished, no work on multiple planes was ever done (Cel layering existed though), but worst of all, I feel that it sucked when trying to make sprites; the original goal of Blit. I still had ideas popping into my head. Such as using FFmpeg to export animations as animated GIFs. All I could do is just scribble them down on some note paper and file it away for when I was done with my current internship.

So four months down the road I was done with my final practicum. Did I start back working on Blit? No. The previous month was pretty turbulent for me, as well as the next couple. It was my last semester at college and I was more focused on graduating. I still had ideas coming into my head for Blit, but they would go into the issue tracker instead of the code. I felt that I was way too out of it to startup work back on Blit. I also realized how much of a behemoth the source had become. Thus I decided to put it on hiatus indefinitely.

 

Final Lookback and the Future

Almost everything I’ve done is a learning project for me. Some of I learnt very little from, others a lot. Working on Blit taught me so much more about Qt than I ever wanted to know. Hell, in the process of developing Blit I spotted a minor bug in Qt and was able to submit a(n) (accepted) patch to the project. That was one of the more rewarding moments, as I’ve never contributed to a major open source project before.

But the main thing I gained from Blit was learning how to manage/handle/organize a larger project. I was never involved with issue tracking, documentation, and design so much before. As stupid of an idea it was to maintain a year long GitHub streak, it somehow worked for me. It was fun to show off the streak to my friends, it was really there for me to motive myself.

While building Blit, one the things I always wanted to do was work on it with other people. Though, I kept it in a private repo I always had the intention of releasing the source code when I was done with some of the core features. While many of my friends thought it was interesting, I couldn’t find anyone else who wanted to work on it. I always made sure to keep good documentation of the design and source code for this reason. I really wish I had others to help me with this, not only so that I could have had Blit in a much further state, but also so I could learn how to collaborate with others better too.

It’s now been a year since I last touched Blit. At the beginning of this past Summer there was a monkey on my back to figure out “the future of Blit.” I know I wanted to release the source for it, but I’m not sure where I want to go with it. In the past year Dwango released OpenToonz and Krita has added some animation tools. Both of these have much better drawing capabilities. It’s hard to compete.

I have a small desire to restart work on Blit. For example, adding a camera connection to shoot paper drawn animation or working on some FFmpeg exporting. But I have other priorities right now. If I had to do it again, I would want to write Blit in C# instead of C++. I’ve grown to love C# a lot in the past year and development in it is much easier than C++, and performance is still pretty good. I really hope that QtSharp can get off of the ground sometime soon.

If you want to check out the source for Blit, you can find it over here: gitlab.com/define-private-public/blit. If you want to see some of my fabulous source documention, it’s at: https://blit.gitlab.io/SourceDocs/. And if in the slightest chance that you’re interested in working on Blit, please contact me.

To end with, here are some stats:

  • 97 source code files
  • 8,175 lines of code (95% C++)
  • 400 days of contributions
  • 364 issues tracked
  • 3,151 commits
  • 91,528 additions, 65,617 deletions
  • An unknown amount of users
  • and 1 developer (me)

 

The Bouncing Ball

 


Tags: Computer Graphics, Art, Arduino, Projects, C/C++, PCBs, Blit, Animation, MEGA_MATRIX

Making Fractal Trees in Blender

Fractals have been something that I've found really intriguing since high school, though, I've never taken too much of a stab at trying to generate them.  For a few assignments back in my CS1 class we had to use Python and the Turtle package to draw some.  These were done mainly to teach the concepts of recursion, state, and using geometry in computer programs; pretty basic stuff.  I imagine that almost everyone has had to use Turtle at some point in their CS coursework, and incidentally, has drawn a fractal.

Last year I was taking a course in Global Illumination.  We had to do two projects over the semester.  Write a ray tracer (throughout the weeks) and explore a graphics related topic of your choosing.  For that second one, some students chose to look into ray marching or real time raytracing.  I wanted to look at fractals some more.

After talking with one of my friends, he told me to look up something called "L-Systems."  The full name is "Lindenmayer System," and it's the magic behind fractal generation.  In a nutshell, the idea behind it is to create a grammar (yeah, one of the CS theory ones) and give each letter (or variable) an action (e.g. "draw line forward 10 units," or "rotate 45 degrees clockwise,").  The simplest example I can think of is the Cantor Set on the L-System wiki page.

Even though I was already making a 3D graphics program for the class, I decided writing a Blender script would be the best.  Here are some of my reasons why:

  1. All the tools, libraries, and rendering infrastructure is already there.  I only need to focus on the tree logic
  2. My Ray Tracer has a .obj file loader, so all I need to do is export it from Blender as a Wavefront object
    • On top of it too, I was also able to export it as a .stl, load it into slic3r, and materialise it on my 3D printer.  Pretty cool!
  3. Blender is widely used and some others might find my script useful

So working in Blender there isn't a 3D Turtle object you can rely on to do the drawing.  But instead, you have to work with Matrices.  The basic idea of what you need to do is this:

  1. Chain a bunch of matrices (appending and popping to/from the end of a list works well).  Most of what you'll need will come from Matrix.Translation() and Matrix.Rotation().  These are equivalent of the Turtle movement commands forward() and left()/right()
    • Make sure you chose one axis as your "forward," direction.  For my script, I always made translations in the Z+ direction.
  2. Compute the result of the matrix chain, by taking the leftmost (first) matrix, then multiply it by it's neighbor to the right.  Rinse and repeat until you have one matrix left
  3. Create a new 3D mesh (e.g. via bpy.ops.mesh.primitive_cylinder_add())
  4. Blender will consider the newly created mesh as the "currently active object."  So multiply that new mesh's world matrix by the computed matrix chain:
    • bpy.context.active_object.matrix_world *= computed_matrix_chain
  5. And voila!  It should be in the location and orientation you want it.  From here you can go to a deeper level of the fractal or move back up.  Don't forgot to pop those matrices off the end of your chain!

If you're still a little bit confused, take a look at the git repo over here.  All of the necessary code is in l-system_tree.py.  It's pretty simple and you should be able to follow along.  My L-System grammar is quite uncomplicated:

  • A → BCDE
  • B → A
  • C → A
  • D → A
  • E → A

"A," also means "draw a branch," whereas "B," "C," "D," and "E," mean rotate about an axis (each one is different).  Each variable also checks the current depth to make sure that it isn't going on forever, though only "A," really needs to check for that.

There are a few other configuration options that I threw in (e.g. TWIST) so I could make some different looking trees.  Below is an example of one of the trees that I made with VARIATION_MODE turned on; it gives the tree a much more natural looking feel.

 

Natural-ish Fractal Tree in Blender


Tags: Computer Graphics, Art, Procedural Generation, Tutorials, Python, Blender

Status Update 7
So for the past two or three months you may have seen me working on My C# Networking series, but for the past couple of weeks I've had to take a little bit of a break from it. The first reason why is that I have a few other important things in my life that I need to take care of right now. The second is that I actually want to take some time off and focus on a few other smaller things.

One of those "smaller things," is this final project I worked on for my Computational Geometry class a year and a half ago; I wanted to release it publicly. My goal was to make "A teaching tool for other students to learn the Monotone Polygon Triangulation algorithm." The old version was buggy, but I finally got around to cleaning it up. If you want to play with it, you can find it here: https://16bpp.net/page/monotone-polygon-triangulation (source code is available too on GitLab).

Tags: Dart, Computer Graphics, Computational Geometry, Status Update

Book Review: Mazes For Programmers

Mazes For Programmers by Jamis BuckI remember first seeing this book in an newsletter from the Pragmatic Bookshelf a year ago.  It caught my attention because it seemed like a publication that was on a very niche topic yet fun.  I didn't get a copy of it when it was released because I was busy at the time with schoolwork (and then forgot about it).  Though a month ago I was down in on a weekend trip to D.C. and I saw it in a bookstore I visited; I decided to buy a copy since I have a lot more free time right now.  Being interested in game development, computer graphics, and procedural generation, I found this book to be a delight to read.

 

The Code

All of the code for each chapter (except for a POV-Ray file) is in Ruby.  My best guess why the author (Jamis Buck) chose to use Ruby is that he is a former contributor for the core team on the Rails projects.  His GitHub page is also littered with Ruby projects, so I assume it's what he's most comfortable with.

If you have zero experience in Ruby, fear not, neither did I before reading this book.  Not knowing Ruby should not be an obstacle to understand what is going on.  As long as you have a lot of experience with many different languages it shouldn't be difficult.  Most of the source reads like Pseudocode.  Only a few times did I find myself checking the Ruby documentation (e.g. Array.sample, or Ruby Blocks) to understand something unknown.  If you are looking to get familiar with the syntax of Ruby (or only to get your feet wet), I think this is a good start, but keep in mind that author's goal is not to teach you Ruby.  Personally, I would have preferred the sample code to be in Python, but that's just me.

Of the tech books I've read, I've gone through many that have given me incomplete code examples (i.e. snippets) or code that breaks on running it.  It's one of the most frustrating things out there!  Buck and the rest of the team that worked on this project did a very good job on making sure all of the code worked as it should.  I wasn't able to find a single issue with anything.  All of the code provided were complete examples.  A+

Everything builds on top of what you've done in the previous chapter, so I don't recommend skipping around.  Lots of inheritance and code reuse, which is good!

 

The Content

Weave Maze (with Kruskals's Algorithm)Most of the book's pages are dedicated to the generation of mazes in a 2D space.  In the beginning he talks about some simple algorithms like Binary Tree and Sidewinder, but later moves on to other methods that generate some more interesting maze designs.  There really isn't much of anything in the realm of solving mazes outside of discussing Dijkstra's Algorithm.  I really wish there were more included.

There was more covered than maze generation for rectangles.  I found the sections on polar, triangle and hex grids really fascinating, but the Weave grids were the best in show (to me at least).  There was also some pages for fitting mazes to odd shapes and designs.

In the later chapters Buck does show you how to generate a three dimensional maze (and talks a tad bit about 4D), but I found the representation of them to be a little difficult to follow (little red arrows are used to shift dimensions).  I would have favored something with 3D graphics instead.  That's a lot more complicated than 2D drawings and beyond the scope of this book though

One thing that was really well done was how algorithms were described with step-by-step drawings.  More books really should be doing this.  I've seen it too many times were only a single image or two are given when really seventeen should be provided  to show a run-through of an algorithm.  This made the algorithms really easy to understand without having to read any code.

3D Maze

 

 

Extra Cool Things

Something that I really appreciated is he included some code on how to display the mazes in a terminal window.  These only work for the 2D rectangular mazes (the early chapters), but I still found it nice since I love ASCII art.

At the end of the book there are two appendices that cover the maze algorithms explained.  The first one is an overview of what each algorithm does along with a picture of it.  The second one goes over some benchmarking/statistics of the various algorithms; very useful.

 

Final Thoughts

This book was worth the money I paid for it.  I don't think I'll be using anything I've learned in it immediately, but I know I will sometime down the road in my video game endeavors.  It's not a definitive source on mazes but a really good starting point.  I really would have loved some more chapters on maze solving.  One on interacting with the puzzles we generate would be cool too, but that falls more into game programming.  It has also done something for me that I've never expected; opening me up to Ruby.

It's been a while since I've read a programming book that wasn't overly dry.  Everything flowed nicely and kept me interested in learning what was coming next.  I really recommend reading this book if the subject matter sounds interesting to you.  It will be enjoyable.

 


Tags: Computer Graphics, Book Review, Ruby

This site uses cookies.