0

What I am doing is using normal maps to light 2D sprites. Originally I was going to use a bump/height map in the images red channel and use the other two channels to store other information. What I thought was that since I know that any normal on the normal map will always have a z value in the range [0 .. 1] I could exclude this information from the blue channel and calculate the z value based on the length of the x and y values. So I tried it out and it seems to work so far, and it looks almost identical to the original.

My question is what is the cost of the additional instructions? There are a few extra multiplies and addition and two more sqrt calls.

Here is the fragment shader used :

// Input >
//   fc0 : Color to normal conversion factor - <2, 1, 0, 0>
//   fc1 : Light - <lightDirection.x, lightDirection.y, lightDirection.z>
//   v0  : texture coordinates - <u, v>
//   fs0 : color texture
//   fs1 : normal map

// Sample normal map (fs1) at coordinates (v0) into temp register (ft0)
tex ft0 v0 fs1 <2d,nearest>
// Convert color values [0, 1] to normal values [-1, 1]
mul ft0 ft0 fc0.xxx
sub ft0 ft0 fc0.yyy

//
// The code below is used to calculate the z value from the
// 2D x/y normal values
// 

// <Start normal z calculation>

// (ft0) should now hold a 2D vector - first find its length
// - length = sqrt(x * x + y * y)
mul ft1.x ft0.x ft0.x // x * x
mul ft1.y ft0.y ft0.y // y * y
add ft1.z ft1.x ft1.y // (x * x + y * y)
sqt ft1.z ft1.z // ft1.z = sqrt(x * x + y * y)
// Now using the length of the 2D normal find the z value
// - z = sqrt(1 - length * length)
mul ft1.z ft1.z ft1.z // length * length
sub ft1.z fc0.y ft1.z // 1 - length * length
sqt ft1.z ft1.z // ft1.z = sqrt(1 - length * length)
// Now move the z value into temp register (ft0) along with the normal x and y value
mov ft0.z ft1.z

// <End normal z calculations>

// The rest of the shader left out
cmann
  • 1,920
  • 4
  • 21
  • 33
  • Only tests on actual hardware you're targeting can show which approach is better. If you're trying to save GPU memory, then you're probably targeting mobile hardware. But, generally, the cost of operations such as mul and sqt is much higher on mobile (ant it depends on the device). – skozin Jan 28 '13 at 15:13

1 Answers1

0

sqrt is very slow operation. So you should avoid it as much as possible. Actually, before normal mapping was bump mapping with only grayscale image representing height. In this case normal calculated based on neightbor pixels. But when hardware memory grew up it's not worth to economize. But on mobile

nikitablack
  • 4,359
  • 2
  • 35
  • 68