I want to calculate the surface normal to a point on a deformed sphere. The surface of the sphere is displaced along its (original) normals by a function $f(\vec x)$.

In mathematical terms:

Let $\vec x$ be a unit length vector in 3D, i.e. any point on the unit sphere centered on the origin. And let $f:\vec x \to \mathbb{R}$ be a function with a well-defined and continuous gradient $\nabla f(\vec x)$ for every $\vec x$.

Now a point on the surface of the resulting sphere is defined as:

$\vec P(\vec x) = (R + s \cdot f(\vec x)) \cdot \vec x$

where $R$ and $s$ are constants for the radius and the modulation depth, respectively.

The question now: Is this information sufficient to calculate the surface normal to the point $\vec P$? I feel like this should be possible, but it is entirely possible that it is not.

More information:
The function in my case is 3D Simplex Noise which gives values on the range $(-1,1)$ for any $\vec x$. The values for $R$ are about 10 times larger than those of $s$, probably more. Maybe this helps if only an approximation is possible.

Yes, it is possible, though there is still some error in here:

  • Calculate the gradient: $\vec g = \nabla f(\vec x)$
  • Then project it into the tangent plane to the sphere passing through the point: $\vec h = \vec g - (\vec g \cdot \vec x)\vec x$
  • The normal can then be calculated as $\vec n = \vec x - s \cdot \vec h$

This works as long as the radius is $R=1$ and something like $s \ll R$.

I think for $R \ne 1$ the gradient has to be rescaled: $\vec g = \dfrac{1}{R} \nabla f(\vec x)$

But I have no idea why the error gets larger with increasing $s$.

Alright, the rescaling factor was only half complete $\vec g = \dfrac{\nabla f(\vec x)}{R + s \cdot f(\vec x)}$
Now it works for all $R$ and $s$.

Picture of the deformed sphere Here is an image to give some intuition what this thing looks like (with approximated normals).

  • $\begingroup$ What do you mean by "normal to a point". Normal means orthogonal, which requires more than a point. Do you mean the vector connecting the origin to the point? $\endgroup$
    – hjhjhj57
    Dec 17, 2014 at 7:05
  • $\begingroup$ I mean normal to the surface in point P. $\endgroup$
    – Gigo
    Dec 17, 2014 at 7:08
  • $\begingroup$ Well, that's a completely different thing ;) $\endgroup$
    – hjhjhj57
    Dec 17, 2014 at 7:13

2 Answers 2


Let's say that your surface is defined by $\vec{r}(\Theta) = [r_0 + s f(\Theta) ] \hat{r}$, where $\Theta$ represents the spherical angles. I'm going to conjecture that the normal vector in radial coordinates is proportional to $\vec{n} = (-s\nabla f,1)$, where the gradient is a 2-vector in the angle space, and the last component is the radial direction.

We can verify this by making sure the normal vector is orthogonal to the surface. Note that a tangent vector to the surface is $(1,s\nabla f)$. This tangent points along the gradient direction. A normal vector orthogonal to this one points along an isocontour, which by construction is $(\hat{\Theta}^\perp,0)$, where $\hat{\Theta}^\perp$ is 90 degree rotation of the unit angular vectors in the tangent plane to the sphere passing through the point. The dot product with both of these is zero; the first is obvious, while for the second, $\nabla f \cdot \hat{\Theta}^\perp = 0$.

TL;DR: In radial coordinates: $(-s\nabla f,1)$, then just normalize and convert to cartesian if needed.

Elaboration: Based on your comment, it seems that your $f(\vec{x})$ is a scalar function of a 3-vector. Then $\nabla f$ is a 3-vector. The notation I use lumps the spherical coordinates $(\phi,\theta)$ into a single abstract 2-vector-like quantity $\Theta$, so that when you say $f(\Theta)$, that means $f$ is a function of only the spherical coordinate angles (and not a function of radius). Then $\nabla f(\Theta)=\nabla_\Theta f(\Theta)$ is a gradient in this 2-dimensional angle space. Your $\nabla f$ needs to be projected onto the surface of a sphere first, since you only ever sample $f(\vec{x})$ for $\lVert \vec{x} \rVert = 1$.

So, to calculate your normals, given a point $\vec{P}(\vec{x}) = [R + s f(\vec{x})]\vec{x}$ with $\vec{x}$ such that $\lVert \vec{x} \rVert = 1$,

  1. Let $\vec{g}(\vec{x}) = \nabla f(\vec{x})$. Here, $\vec{g}$ is the true gradient of $f$ in 3-space, and you can calculate that in cartesian coordinates, so you get $\vec{g} = (g_x,g_y,g_z)$.
  2. Project out the radial component of $\vec{g}$ to get $\vec{h}(\vec{x})$. To do this, $\vec{h} = \vec{g} - \frac{\vec{g}\cdot\vec{x}}{\vec{x}\cdot\vec{x}}\vec{x}$. Note that the denominator should be 1. Here, $\vec{h}$ represents the component of $\vec{g}$ that should be tangential to a sphere centered at the origin and passing through $\vec{P}$.
  3. An outward normal vector to the surface is $\vec{n} = \vec{x} - s\cdot \vec{h}$. Normalize it to get a unit normal vector.

All these computations can be done in Cartesian coordinates, but notice that I never had to resort to referring to the Cartesian components of any vector; the basic operations are vector arithmetic and dot products.

  • $\begingroup$ Thanks for the answer, but can you elaborate more, especially on the coordinates you use? I'm not quite able to follow your solution. Also $f$ and $\nabla f$ are given in cartesian coordinates and if possible I would like to skip calculating a bunch of angles because trigonometric functions are expensive on the hardware I use for this (GPUs). $\endgroup$
    – Gigo
    Dec 17, 2014 at 8:25
  • $\begingroup$ Alright, now I get it, but the radial component of $\vec g$ should be $(\vec g \cdot \vec x)\vec x$ not $(\vec g \cdot \vec x)\vec g$ right? $\endgroup$
    – Gigo
    Dec 17, 2014 at 17:56
  • $\begingroup$ @Gigo: Ah yes, you are absolutely right. Fixed. $\endgroup$
    – Victor Liu
    Dec 17, 2014 at 18:52
  • $\begingroup$ Strange, there seems to be an error with the sign. If I use $\vec n = \vec x - s \cdot \vec h$ the resulting normal seems correct. $\endgroup$
    – Gigo
    Dec 17, 2014 at 21:03
  • $\begingroup$ Well, I guess that makes sense, now that I think about it. The gradient points in the direction of increasing height, so the normal should tilt towards the opposite direction. $\endgroup$
    – Gigo
    Dec 17, 2014 at 21:06

Your modulated sphere is the 0-set of the function $$ F(x,y,z)=x^2+y^2+z^2-r^2(x,y,z) \\ F(\rho,\theta,\varphi)=\rho-r(\theta,\varphi) $$ ($r=R+sf$ in your notation). We shall need its differential, $$ dF=2\big((x-rr_x)dx+(y-rr_y)dy+(z-rr_z)dz\big) \\ dF=d\rho-r_\theta d\theta-r_\varphi d\varphi $$ By the definition of the gradient, $\nabla F=(dF)^{\sharp}:\quad \forall v,\;dF(v)=\langle \nabla F, v\rangle=g(\nabla F,v)$. Using the usual Eucledian metric, $$ g=dx^2+dy^2+dz^2 \\ g=d\rho^2+\rho^2d\theta^2+\rho^2\sin^2\theta \;d\varphi^2 $$ we get $$ \nabla F \propto (x-rr_x)\partial_x+(y-rr_y)\partial_y+(z-rr_z)\partial_z \\ \nabla F=\partial_\rho-\tfrac{r_\theta}{\rho^2} \partial_\theta- \tfrac{r_\varphi}{\rho^2\sin^2\theta}\partial_\varphi = \vec e_\rho-\tfrac{r_\theta}{\rho}\vec e_\theta- \tfrac{r_\varphi}{\rho\sin\theta}\vec e_\varphi, $$ where for the spherical coordinates we've written it first in the natural tangent space basis and then in the orthonormal basis used in vector calculus. These expressions evaluated at $F=0$ give a normal vector to the modulated sphere.


You must log in to answer this question.

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