<p>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.</p>

<h1>Average normal approach</h1>

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

<p>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)$$</p>

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

<h1>Geometric approach (recommended for this problem)</h1>

<p>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:</p>

<h2>Winding order 1</h2>

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

<h2>Winding order 2</h2>

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

<p>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$$</p>

<p>So then,
$$normal = geometric\ normal2$$</p>

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

CC BY-SA 3.0
2017-03-14T16:58:44.670Z
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
CC BY-SA 3.0
2017-03-14T17:40:56.410Z
Nathan, so cos(theta) is equal to 0.8 still, right?
S.A
CC BY-SA 3.0
2017-03-14T19:28:58.263Z
@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
CC BY-SA 3.0
2017-03-14T19:32:16.863Z
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
CC BY-SA 3.0
2017-03-14T19:33:06.447Z
I do like your suggestion though. :) I'll incorporate it into the answer.
aces
CC BY-SA 3.0
2017-03-14T20:31:46.313Z
Actually, I decided to compare it against the average normal vector. The reasoning behind this is that the supplied vertex normals can help us determine the winding order if the triangle is single-sided.
aces
CC BY-SA 3.0
2017-03-12T03:48:04.913Z
2017-03-14T20:27:39.237Z
2017-03-14T20:27:39.237Z
aces
<p>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. </p>

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

<p>First, I try to calculate ambient light intensity</p>

<p>$$ambient\ light\ intensity = (ambient\ reflection\ coefficient) \cdot (incident\ ambient\ light\ intensity)$$</p>

<p>so,</p>

<p>$$red = 0.6 \cdot 0.1 = 0.06$$</p>

<p>$$green = 0.7 \cdot 0.1 = 0.07$$</p>

<p>$$blue = 0.8 \cdot 0.1 = 0.08$$</p>

<p>Then, I try to calculate diffuse light:</p>

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

<p>so,</p>

<p>$$incident\ light\ intensity = 1$$</p>

<p>$diffusive\ reflection\ light$ is given as $(0.6, 0.7, 0.8)$</p>

<p>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.</p>

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

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

<rendering>
How do you calculate cos(theta) for diffuse in flat shading?
S.A
# How do you calculate cos(theta) for diffuse in flat shading?

(Asked by: username_0 on 2017-03-11)

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.

**Tags:** rendering


---

## 1 answers

### Answer by username_1 on 2017-03-12. Score: 2 | Accepted answer

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 username_2 username_2 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 $$

> **Comments:**
> **username_2**: 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.  
> **username_0**: username_2, so cos(theta) is equal to 0.8 still, right?  
> **username_1**: @username_2 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...  
> **username_2**: 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.  
> **username_1**: I do like your suggestion though. :) I'll incorporate it into the answer.  
> **username_1**: Actually, I decided to compare it against the average normal vector. The reasoning behind this is that the supplied vertex normals can help us determine the winding order if the triangle is single-sided.  

---

