I am new to rendering and I would like to calcualte UV partial derivatives of a cylinder shape, which is parameterized by radius $R$ and length $L$.

Using cylindrical coordinate mapping, for a surface point $\mathbf{p}=(x,y,z)$, the UV map (normalized to $[0,1]$) is: $$ (u,v) = \Big(\frac{\phi}{2\pi}, \frac{z}{L}\Big)\qquad \text{where} \quad \phi = \arctan \frac{y}{x} $$ Then I compute the derivatives with respect to $\mathbf{p}$, that is: $$ \begin{aligned} \frac{\partial u}{\partial \mathbf{p}} & = \frac{1}{2\pi R^2} \Big( -y, x, 0\Big) = \frac{1}{2\pi R} \Big( -\sin\phi, \cos\phi, 0\Big)\\ \frac{\partial v}{\partial \mathbf{p}} &= \Big( 0, 0, \frac{1}{L}\Big) \end{aligned} $$ Or equivalently: $$ \begin{aligned} \frac{\partial \mathbf{p}}{\partial u} & = 2\pi R \Big( -\frac{1}{\sin\phi}, \frac{1}{\cos\phi}, 0\Big)\\ \frac{\partial \mathbf{p}}{\partial v} &= \Big( 0, 0, L\Big) \end{aligned} $$ Everything looks good until now.


In pbrt-3, the relevant part of cylinder.cpp is: (i) UV same as above; (ii) $\partial \mathbf{p}/\partial u$ however is different:

Float u = phi / phiMax;
Float v = (pHit.z - zMin) / (zMax - zMin);

// Compute cylinder $\dpdu$ and $\dpdv$
Vector3f dpdu(-phiMax * pHit.y, phiMax * pHit.x, 0);
Vector3f dpdv(0, 0, zMax - zMin);

What am I missing here?


I think it's easiest to get the tangent frame by writing the forward mapping from $(u,v)$ to $\mathbf{p}$: $$ \mathbf{p}(u,v) = \begin{bmatrix} R \, \cos (2\pi u) \\ R \, \sin (2\pi u) \\ vL \end{bmatrix} $$ Then you can see that the derivatives are: $$ \frac{\partial\mathbf{p}}{\partial u} = \begin{bmatrix} -2\pi R \, \sin(2\pi u) \\ 2\pi R \, \cos(2\pi u) \\ 0\end{bmatrix} = \begin{bmatrix} -2\pi y \\ 2\pi x \\ 0\end{bmatrix}, \qquad \frac{\partial\mathbf{p}}{\partial v} = \begin{bmatrix} 0 \\ 0 \\ L \end{bmatrix} $$ which matches the pbrt code.

I think your derivation went wrong by assuming that $\partial\mathbf{p}/\partial u$ was the component-wise reciprocal of $\partial u / \partial{\mathbf{p}}$. It's not so simple, because the latter object is really the gradient of $u$, where $u$ is now considered as a scalar field defined over all space (not just on the cylinder). To invert this properly we really need another coordinate running perpendicular to $u$ in the $xy$ plane, so that we have a locally invertible mapping; then we can take its Jacobian matrix and invert that. We can use the radius $R$ as such a coordinate. Then we have the inverse mapping, $$ \begin{aligned} u(x,y) &= \frac{1}{2\pi} \arctan(y,x) \\ R(x,y) &= \sqrt{x^2 + y^2} \end{aligned} $$ whose Jacobian is: $$ \frac{\partial(u,R)}{\partial(x,y)} = \begin{bmatrix} \tfrac{\partial u}{\partial x} & \tfrac{\partial u}{\partial y} \\ \tfrac{\partial R}{\partial x} & \tfrac{\partial R}{\partial y} \end{bmatrix} = \begin{bmatrix} -y/(2\pi R^2) & x/(2\pi R^2) \\ x/R & y/R \end{bmatrix} $$ and the inverse of that is: $$ \frac{\partial(x,y)}{\partial(u,R)} = -2\pi R \begin{bmatrix} y/R & -x/(2\pi R^2) \\ -x/R & -y/(2\pi R^2) \end{bmatrix} = \begin{bmatrix} -2\pi y & x/R \\ 2\pi x & y/R \end{bmatrix} $$ from which you can then read off $\partial{(x,y)}/\partial u$ as the first column, which matches the result obtained for $\partial\mathbf{p}/\partial u$ above.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.