About Me

Hi. I'm Josh Ols. Lead Graphics Developer for RUST LTD.

Contact:
crunchy.bytes.blog[at]gmail[dot]com

View Joshua Ols's profile on LinkedIn

Meta
« Alloy 3 is up on the asset store! | Main | Unity Shader Gotcha #11 - World Normals »
Sunday
Jan112015

Parallax/POM + Detail Mapping Gotchas

So I'm going to make a bold assertion. We as an industry are doing texture transforms wrong! >:(

...I suppose you want context for that statement. Well then...

 

Background

Let's start from the most common way to transform textures:

Texcoord = UV * Tiling + Offset;

This approach has a very serious problem in that Offset and Tiling are both implicitly coupled together. By that I mean that when the Tiling rate increases/descrease then the Offset's translation effect is decreased/increased. To compensate for this limitation, artists typically have to manually adjust the Offset value by dividing by the previous Tiling amount and then multiplying by the new amount. 

It would be far more preferable to have the two properties be decoupled, so that Offset always has a consistent translation effect. Thankfully it is pitifully easy to do this in code via:

Texcoord = (UV * Tiling) + (Offset * Tiling);

or just:

Texcoord = (UV + Offset) * Tiling;

Sadly we can't do much with this as the content creation tools do it the wrong way, so the engines also have to do it that way to be consistent. So what does knowing this really gain us?

I'll tell you...

 

Parallax Mapping

For those who don't know, Parallax Mapping of most varieties work by using a height map to generate a per-pixel texture coordinate offset to create the illusion of depth on flat surfaces. Now what you may not know is that this offset is implicitly multiplied by the Tiling amount of the texture coordinates used by said heightmap. So assuming your base texture uses the same texture coordinates, you can apply the parallax offset by doing the following:

Texcoord = UV * Tiling + ParallaxOffset;

Simple! Convenient! But...

 

Parallax + Detail Mapping

Detail mapping is a very common way to increase surface detail by combining a second set of textures into the base textures, usually at a much higher Tiling frequency. As you might imagine, combining parallax + detail mapping is a great way to make visually interesting surfaces. However, it comes with a nasty gotcha as the equation from above doesn't work for detail mapping!

The detail textures' Tiling rate will almost always be different from the base maps', meaning that the Parallax Offset will almost always translate the texture coordinates either too much or too little. This results in the rather unsightly effect of detail maps swimming across the surface as the camera changes position relative to it. So how do we fix this?

It turns out that the same fix applies as with any other offset. You just need to remove the base Tiling by dividing it out of the Parallax Offset. The resulting normalized offsets can be applied the correct way and benefit from the detail Tiling amount without any texture swimming. That looks something like this:

DetailTexcoord = (UV + (ParallaxOffset / BaseTiling)) * DetailTiling;

Any questions?

PrintView Printer Friendly Version

EmailEmail Article to Friend

Reader Comments

There are no comments for this journal entry. To create a new comment, use the form below.

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
All HTML will be escaped. Hyperlinks will be created for URLs automatically.