The immediate question is: in HLSL, how can I orient a surface normal generated in UV space so that I can apply it to a cube face?

The overall project is that I'm trying to build a procedural planet generator. I'm using a cube projected to a sphere where each face is a quad-tree. The intermediate project is that I want to generate a normal map for the terrain. I think the best way for me to do this (and understand what I'm doing) is to generate the normals for the cube version first, then work out the transformations to warp those normals to the sphere.

Ideally the method would not involve branching code based on which face I'm working on (i.e., if we're on the top side of the cube, then U = X and V = Y). In other words, what I'm hoping for is some math-magic like "Oh, just cross multiply the terrain normal by the dot product of the cube face normal and blah blah blah".

9/20/10 ETA:

I know how to calculate normals for a flat surface. My subsequent problem is two-fold:

  1. How do I rotate the normal map so it is oriented correctly on each of the cube faces?
  2. how do I warp the flat normal map so that it wraps the sphere?

I've found one solution that uses a Jacobian matrix, but I can't get it to work. Even when all of the normals are pointing straight up (i.e. a flat surface), the HLSL code involving the Jacobian totally messes up the lighting--so it makes me not trust my implementation of the solution.

  • \$\begingroup\$ multiply the terrain normal by a 3x3 matrix, different for each cube face? \$\endgroup\$
    – moonshadow
    Sep 6, 2010 at 14:06
  • \$\begingroup\$ Wouldn't you just extend your center-to-surface vector until it hits the cube, just like in other kinds of cube-mapping? Or am I missing something here? \$\endgroup\$
    – drxzcl
    Sep 9, 2010 at 15:06
  • \$\begingroup\$ This question doesn't directly pertain to game development, and you would most likely get better answers at Stack Overflow stackoverflow.com \$\endgroup\$
    – Ricket
    Sep 20, 2010 at 22:22
  • \$\begingroup\$ This pertains to real time graphics which is a large part of game dev, so I think its relevant. \$\endgroup\$ Sep 21, 2010 at 6:29
  • \$\begingroup\$ It's graphics, rather than programming. So here sounds good. And moonshadow, Ranieri: Wouldn't they do better as answers? \$\endgroup\$ Oct 21, 2010 at 15:39

2 Answers 2


Your normals should be in tangent space, that way you can apply them onto any surface for which you can create a tangent space (trivial for spheres.) Basically the normal map describes how the normal differs from the actual normal on a small patch on the surface. The tangent space is what you probably try to get with your Jacobian matrix -- for a sphere, you can create a tangent space coordinate system at any given point by using the normal at the point and two perpendicular vectors -- just orient them consistently (for instance, along u and v) and you're done. You can then translate your incoming light vector into tangent space (or the other way round) and light with the new normal. The advantage is that your normal map will work on any object with a defined tangent space and UV mapping.

On the cube, your tangent space for each face is simply that face itself (i.e. if you have a face which has a normal -Z for instance, and your tangent space up is +Y, you just rotate that normal using a matrix which maps -Z to +Y.)

  • \$\begingroup\$ I have a vague half-notion of what tangent-space is, but I don't know how to take your advice and do anything with it. But that's probably entirely my fault. As for the second paragraph--I was trying to avoid doing branching code in HLSL, because my amateur understanding says that branching code is a Very Bad Thing in HLSL. Though it sounds like it may be unavoidable. \$\endgroup\$
    – Klay
    Nov 1, 2010 at 15:39
  • \$\begingroup\$ There's no branching: I assume you have a cube with a normal map on each of the faces. Now you basically unfold this cube onto a sphere ... the easiest thing you might want to do is to place a sphere inside your cube, and trace rays against the cube and bend the normal then. Assuming your normal frequency is uniform on a spherical surface (i.e. non-uniform on a cube-face), this should give you a ready-to-use normal map for a sphere. Though I still don't understand why you have that cube? Can't you work a sphere right away? \$\endgroup\$
    – Anteru
    Nov 2, 2010 at 1:41
  • \$\begingroup\$ The reason I'm using the cube map is because it's much easier to do level-of-detail rendering with six quadtrees subsequently mapped to a sphere than it is to do LOD calculations on the sphere's surface itself. \$\endgroup\$
    – Klay
    Dec 1, 2010 at 18:23
  • \$\begingroup\$ Also, the part in your answer where you say "just orient them consistently" might be the crux of the problem. I don't know how to orient my uv coordinates consistently on the six cube faces without resorting to something like [if cubeFace == top, then u = x and v = z...] etc, which leads to the branching I'm talking about. but all-in-all I'm still not able to visualize the overall process. Sorry for being so dense. \$\endgroup\$
    – Klay
    Dec 1, 2010 at 18:25

"I know how to calculate normals for a flat surface." Exactly how are you doing this? As far as I know, you shouldn't have to do anything to map it to a sphere other than map your UV's to the sphere surface correctly. Normal maps are always in a "flat" plane because the texture itself is "flat". The shape of the object that you apply the normal map to shouldn't matter.

  • \$\begingroup\$ The algorithm samples the surrounding points and cross multiplies (or is it the dot-product?) the slopes to get the vector perpendicular to the slopes. At least, that's my vague recollection--I'm at work and can't check it ATM. \$\endgroup\$
    – Klay
    Nov 1, 2010 at 15:41
  • \$\begingroup\$ Also, if I understand you correctly, it seems I need to "bake in" the curvature of the sphere into the normal map itself so the lighting is correct. Again, I apologize for being so dense, but some sort of diagram and/or pseudocode might help. \$\endgroup\$
    – Klay
    Dec 1, 2010 at 18:29

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .