Wednesday, December 29, 2010

Skin Rendering: Work in Progress

After my last post, I was like hey, it's winter break - why don't I do skin rendering now. I've decided to post my current progress. Still needs a lot of work, but it isn't too terrible:

Unity's giving me a lot of grief with texture-space diffusion and linear space lighting calculations. But hopefully things will only improve from here! I have a feeling this might become one of my longterm goof around projects like Bioshock Pinball was.

Friday, December 24, 2010

An overview of Real-Time Skin Rendering

I recently gave a 15 minute presentation about Real-Time Skin Rendering for my Advanced Graphics Course and I thought maybe I would write up some of the significant bits here. First and foremost this talk was based off of information from 2 sources: Eugene d'Eon and David Luebke's article in GPU Gems 3 about their work on the Human Head Demo, and John Hable's course notes from his presentation on Character Lighting and Shading at Siggraph 2010. Note that all the images in this post are from Hable's presentation.

Skin rendering is notable primarily for the challenges of replicating the subsurface scattering found in human skin. This subsurface scattering creates a vibrant glow of sorts in the diffuse component of the skin, and without it the skin can appear dry and unnatural.

Here's a shot from Hable's presentation of skin rendered with standard Blinn-Phong shading model:
An important comment that Hable makes in his presentation is that the input mesh is very high detail with high detail diffuse color and bump textures, and although the skin appears too rough in the Blinn-Phong model, blurring those is a hack and not a good solution. Rather, modeling subsurface will smooth a lot of the rough feeling in a much more vibrant manner.

NVIDIA calculates subsurface scattering by blurring the irradiance texture that has the diffuse component for the skin. The irradiance texture is split into multiple Gaussians, and then these are blended together to create the final irradiance result.

Here's a shot of the same model and lighting conditions using NVIDIA's approach:
Definitely a huge improvement here. But it comes with the price of a lot of texture reads and writes. In a game that can be a lot for skin rendering on multiple characters. Hable presents the alternatives that Naughty Dog examined to try to find a good middle ground between cost and performance. A single 12-tap blur is used in place of the sum of gaussians for cut scenes in Uncharted 2. Here's what it looks like (the differences are subtle):
I'm not going to go into much detail about the approach that Naughty Dog used during gameplay for Uncharted 2, because it ditches the blurs altogether and uses an approximation created by pretending that the normals for each color channel are bent. It's better than the straight diffuse, and as Hable points out, good enough for a game where most of the time the player only sees the skin on the back of Drake's neck if they're not in a cut scene. Here's a shot of the Blended Normals approach:
This post definitely only skims the surface of real-time skin rendering, and I definitely recommend checking out the NVIDIA article and Hable's presentation if you are thinking of implementing specialized skin shaders. Hopefully sometime in the future I'll be able to find the time to try my own hand at it.

Tuesday, December 21, 2010

A Perfect Game?

I don't write about design so much as of late, but I decided to partly because of the impact a game made on me over thanksgiving break and the brainstorming I've been doing to come up with an idea to pitch to my class at the beginning of next semester (due on the first day of class, crazy right?).

So this game that made such a huge impression on me: Braid. A little late to the game on my part, because I had only heard good things about it... but I had trouble finding myself in the mood to seriously sit down and play a 2D platformer, but when I did, Braid just blew me away. And the reason is that Jonathan Blow sat down and made what I would be tempted to call a perfect game. Maybe not my favorite game of all time, or even the best game, but a perfect game. The reason that I say perfect is because Braid is a complete game. Something that developers I think have learned to think of as impossible because no matter what it's got to ship on time, right?

Wrong. Chris Hecker had a very interesting rant about this at GDC entitled "Please Finish Your Game" that uses Braid as one its core examples. Braid is a finished game, and to me that's very important, because that means that Braid can convey its ideas in much the same way that a good piece of literature can.

But what makes Braid feel like a game that's been completed? It's partly because there are a set of underlying concepts, messages, and themes that drive the games purpose for existence to be something other than end of quarter profits. That's just the first step though. The second is that from these ideas came mechanics and puzzles that complement those ideas. These core elements of the gameplay are accompanied by art, pieces of writing, and music that all fits with what is happening. and part of it is that I understand is that Jonathan Blow had time to go through and polish the gameplay multiple times while his artist iterated over an art direction several times. As a result the game stands as a testament to what a game that wants to be called "art" should actually be striving for- it should be something that conveys its underlying message from every angle you examine it from.

Nothing is without purpose in the game. I was recently asked at a party what type of games I want to make after I graduate. That's the type of game I want to make. But I don't want to make them after I graduate. I want to make them now.

Friday, December 17, 2010

Advanced Graphics Final Project: Motion Blur

For part of my final project in CSE 872: Advanced Graphics, I did a variety of implementations of Real-Time Motion Blur. It was a fun project, and this blog might see me post more implementations in the future (I've been playing around with a velocity buffer based one), but for now:

Technique 1: An Accumulation Buffer
This is a really easy technique that essentially is just the averaging together of several frames, causing motion from dynamic objects and camera motion to become blurred. The reality is that is really just impractical, but converges to a correct solution if a small enough time step and enough samples are used. But in a real-time implementation, this will almost never be feasible. As a result, under-sampling known as "ghosting" can be seen. Check out this shot from my project:

Technique 2: Motion Blur as a Post Process
This is a technique presented in the excellent GPU Gems 3, where world space positions are reconstructed from the depth buffer during post processing. The difference between the current frame's position and the previous frame's position will produce a velocity vector that can then be used to blur the image. However, this technique only works for static geometry (camera motion), but the results are good:

Technique 3: Just Fake It with a Radial Blur already
This one I actually used in a game project recently that I will probably be posting about in the near future. This is something that Real-Time Rendering points out about Assassin's Creed- the effectiveness of a simple radial blur looks very favorable for certain instances of forward motion. We use it for the boos functionality on the vehicle in my game, and Assassin's Creed uses it for chase sequences. Here's a shot of my demo scene:

So that sums up my current round of motion blur techniques for my final. I might talk about the Depth of Field component of my project, but then again maybe not.

Thursday, December 2, 2010

Next Semester: Enter Teaching Assistant

So I'm taking a break from my most recent project (which I'll be posting about soon I promise) to write a little post on something I'm doing this spring. I will be a TA for the Digital Game Design class at Michigan State, the first class that students take in our Game Development Specialization.

This is really exciting to me for a variety of reasons:
  • I like helping people make games. Its awesome to help someone learn the technical aspects in game development so that they can craft interesting experiences. Art games anyone? (hint: go play pOnd)
  • I know that by helping others, I am helping my development community in an important way. When I was a freshman, I worked with several seniors on game projects and game jams. They helped me every step of the way and it's the only reason I'm where I'm at today.
  • Maybe I can help people not write such terrible code. Us programmers are supposed to be the enablers right? Aras had some really good points in a recent presentation.