Let's suppose we have an object consisting of only 3d points, and triangle faces that each take a subset of these 3d points. How can I interpolate the normal vectors to get that Phong smooth shading? The actual algorithm seems impossible to find yet everybody is doing it.

There is one post on here, but I still have no idea how to implement it: Normal Interpolation for Phong shading

Also, it seems wrong to me that this supposed formula only takes in account two normals. What if you have a triangle surrounded by 3 other triangles? Then how do you blend the normals?

  • 2
    $\begingroup$ Refer to: "Weights for Computing Vertex Normals from Facet Normals". Generally you walk over all triangles that share a vertex and use all of the adjacent triangle normals to compute the normal at that vertex. To achieve this you can walk over all triangles and add their normals to their 3 adjacent vertices (with a weight). More generally you can create a structure which for each vertex lets you iterate over the triangles that share it. $\endgroup$
    – lightxbulb
    Sep 30, 2019 at 9:23
  • $\begingroup$ @lightxbulb exactly what I was looking for, thank you! I can't upvote comments yet but otherwise I would have. $\endgroup$
    – AnnoyinC
    Sep 30, 2019 at 16:07
  • 1
    $\begingroup$ Also worth pointing out the interpolated normals need renormalising per pixel. $\endgroup$
    – PaulHK
    Feb 28, 2020 at 4:44

3 Answers 3


EDIT: I misunderstood your question, so please disregard this answer.

The Phong shading model assumes a surface normal $\mathbf{n}$ at the shading point $\mathbf{x}$ but it is independent of its type, so either the shading normal or the geometric normal will work. Moreover, this reflectance model requires an incoming and outgoing directions. In that sense, you can't just "interpolate the normals" to get the desired effect since you need to take into account the positions of the camera and the light, as well as the roughness parameters.

The (normalized) Phong BRDF is a sum of a diffuse and specular term:

$$ f_r(\mathbf{x},\omega_i,\omega_o) = \frac{\rho_d}{\pi} + \rho_s \frac{n+2}{2\pi}\max(0,\cos^n\alpha), $$ where

  • $\rho_d$ is the diffuse albedo, i.e. the fraction of the incoming energy that is reflected diffusely,
  • $\rho_s$ is the specular albedo, i.e. the fraction of the incoming energy that is reflected specularly,
  • $n$ is the Phong exponent; higher values yield more mirror-like specular reflection, and
  • $\alpha$ is the angle between the perfect specular reflection direction $\omega_r$ and the outgoing direction $\omega_o$.

You can compute $\omega_r$ from the surface normal $\mathbf{n}$ and the lighting direction $\omega_i$, which is just

$$ \omega_r = 2\mathbf{n}(\mathbf{n}\cdot\omega_i) - \omega_i. $$

Typically you pick the albedos such that $\rho_d + \rho_s \leqslant 1$ to conserve energy.

  • $\begingroup$ I don't see how this formula makes creased edges appear to smoothly blend into its neighbours, aka phong normal interpolation (I'm not confused with gouraud interpolation) $\endgroup$
    – AnnoyinC
    Sep 30, 2019 at 8:05
  • 2
    $\begingroup$ He is talking about Phon shading, not the Phong brdf: en.m.wikipedia.org/wiki/Phong_shading Consider editing your answer as it is currently misleading. $\endgroup$
    – lightxbulb
    Sep 30, 2019 at 9:16

I am going to assume that you have the normals available for each point and that your vertex pass don't do this for you. For every pixel you will have an intersection point $p$ that exists on the nearest triangle surface defined by 3 points $p_i$, $p_j$ and $p_k$ with corresponding normals $n_i$, $n_j$ and $n_k$. Phong shading is the normalized interpolated normal, which can be found by:

  1. Computing the barycentric coordinates of $p$, (look at (https://github.com/Jojendersie/gpugi/blob/5d18526c864bbf09baca02bfab6bcec97b7e1210/gpugi/shader/intersectiontests.glsl#L63) in the function "IntersectTriangle"). Note that the order is important such that your coordinate values $u$, $v$ and $w$ has the same order as your points.

  2. Interpolating and normalizing: $\frac{un_i + vn_j + wn_k}{|| un_i + vn_j + wn_k ||}$.

  3. ???

  4. Profit!


A possible way is using bilinear interpolation. Assuming you know the normals at the triangle vertices, when doing a raster-scan conversion, you intersect the triangle projection with horizontals and each time obtain two intersection points. Then you fill the segment between them with further interpolated data.

So interpolation takes place first between triangle vertices, then between intersection, and in both cases a linear interpolation can be used. Anyway, the resulting vector should be normalized to unit norm in order to apply Phong's model.

Note that as the first interpolation is done between two vertices, the continuity of the normal vectors is implicitly guaranteed along edges common to two faces.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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