# How do you calculate cos(theta) for diffuse in flat shading?

Consider a triangular face of three vertices $A=(0,2,1)$, $B=(3,0,1)$ and the origin $O$, with normal vectors $(0,0,1)$, $(1,1,0)$, and $(-1,-1,1)$, respectively. The incident light is white and directional in the direction of $L = (0,3,4)$ and the intensity is $1$, the background ambient light intensity is $0.1$, and the diffuse reflection coefficients for $(red, green, blue)$ are $(0.6,0.7,0.8)$. No specular light contribution need be considered.

To find the $(red, green, blue)$ intensity values at the centre of the face using flat shading, I follow this procedure:

First, I try to calculate ambient light intensity

$$ambient\ light\ intensity = (ambient\ reflection\ coefficient) \cdot (incident\ ambient\ light\ intensity)$$

so,

$$red = 0.6 \cdot 0.1 = 0.06$$

$$green = 0.7 \cdot 0.1 = 0.07$$

$$blue = 0.8 \cdot 0.1 = 0.08$$

Then, I try to calculate diffuse light:

$$diffuse\ light = (incident\ light\ intensity) \cdot (diffusive\ reflection\ light) \cdot \cos{\theta}$$

so,

$$incident\ light\ intensity = 1$$

$diffusive\ reflection\ light$ is given as $(0.6, 0.7, 0.8)$

I am not sure how to calculate $\cos{\theta}$. I believe it to be the angle between the normal vector of a vertex and the incident light. But I am having difficulties because there are three different normal vectors.

After that, I think I should sum the ambient light intensity with the diffuse light to get the final RGB values.

I would really appreciate it if you could help me fill the gaps to my calculations. Thanks.

With flat shading, the normal is the same across the whole triangle (or quad or whatever). There are some assumptions that were made here and two approaches. The latter approach will probably be best for most basic problems (although more work). We don't have the winding order, so we need to calculate the normal based on the vertices.

# Average normal approach

The assumption is that each vertex contributes the same amount of weight towards the triangle normal.

We first calculate the average of each: $$normal = normalize(0,0,1) + normalize(1,1,0) + normalize(-1,-1,1) \approx \frac{(0,0,1)+(0.7,0.7,0)+(-0.58,-0.58,0.58)}{3} \approx (0.04,0.04,0.53)$$ $$normalize(0.04,0.04,0.53) \approx (0.076,0.076,0.994)$$

For Lambert shading: $$cos(\theta) = normalize(0,3,4) \cdot (0.76,0.76, 0.994) \approx 0.84$$

# Geometric approach (recommended for this problem)

Another assumption Nathan Reed suggested was that each vertex normal holds equal weight, which would make sense in more common use cases. For this, we will want to find the face normals in both winding directions to compare this value to:

## Winding order 1

$$normal1 = normalize((B-A) \times (O-A)) \approx (0.29,0.43,-0.85)$$

## Winding order 2

$$normal2 = normalize((O-A) \times (B-A)) \approx (-0.29,-0.43,0.85)$$

Now, we can take the dot product between these two vectors and the one we computed above. Whichever one is greater or equal to 0: $$geometric\ normal1 = normal \cdot normal1 \approx -0.79$$ $$geometric\ normal2 = normal \cdot normal2 \approx 0.79$$

So then, $$normal = geometric\ normal2$$

For Lambert shading: $$cos(\theta) = normalize(0,3,4) \cdot (-0.29,-0.43,0.85) \approx 0.42$$

• So cos(theta) would equal to 0.8. Thanks! – S.A Mar 12 '17 at 9:28
• For flat shading you'd want to use the triangle's true, geometric normal vector, right? Not the average of the vertex normals or something. – Nathan Reed Mar 14 '17 at 16:58
• Nathan, so cos(theta) is equal to 0.8 still, right? – S.A Mar 14 '17 at 17:40
• @NathanReed We don't have the winding direction, so we could potentially compare the average with both flat geometric normal vectors and pick one. What if the triangle has some sort of weighted normal distribution and the vectors are given to compensate for this? This might be too general of a case I'm thinking of though... – aces Mar 14 '17 at 19:28
• I suspect you're overthinking it, since this sounds like a homework problem. :) But it's true the winding direction needs to be considered, or we need to check light vs normal and do double-sided lighting. – Nathan Reed Mar 14 '17 at 19:32