Okami’d

DirectX, Uncategorized

I just had one of these moments. One of these moments when you think about something, try it out, and it just works. Happy.

As most of you probably know, Okami is one beautiful game, and despite being something else, is one of the late PS2’s finest gems.

If, on the other hand, you do not know Okami, here is a quick refresher.

Pretty.

The game looks like a living, breathing Japanese ink painting.

There are big, dark outlines, billboards, all of it combined with textures which describe their elements using the same black outlines. Adding a few screen-space effects to make the outlines more organic in motion, and you get a jaw-droppingly pretty game.

I recently bought (and played around ten hours) the HD re-release, and I am having a delightful time. But with crisper visuals, some smaller details become more apparent, some small details start being noticeable.

..and this is how I notice Okami’s method of cell-shading. During the PS2 days, there were no shaders, and while there would still be ways to internally displace vertices, there was no such thing as a pixel shader.

An example of the landscape outlines in the game.

An example of the landscape outlines in the game.

Okami’s method of outlining is clever by its simplicity. As I twisted the camera to some angles, I noticed that the large outlines you can see on the cliffs and landscape elements would distort. It is because they are in fact drawn twice. Once as the normal, textured model is drawn, another model, slightly larger, with a fixed colour (in this case, black), is drawn on top of it, with culling faces inversed. What you are seeing as an outline is in fact the inside of another model painted black.

After being intensely in love with this game for many years, this realisation came like a M. Shyamalan plot twist.

But wait, you might ask, pretending to care. Wouldn’t this be very easy to do with shaders? Exactly, and I had a little play with DirectX.

Here is what came out of it (link to video).

As you can probably see in the video, this method causes some visual artefacts when geometry intersects (see below). I cannot think yet of any efficient way around the problem, however it is only a small price to pay for such satisfying results obtained without influence of the pixel shader.

The original model is visible "through" the outlines at intersections.

The original model is visible “through” the outlines at intersections.

However, it is still possible to observe the same kind of artefact in the game itself, when looking at the models carefully.

Kokari's ear goes through the outline.

Kokari’s ear goes through the outline.

But these types of artefacts are not clearly visible in the game, and you would have to pay a lot of attention to spot them. Exception goes to the landscape elements (such as rocks) which do have to intersect with the ground, thus revealing the outlines.

Another thing you might notice from this screenshot is that the outlines are not regular, like in the teapot shader. In fact, in most character models, they are far from being regular. For instance, on Amaterasu’s model, the ear and the stomach outlines are much more prevalent. This goes to show that instead of using vertex displacement for the characters, the team behind Okami might have created its own outline models. It implies more work on modelling, but on the other hand, more artistic liberty in how the outlines look. Namely, the ability to make them larger to emphasize certain parts of a character, or smaller, to hide possible artefacts.

Here is the shader code to render the outlines using a vertex shader. I intentionally left out the texture rendering pass to save some space.


RasterizerState backface {
 FillMode = Solid;
 CullMode = Back;
 FrontCounterClockwise = true;
};

cbuffer OutlineBuffer
{
 float lineLength;
};

VertexPosition Outline3dVS(VertexIn vin) {
 VertexPosition vout;
 float3 position = vin.pos;
 position += vin.normal * lineLength; //Translate the point along its normal
 vout.posH = mul(float4(position, 1.0f), worldViewProj);
 return vout;
}

float4 Outline3dPS(VertexPosition pin) : SV_TARGET
{
 return float4(0,0,0,1); //Black outline
}

technique10 Outline3d {
 pass P1 {
 SetVertexShader( CompileShader( vs_4_0, Outline3dVS() ) );
 SetGeometryShader( NULL );
 SetPixelShader( CompileShader( ps_4_0, Outline3dPS() ) );

 SetRasterizerState( backface );
 SetDepthStencilState(DSSLess, 1);
 SetBlendState(NoBlend, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
 }
}

Now, many things remain for the render to look really Okami-like, such as distortion of the outline (the outlines are distorted in motion), and screen-space effects, which I hope I will have time to cover at some later time.

About these ads

One thought on “Okami’d

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s