In Unity we very often mix fixed function and programmable vertex pipelines. In our lighting model, some amount of brightest lights per object are drawn in pixel lit mode, and the rest are drawn using fixed function vertex lighting. Naturally the pixel lights most often use vertex shaders, as they want to calculate some texcoords for light cookies, or do something with tangent space, or calculate some texcoords for shadow mapping, and so on. The vertex lighting pass uses fixed function, because it’s the easiest way. It is possible to implement fixed function lighting equivalent in vertex shaders, but we haven’t done that yet because of complexities of Direct3D and OpenGL, the need to support shader model 1.1 and various other issues. Call me lazy.
And herein lies the problem: most often precision of vertex transformations is not the same in fixed function versus programmable vertex pipelines. If you’d just draw some objects in multiple passes, mixing fixed function and programmable paths, this is roughly what you will get (excuse my programmer’s art):
Not pretty at all! This should have looked like this:
So what do we do to make it look like this? We “pull” (bias) some rendering passes slighly towards the camera, so there is no depth fighting.
Now, at the moment Unity editor runs only on the Macs, which use OpenGL. In there, most of hardware configurations do not need this depth bias at all - they are able to generate same results in fixed function and programmable pipelines. Only Intel cards do need the depth bias on Mac OS X (on Windows, AMD and Intel cards need depth bias). So people author their games using OpenGL, where it does not need depth bias in most cases.
How do you apply depth bias in OpenGL? Enable GL_POLYGON_OFFSET_FILL and set glPolygonOffset to something like -1, -1. This works.
How do you apply depth bias in Direct3D 9? Conceptually, you do the same. There are DEPTHBIAS and SLOPESCALEDEPTHBIAS render states that do just that. And so we did use them.
And I’d look at their projects, see that they are using something like 0.01 for camera’s near plane and 1000.0 for the far plane, and tell them something along the lines of “increase your near plane, stupid!” (well ok, without the “stupid” part). And I’d explain all the above about mixing fixed function and vertex shaders, and how we do depth bias in that case, and how on OpenGL it’s often not needed but on Direct3D it’s pretty much always needed. And yes, how sometimes that can produce “double lighting” artifacts on close or intersecting geometry, and how the only solution is to increase the near plane and/or avoid close or intersecting geometry.
Sometimes this helped! I was so convinced that their too-low-near-plane was always the culprit.
And then one day I decided to check. This is what I’ve got on Direct3D:
Ok, this scene is intentionally using a low near plane, but let me stress this again. This is what I’ve got:
Not good at all.
What happened? It happened in roughly this way:
First, depth bias documentation on Direct3D is wrong. Depth bias is not in 0..16 range, it is in 0..1 range which corresponds to entire range of depth buffer.
Back then, our code was always using 16 bit depth buffers, so the equivalent of -1,-1 depth bias in OpenGL was multiplied with something like 1.0/65535.0, and that was fed into Direct3D. Hey, it seemed to work!
Later on, the device setup code was modified to do proper format selection, so most often it ended up using 24 bit depth buffer. Of courseno one I never modified the depth bias code to account for this change…
And it stayed there. And I kept deceiving myself that the content of the users is to blame, and not some stupid code of mine.
It’s good to check your assumptions once in a while.
So yeah, the proper multiplier for depth bias on Direct3D with 24 bit depth buffer should be not 1.0/65535.0, but something like 1.0/(2^24-1). Except that this value is really small, so something like 4.8e-7 should be used instead (see Lengyel’s GDC2007 talk). Oh, but for some reason it’s not really enough in practice, so something like 2.0*4.8e-7 should be used instead (tested so far on GeForce 8600, Radeon HD 3850, Radeon 9600, Intel 945, reference rasterizer). Oh, and the same value should be used even when a 16 bit depth buffer is used; using 1.0/65535.0 multiplier with 16 bit depth buffer produces way too large bias.
With proper bias values the image is good on Direct3D again. Yay for that (fix is coming in Unity 2.1 soon).
…and yes, I know that real men fudge projection matrix instead of using depth bias… someday maybe.
I decided to make a very small game with Unity. Coincidentally, Danc of Lost Garden fame just announced a small game design challenge called “Play With Your Peas“. It comes with a set of cute graphics and a ready-to-be-implemented game design. What more could I want?
So it’s a small very small 2D game without any next-gen bells and whistles. It can probably be done casually on the side, by allocating an hour here and there. We’ll see how it goes. Hey, I never actually done any game in Unity, I only make or break some underlying parts…
Of course, first I start with no game, just imported graphics. Hey look, I can do sprites!
Then cook up some base things: define the game grid, throw in some basic user interface on the right hand side, and make it actually do something. This wasn’t so hard; that already gets me an almost working level building functionality. It does not have fancy block building delay or block deletion yet; that will come later.
Next come basic physics. Danc’s design calls for simple arcade-like physics (things moving at constant speeds, bouncing off at equal angles, and so on), but in Unity I have a fully fledged physics engine just waiting to be used. Let’s use that.
The design has sloped ramp pieces, which are hard to approximate using any primitive colliders, so instead I’ll use convex mesh colliders for them. Now, on this machine I only have Blender, which I totally don’t know how to use; and I was too lazy to go to PC and use 3ds Max there. What a coder does? Of course, just type in the mesh file in ASCII FBX format. Excerpt:
; scaled 2x in Z, by 0.85 in Y
Vertices: -0.5,-0.425,-1.0, 0.5,-0.425,-1.0, -0.5,-0.425,1.0, 0.5,-0.425,1.0, -0.5,0.425,-1.0, -0.5,0.425,1.0
PolygonVertexIndex: 0,1,-3,2,1,-4,1,0,-5,2,3,-6,0,2,-5,2,5,-5,3,1,-5,5,3,-5
It’s a left ramp mesh! So much for fancy asset auto-importing functionality, when you don’t know how to use those 3D apps :)
After a while I’ve got peas being controlled by physics, colliding with level and so on. Physics is very bad for productivity, as I ended up just playing around with pea-stacks!
So far there’s no game yet… Next up: implement some AI for the peas, so they can wander around, climb the walls, fall down and bounce around. I guess that will be more work and less playing around… We’ll see.
This is just too cool: Off-Road Velociraptor Safari game. Read that again. Who says game industry is all about sequels and safe licenses?
You drive a jeep with a spiky ball, and your goal is to chase down raptors and send them to the future, presumably to end world hunger. Or you can do stunts. And you the driver are a raptor, only you wear a hat and a monocle.
Or watch a trailer if you want to miss all the real fun, or read a press release. Of course it’s made in Unity, in two months from start to finish.
To me, this is a perfect example of focus. Basically there are three things - 1) vehicle, 2) raptors, 3) physics mayhem - and that almost describes a game. Yes, there are crates and stunts and achievements and online leaderboards, but that’s just additional stuff on top of the core game.
Sounds like a good plan for making game prototypes:
Think up a game idea and describe it in one concise sentence. The idea may be totally crazy, like in this case. I guess an idea like Velociraptor Safari would not fly in a pitch at any publisher, but that does not matter at this point.
Get a small team of smart people. In Flashbang’s case, it seems they were 4 to 7 person team.
Choose a game engine/toolset that will allow you to make your game fast. *cough cough*
Do it!
All the above requires is a small smart team and groceries/rent for a couple of months.
Your original idea may be totally crazy, but with the actual working prototype at hand it might just work. Looks like Velociraptor Safari really clicked something on the internets (see Kotaku, JayIsGames, Destructoid, TIGSource, AtomicGamer, …).
One of our customers found an interesting bug the other day: embedding Unity Web Player into a web page makes some javascript animation libraries not work correctly. For example, script.aculo.us or Dojo Toolkit would stop doing some of their tasks. But only on Windows, and only on some browsers (Firefox and Safari).
Wait a moment… Unity plugin makes nice wobbling web page elements not wobble anymore!? Sounds like an interesting issue…
So I prepared for a debug session and tried the usual “divide by two until you locate the problem” approach.
Unity Web Player is composed of two parts: a small browser plugin, and the actual “engine” (let’s call it “runtime”). First I change the plugin so that it only loads the data, but never loads or starts the runtime. Everything works. So the problem is not in the plugin. Good.
Load the runtime and do basic initialization (create child window, load Mono, …), but never actually start playing the content - everything works.
Load the runtime and fully initialize everything, but never actually start playing the content - the bug appears! By now I know that the problem is somewhere in the initialization.
Initialization reads some settings from the data file, creates some “manager objects” for the runtime, initializes graphics device, loads first game “level” and then the game can play.
What of the above could cause something inside browser’s JavaScript engine stop working? And do that only on Windows, and only on some browsers? My first guess was the most platform-specific part: intialization of the graphics device, which on Windows usually happens to be Direct3D.
So I continued:
Try using OpenGL instead of Direct3D - everything works. By now it’s confirmed that initializing Direct3D causes something else in the browser not work.
“A-ha!” moment: tell Direct3D to not change floating point precision (via a create flag). Voilà, everything works!
I don’t know how I actually came up with the idea of testing floating point precision flag. Maybe I remembered some related problems we had a while ago, where Direct3D would cause timing calculations be “off”, if the user’s machine was not rebooted for a couple of weeks or more. That time around we properly changed our timing code to use 64 bit integers, but left Direct3D precision setting intact.
Side note: Intel x86 floating point unit (FPU) can operate in various precision modes, usually 32, 64 or 80 bit. By default Direct3D 9 sets FPU precision to 32 bit (i.e. single precision). Telling D3D to not change FPU settings could lower performance somewhat, but in my tests it did not have any noticeable impact.
So there it was. A debugging session, one line of change in the code, and fancy javascript webpage animations work on Windows in Firefox and Safari. This is coming out in Unity 2.0.2 update soon.
The moral? Something in one place can affect seemingly completely unrelated things in another place!
…I flew to Copenhagen and started working at Unity Technologies (OTEE back then). Here’s the famous last blog entry; and indeed with day work that is actually interesting there’s little time to spam the forums or the blogosphere.
It’s been an amazing ride so far. I’m working with amazing people, we have (mostly :)) amazing customers, we’ve done three major releases and five minor ones, I’ve seen sales grow from ridiculously low amount to feels good levels, I’ve seen the team expansion, and I took svn revision number 10000 for myself (that happened half a year ago):
> Wohoo! Congratulations on the 10,000th commit Aras! You have won a warm cup of freshly brewed coffee when you come to work! :)
You don’t know the whole exciting story behind this… :)
I had two tiny “cleanups” to two files - removing unused variable from each. Now, I’d so something on my Mac, start compiling, and while it’s compiling I’d check svn log on the windows machine.
As soon as Valdemar checked in revision number 9998, I knew what I had to do. Two trivial svn commits!
Some serious work, as you can see. Oh, some of my work also ended up being actually released, I’m not just sitting there claiming svn revisions for myself. Honestly!
I’ve moving back to Lithuania now, continuing to work on Unity from home. Gonna miss some of the office fun, but oh well. Tradeoffs have to be made.
Let’s see what the coming years will bring. Rock on.
Flashbang Studios just launched Splume, probably the first game out there* made with Unity 2.0. It just won our “Top DOG” competition by the way.
It’s a cute little gem, or alternatively, “Puzzle Bobble meets Ageia’s PhysX engine”. Lots of levels, user level editor, some AJAX magic and so on, and everything made in about four weeks. Matthew has some technical details for the curious.
Here are some shots and a youtube trailer for the lazy ones. The youtube trailer uses music from 8bitpeoples which can’t be bad :)
Finally, Unity 2.0 is out. Took a bit longer than we expected (but not 3.1415926 times longer, so we’re all good), but now, after half a year in beta testing, over a dozen alpha/beta releases, it is finally shipped. Feels good!
It’s been in active development for about a year (though some of 2.0 features were in development for much longer), with source control commits graph looking roughly like this. We pretty much spent the summer doing 800 svn commits/month with about four major code monkeys :) Now that the release is done I fully expect the graph to drop off to low values again (is it called “burnout”?).
Last week there was the first Unity conference, and it was a blast. It was like, oh my, it’s full of people and all about unity! In other words, really really cool.
The night before the conference was spent in the hotel, doing last tweaks to the website and launch demos. If the presenters during keynote talk looked confused or exhausted, that’s a combination of trans-Atlantic flight and this last night of work. In fact, the very last fixes to the website were done during the keynote… oh well, Murphy’s law for the win.
Now what? Time to start working on Unity 2.x release :)
Everyone is saying “unit tests for the win!” all over the place. That’s good, but how would you actually test graphics related code? Especially considering all the different hardware and drivers out there, where the result might be different just because the hardware is different, or because the hardware/driver understands your code in a funky way…
Here is how we do it at work. This took quite some time to set up, but I think it’s very worth it.
First you need hardware to test things on. For a start just a couple of graphics cards that you can swap in and out might do the trick. A larger problem is integrated graphics cards - it’s quite hard to swap them in and out, so we bit the bullet and bought a machine for each integrated card that we care about. The same machines are then used to test discrete cards (we have several shelves of those by now, going all the way back to… does ATI Rage, Matrox G45 or S3 ProSavage say anything to you?).
Then you make the unit tests (or perhaps these should be called the functional tests). Build a small scene for every possible thing that you can imagine. Some examples:
Do all blend modes work?
Do light cookies work?
Does automatic texture coordinate generation and texture transforms work?
Does rendering of particles work?
Does glow image postprocessing effect work?
Does mesh skinning work?
Do shadows from point lights work?
This will result in a lot of tests, with each test hopefully testing a small, isolated feature. Make some setup that can load all defined tests in succession and take screenshots of the results. Make sure time always progresses at fixed rate (for the case where a test does not produce a constant image… like particle or animation tests), and take a screenshot of, for example, frame 5 for each test (so that some tests have some data to warm up… for example motion blur test).
By this time you have something that you can run and it spits out lots of screenshots. This is already very useful. Get a new graphics card, upgrade to new OS or install a new shiny driver? Run the tests, and obvious errors (if any) can be found just by quickly flipping through the shots. Same with the changes that are made in rendering related code - run the tests, see if anything became broken.
The testing process can be further automated. Here we have a small set of Perl scripts that can either produce a suite of test images for the current hardware, or run all the tests and compare the results with “known to be correct” suite of images. As graphics cards are different from each other, the “correct” results will be somewhat different (because of different capabilities, internal precision etc.). So we keep a set of test results for each graphics card.
Then these scripts can be run for various driver versions on every graphics card. They compare results for each test case, and for failed tests copy out the resulting screenshot, the correct screenshot, log the failures into a wiki-compatible format (to be posted on some internal wiki), etc.
I’ve heard that some folks even go a step further - fully automate the testing of all driver versions. Install one driver in silent mode, reboot the machine, after reboot runs another script that launches the tests and proceeds with the next driver version. I don’t know if that is only an urban legend or if someone actually does this*, but that would be an interesting thing to try. The testing per card then would be: 1) install a card, 2) run the test script, 3) coffee break, happiness and profit!
* My impression is that at least with the big games it works the other way around - you don’t test with the hardware; instead the hardware guys test with your game. That’s how it looks for a clueless observer like me at least.
So far this unit test suite was really helpful in a couple of ways: making of the just-announced Direct3D renderer and discovering new & exciting graphics card/driver workarounds that we have to do. Making of the suite did take a lot of time, but I’m happy with it!