<p>Without knowing the internals of Blender, I would say it uses shared normals for the quads, splitting the normals only on edges between the quads, not between the triangles. So your idea of uploading a normal per quad is probably close to the result you are looking for.</p>

<p>If you load the mesh as quads, you are set. If you are using an old version of OpenGL where quads still exist, you may even be able to use solution 3).</p>

<p>If you load the mesh as triangles, you will have to figure out which triangles originated in quads. You can likely do this simply by enforcing split normals beyond a fixed angle between adjacent triangles.</p>

<p>I am not sure there is a simple dynamic solution, where you just render any mesh. You may be able to use the geometry shader to look at the adjacent vertices, but the easiest version is to smooth the normals once before upload.</p>

CC BY-SA 3.0
2016-01-13T14:29:53.797Z
2016-01-13T14:29:53.797Z
Mikkel Gjoel
<p>I'm trying to figure out how to properly implement flat shading for meshes containing non-planar polygons (using OpenGL/GLSL). The aim is to obtain something similar to the result <em>Blender</em> gives (all polygons below are non-planar):</p>

<p><a href="https://i.sstatic.net/2Whne.png" rel="noreferrer"><img src="https://i.sstatic.net/2Whne.png" alt="enter image description here"></a></p>

<p>To provide a bit of context — the non-planar polygons (e.g. quads, pentagons, ...) are either present in the mesh I load or appear as a result of applying a subdivision scheme (such as Catmull-Clark) to the mesh.</p>

<p>In case of a triangle mesh, I'm aware of the following approaches to implement flat shading —</p>

<ol>
<li>Compute the cross product of <code>dFdx</code> and <code>dFdy</code> in the fragment shader</li>
<li>Use the geometry shader to compute the triangle normal by taking the cross product of two sides of the triangle</li>
<li>When using <code>glDrawElements</code>, use the <code>flat</code> interpolation qualifier (which basically uses the normal associated with the provoking vertex for all fragments)</li>
<li>When using <code>glDrawArrays</code>, most vertices (usually all of them) are copied to the GPU multiple times. Therefore, a different normal can be used each time</li>
</ol>

<p>For a mesh containing non-planar polygons the first three options don't yield the result I'm after. In my implementation (using the Qt framework) I use <code>GL_TRIANGLE_FAN</code>:</p>

<p><a href="https://i.sstatic.net/4ujWL.png" rel="noreferrer"><img src="https://i.sstatic.net/4ujWL.png" alt="enter image description here"></a></p>

<p>The fourth option could work, but isn't very elegant — I'd like to use either <code>glDrawElements</code> or <code>glDrawMultiElements</code>. One other option would be to use <code>glDrawElements</code> while looping over the faces one by one (instead of invoking it once using <code>glPrimitiveRestartIndex</code>). In that case, one could upload a <code>uniform</code> normal for each face. However, this does not seem very efficient. Any other ideas?</p>

CC BY-SA 3.0
2016-01-10T16:12:58.640Z
Interesting question. If there is a specific reason that you don't want a shape with planar quads, like a [rhombic dodecahedron](https://en.wikipedia.org/wiki/Rhombic_dodecahedron), mentioning that reason and explaining your motivation for using non-planar quads might help give insight into what is required.
trichoplax is on Codidact now
CC BY-SA 3.0
2016-01-10T17:57:59.480Z
@trichoplax Ok, updated the question :).
Ailurus
CC BY-SA 3.0
2017-05-11T04:49:18.350Z
You could also specify a normal for each vertex as an attribute, not a uniform, and render the mesh all in one call.
Jack
<opengl><shader><glsl>
Flat shading for non-planar polygons
Ailurus
# Flat shading for non-planar polygons

(Asked by: username_0 on 2016-01-10)

I'm trying to figure out how to properly implement flat shading for meshes containing non-planar polygons (using OpenGL/GLSL). The aim is to obtain something similar to the result *Blender* gives (all polygons below are non-planar):

[![enter image description here](https://i.sstatic.net/2Whne.png)](https://i.sstatic.net/2Whne.png)

To provide a bit of context — the non-planar polygons (e.g. quads, pentagons, ...) are either present in the mesh I load or appear as a result of applying a subdivision scheme (such as Catmull-Clark) to the mesh.

In case of a triangle mesh, I'm aware of the following approaches to implement flat shading —

1. Compute the cross product of `dFdx` and `dFdy` in the fragment shader
2. Use the geometry shader to compute the triangle normal by taking the cross product of two sides of the triangle
3. When using `glDrawElements`, use the `flat` interpolation qualifier (which basically uses the normal associated with the provoking vertex for all fragments)
4. When using `glDrawArrays`, most vertices (usually all of them) are copied to the GPU multiple times. Therefore, a different normal can be used each time

For a mesh containing non-planar polygons the first three options don't yield the result I'm after. In my implementation (using the Qt framework) I use `GL_TRIANGLE_FAN`:

[![enter image description here](https://i.sstatic.net/4ujWL.png)](https://i.sstatic.net/4ujWL.png)

The fourth option could work, but isn't very elegant — I'd like to use either `glDrawElements` or `glDrawMultiElements`. One other option would be to use `glDrawElements` while looping over the faces one by one (instead of invoking it once using `glPrimitiveRestartIndex`). In that case, one could upload a `uniform` normal for each face. However, this does not seem very efficient. Any other ideas?

**Tags:** opengl, shader, glsl

> **Comments:**
> **username_1**: Interesting question. If there is a specific reason that you don't want a shape with planar quads, like a [rhombic dodecahedron](https://en.wikipedia.org/wiki/Rhombic_dodecahedron), mentioning that reason and explaining your motivation for using non-planar quads might help give insight into what is required.  
> **username_0**: @username_1 Ok, updated the question :).  
> **username_2**: You could also specify a normal for each vertex as an attribute, not a uniform, and render the mesh all in one call.  

---

## 1 answers

### Answer by username_3 on 2016-01-13. Score: 7

Without knowing the internals of Blender, I would say it uses shared normals for the quads, splitting the normals only on edges between the quads, not between the triangles. So your idea of uploading a normal per quad is probably close to the result you are looking for.

If you load the mesh as quads, you are set. If you are using an old version of OpenGL where quads still exist, you may even be able to use solution 3).

If you load the mesh as triangles, you will have to figure out which triangles originated in quads. You can likely do this simply by enforcing split normals beyond a fixed angle between adjacent triangles.

I am not sure there is a simple dynamic solution, where you just render any mesh. You may be able to use the geometry shader to look at the adjacent vertices, but the easiest version is to smooth the normals once before upload.


---

