Compute sphere tangent for normal mapping I'm implementing normal mapping on my toy pathtracer. I need to compute the tangent (and bitangent) of any sphere point in order to create the matrix that will transform tangent space to world space.

More specifically, I want the tangent that runs along the u texture coordinate, and the bitangent that runs along the v coordinate.

Here's how I implemented it:


At the intersection point P, compute the spherical coordinates
(theta, phi) of P.
Add a tiny delta to the angle that relates to the u texture
coordinate (phi), finding another point Q on the sphere.
Compute Q - P and normalize it to have the tangent.
The bitangent is then computed by doing the cross product of the
tangent and the normal at the point P.


Relevant code on the sphere collision function:

    hitRecord.point = ray.pointAtParameter(t);

    Vec3 localCoord = hitRecord.point - center;
    float theta = asin(localCoord.y / radius); //[-pi/2,pi/2]
    float phi = atan2(localCoord.z, localCoord.x); //[-pi,+pi]

    float deltaPhi = phi + FLOAT_BIAS;
    Vec3 deltaPoint(radius * cos(theta) * cos(deltaPhi),
        radius * sin(theta),
        radius * cos(theta) * sin(deltaPhi));

    //Assume local space to be aligned with world space
    //So this is also the tangent in world space
    hitRecord.tangent = deltaPoint - localCoord;
    hitRecord.tangent.normalize();

    hitRecord.normal = localCoord / radius;
    hitRecord.bitangent = hitRecord.tangent.cross(hitRecord.normal);
    hitRecord.bitangent.normalize();


This seems to work, but all this trigonometry is not light and makes me wonder if there is a better way of doing it. Does anyone has any ideias/pointers?
You can do this a little bit more efficiently and accurately by calculating derivatives of $P$ with respect to $u, v$—or the derivatives with respect to $\phi, \theta$, equivalently (up to a scalar multiple).

Start by expressing $P$ in terms of the spherical coordinates:
$$\begin{aligned}
P_x &amp;= r \cos \theta \cos \phi \\
P_y &amp;= r \sin \theta \\
P_z &amp;= r \cos \theta \sin \phi
\end{aligned}$$

Now you can get the tangent as $T = \partial P / \partial \phi$, which works out as:
$$\begin{aligned}
T_x &amp;= -r \cos \theta \sin \phi \\
T_y &amp;= 0 \\
T_z &amp;= r \cos \theta \cos \phi
\end{aligned}$$

Once you normalize it, the $r \cos \theta$ factors drop out and you're left with just $T = (-\sin \phi, 0, \cos \phi)$. Pretty simple!

You can similarly get the bitangent as $B = \partial P / \partial \theta$, or you can just calculate it as the cross product $N \times T$, which is probably faster. (Note it should be $N \times T$, not $T \times N$, assuming you want $T, B, N$ to form a right-handed basis in that order.)



The above approach will work for pretty much any kind of surface that can be parameterized, not just spheres. However, in the case of spheres with the usual $\phi, \theta$ coordinates, there's an even quicker shortcut that you can do with just vector math, no trig at all. Let $C$ be the center of the sphere, and $A$ be a vector representing the axis of the spherical coordinates—i.e. pointing from the center toward the north pole. Then you can just calculate $T = \text{normalize}\bigl(A \times (P - C) \bigr)$, then $B = N \times T$ as before.