<p>If I understand you correctly, the problem is that the provoking vertex isn't the same vertex between the two triangles in a quad, due to using triangle strips. You could switch to using an indexed triangle list, and set up indices in such a way that the provoking vertex is the same in each quad. For instance, if one quad is vertices {0, 1, 2, 3} (CCW) then you might write {0, 1, 2, 3, 0, 2} in your index buffer so that 2 is the provoking vertex for both triangles. This should still be pretty efficient.</p>

<p>Another possibility (more involved, but more flexible) is to use the built-in <a href="http://docs.gl/el3/gl_VertexID" rel="nofollow noreferrer"><code>gl_VertexID</code></a> variable in your vertex shader to figure out which quad you're in (eg <code>int quadID = gl_VertexID / 4</code>), and use an appropriate shading location for that quad—the centroid of its vertices, for instance. However, for this to work, I think you would have to "un-share" the vertices so that each quad has its own 4 unique vertices (the two triangles in a quad can still share). So you would have to use primitive restarting, or again switch to indexed non-strip draws. You could also have per-quad data in an SSBO that you manually fetch using your computed quad index.</p>

CC BY-SA 3.0
2017-12-19T04:25:47.427Z
Thanks, that's really clever! I think it almost doubles the number of 16bit indices, but isn't there some caching advantage to indexing too? TIL ES 3.1 has `gl_VertexID` and `primitive restart` (thought degenerate tris was the only way)... pity there's no `gl_PrimitiveID`. I see it's more flexible, but I think same memory overhead as the provoking-trick.
hyperpallium
CC BY-SA 3.0
2017-12-19T05:41:55.680Z
@hyperpallium Yeah, more indices. They're usually a pretty small memory overhead compared to vertex data, but YMMV. As for cache, a well optimized indexed mesh can be as good or better than strips for general meshes, but I'm not sure if that's true for pure grid meshes.
Nathan Reed
CC BY-SA 3.0
2017-12-19T06:24:57.647Z
I can see it's much less than vertex data; but better to have no extra at all (*if* possible...). I probably shouldn't worry too much over efficiency at this stage - it seems a bit hard to predict. BTW I was thinking the way to cache-optimize a (plane) mesh is to split the rows, making it short enough so the vertices shared with the above tris are still in cache when needed (I don't think there's benefit to it being any shorter; and a small detriment with losing the horizontally shared vertices where the row is split.).
hyperpallium
CC BY-SA 3.0
2017-12-19T06:40:49.413Z
@hyperpallium You might be interested in this article: [Optimal grid rendering is not optimal](https://zeuxcg.org/2017/07/31/optimal-grid-rendering-is-not-optimal/)
Nathan Reed
CC BY-SA 3.0
2017-12-19T06:57:36.677Z
Spot on. Definitely best to not worry about optimizing yet! I wonder if different on mobile GPUs, which probably do fewer clever things under the hood(?)
hyperpallium
CC BY-SA 3.0
2017-12-22T01:30:47.483Z
With using the same provoking vertex, the location will be for that vertex, not the center of the square. But because I have the normal, I can work out the gradient and because I have a 2D height map (i.e. heights over a uniform 2D grid), I can calculate the exact 3D location of the center. There'a  bit of calculation there, but probably faster than the bandwidth cost of explicitly storing the center.
hyperpallium
CC BY-SA 3.0
2017-12-22T01:39:36.030Z
I'm not sure of the meaning of `gl_VertexID`. With the "un-sharing", can you use the same indexing as for the first method? i.e. `gl_VertexID` is not the index of the vertex, but the index in the list of indices? So if the same vertex is used twice, that vertex has two different `gl_VertexID`'s?
hyperpallium
CC BY-SA 3.0
2017-12-22T19:20:42.617Z
@hyperpallium It's the index into the vertex buffer (ie the value from the index buffer). If a vertex is re-used, it has the same `gl_VertexID` every time. By "un-sharing" I mean that, e.g.: vertices 0–3 are the first quad, 4–7 are the second quad, etc. So if a vertex is used in multiple quads, it's duplicated in the vertex buffer for each quad.
Nathan Reed
CC BY-SA 3.0
2017-12-23T02:47:29.907Z
Thanks, so that's much more buffer-expensive than the first ("provoking")  method. (I see what you mean: but at least you can reuse/share two vertices within the one quad.) Another approach to the heightmap might interact: my heights change, so 2D plane in a "static"-hinted buffer, and heights in a "dynamically"-hinted buffer. But, one could also calculate the 2D location, based on knowing which quad it's in (alternative: send in x,y coords, in just 16bit (or 8bit) Uints). But maybe caching won't catch the duplicates?
hyperpallium
CC BY-SA 3.0
2017-12-19T03:46:27.520Z
2017-12-19T03:46:27.520Z
Nathan Reed
<p>The easiest fix would be to do your light calculations in the fragment shader rather than per-vertex—you’ll avoid the discontinuity you’re currently seeing and your lighting will appear more natural (while still fitting the “low-poly” aesthetic). If that’s not an option, then you’re probably stuck with passing in each quad’s center along with the normals you’re already supplying.</p>

CC BY-SA 3.0
2017-12-18T23:16:24.020Z
Thanks. If I understand correctly, this will give a gradually changing specular highlight across the tri (because each pixel is in a slightly different location). The discontinuity between tris will vanish, because adjacent pixels in the different tris are very close in location. Is that what you mean? [BTW I've gotten a similar effect by letting the specular result from the vertex shader interpolate in the fragment shader]. I agree this is more natural - but I want uniform shading across the quad (so the discontinuity is between quads). A bit like the flashing facets of a jewel.
hyperpallium
CC BY-SA 3.0
2017-12-20T02:32:01.397Z
a common way to get that discontinuity is to interpolate position but not interpolate normals. maybe this works better for you
Sebastián Mestre
CC BY-SA 3.0
2017-12-18T18:30:18.777Z
2017-12-18T18:30:18.777Z
Noah Witherspoon
<p>You are probably mixing thing up. As I understood from you explanation, you are trying to do Phong shading and you want flat shading. </p>

<p>Your problem might be happening because you are calculating a specular component that depends on the view/camera direction.</p>

<p>It would help if you could add pictures explaining what is happening and what you want to happen.</p>

CC BY-SA 3.0
2017-12-19T03:12:59.217Z
Thanks. Yes, "flat shading" as [here](https://wikipedia.org/wiki/File:Phong-shading-sample.jpg). And yes, the diffuse + specular reflection of [Phong shading](https://wikipedia.org/wiki/Phong_reflection_model), but without the interpolation (TIL the interpolation is also called "Phong shading"). I believe the specular component increases the angle between the angle of reflection and the viewing direction decreases (brightest when aligned).... specular highlights move as you move your head. I needed a diagram too! I'll look for an online diagram tool (do you know of one?)
hyperpallium
CC BY-SA 3.0
2017-12-19T04:33:37.173Z
typo, should be: "specular component *increases* **as** the angle between reflected ray and the direction of the viewer *decreases*"
hyperpallium
CC BY-SA 3.0
2017-12-18T20:22:35.983Z
2017-12-18T20:22:35.983Z
ALourenco
<p>Here's an example of the <a href="https://wikipedia.org/wiki/File:Phong-shading-sample.jpg" rel="nofollow noreferrer">flat shaded</a> squares I want. But my squares are made of two triangles, and I'm getting flat shading of those <em>triangles</em>.</p>

<p><a href="https://i.sstatic.net/7UNuF.jpg" rel="nofollow noreferrer"><img src="https://i.sstatic.net/7UNuF.jpg" alt="from wiki article on phong shading"></a></p>

<p>In openGLES 3.1 (android), I'm turning off interpolation in the fragment shader, and using the provoking vertex (or using the centroid/average), to get the same "low-poly" lighting throughout a tri. The specular calculation is done in the vertex shader, so it's only done once.</p>

<p>I have a flat sea, a mesh of squares (two triangles per quad), with a specular reflection of the sun. But instead of each square being lit the same, the two triangles forming a square get different specular values.</p>

<p>I worked out it's because the tris are at different locations. Although the sun's rays are parallel (with the same angle of incidence at all locations), the angle between each tri and the <em>viewer</em> is slightly different, depending on where the tri is relative to the viewer.</p>

<p><a href="https://i.sstatic.net/X9oGg.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/X9oGg.png" alt="[Introduction to Computer Graphics, *David J. Eck*](http://math.hws.edu/graphicsbook/c4/s1.html)"></a></p>

<blockquote>
  <p>This diagram (<a href="http://math.hws.edu/graphicsbook/c4/s1.html" rel="nofollow noreferrer"><em>Intro to Computer Graphics</em>, David J. Eck</a>) only shows the light from one point, for observers at different locations, but you can see that light from different points would produce a shifted cone, having a similar effect on an observer at one place.</p>
</blockquote>

<p>A brute force solution would be to store a special "location" for each vertex of each tri, and set "location" to the same value for each of the 4 verices of the two tris forming the square.</p>

<p>But that's inefficient, and I'm using a STRIP for the mesh. I don't think this brute force solution work, because any <em>per vertex</em> data would be used by the 4 squares sharing that vertex, wouldn't they? Or can you have <em>per tri</em> data?</p>

<blockquote>
  <p><strong>EDIT</strong> I currently have <em>per vertex</em> normals - used in the specular calc - and only the normal of the provoking vertex is used for a tri. This works out as <em>per tri</em>, since only one tri is provoked by each vertex. I could give the same "location" to both tris in a quad this way. But it's still brute force - is there a better way?</p>
</blockquote>

<p>Or, can you tell which tri of a quad you're in, so you can decide what it's "location" should be?</p>

<p>It seems so simple, but doesn't fit with openGL ES's approach... is there a way to do it? Note it's openGL ES 3.1 (mobile).</p>

<shader><mesh><specular><opengl-es><android>
Same specular lighting on both tris in a quad (for "low-poly" "flat shading" look)?
hyperpallium
# Same specular lighting on both tris in a quad (for "low-poly" "flat shading" look)?

(Asked by: username_0 on 2017-12-18)

Here's an example of the [flat shaded](https://wikipedia.org/wiki/File:Phong-shading-sample.jpg) squares I want. But my squares are made of two triangles, and I'm getting flat shading of those *triangles*.

[![from wiki article on phong shading](https://i.sstatic.net/7UNuF.jpg)](https://i.sstatic.net/7UNuF.jpg)

In openGLES 3.1 (android), I'm turning off interpolation in the fragment shader, and using the provoking vertex (or using the centroid/average), to get the same "low-poly" lighting throughout a tri. The specular calculation is done in the vertex shader, so it's only done once.

I have a flat sea, a mesh of squares (two triangles per quad), with a specular reflection of the sun. But instead of each square being lit the same, the two triangles forming a square get different specular values.

I worked out it's because the tris are at different locations. Although the sun's rays are parallel (with the same angle of incidence at all locations), the angle between each tri and the *viewer* is slightly different, depending on where the tri is relative to the viewer.

[![[Introduction to Computer Graphics, *David J. Eck*](http://math.hws.edu/graphicsbook/c4/s1.html)](https://i.sstatic.net/X9oGg.png)](https://i.sstatic.net/X9oGg.png)

> This diagram ([*Intro to Computer Graphics*, David J. Eck](http://math.hws.edu/graphicsbook/c4/s1.html)) only shows the light from one point, for observers at different locations, but you can see that light from different points would produce a shifted cone, having a similar effect on an observer at one place.

A brute force solution would be to store a special "location" for each vertex of each tri, and set "location" to the same value for each of the 4 verices of the two tris forming the square.

But that's inefficient, and I'm using a STRIP for the mesh. I don't think this brute force solution work, because any *per vertex* data would be used by the 4 squares sharing that vertex, wouldn't they? Or can you have *per tri* data?

> **EDIT** I currently have *per vertex* normals - used in the specular calc - and only the normal of the provoking vertex is used for a tri. This works out as *per tri*, since only one tri is provoked by each vertex. I could give the same "location" to both tris in a quad this way. But it's still brute force - is there a better way?

Or, can you tell which tri of a quad you're in, so you can decide what it's "location" should be?

It seems so simple, but doesn't fit with openGL ES's approach... is there a way to do it? Note it's openGL ES 3.1 (mobile).

**Tags:** shader, mesh, specular, opengl-es, android


---

## 3 answers

### Answer by username_1 on 2017-12-19. Score: 1 | Accepted answer

If I understand you correctly, the problem is that the provoking vertex isn't the same vertex between the two triangles in a quad, due to using triangle strips. You could switch to using an indexed triangle list, and set up indices in such a way that the provoking vertex is the same in each quad. For instance, if one quad is vertices {0, 1, 2, 3} (CCW) then you might write {0, 1, 2, 3, 0, 2} in your index buffer so that 2 is the provoking vertex for both triangles. This should still be pretty efficient.

Another possibility (more involved, but more flexible) is to use the built-in [`gl_VertexID`](http://docs.gl/el3/gl_VertexID) variable in your vertex shader to figure out which quad you're in (eg `int quadID = gl_VertexID / 4`), and use an appropriate shading location for that quad—the centroid of its vertices, for instance. However, for this to work, I think you would have to "un-share" the vertices so that each quad has its own 4 unique vertices (the two triangles in a quad can still share). So you would have to use primitive restarting, or again switch to indexed non-strip draws. You could also have per-quad data in an SSBO that you manually fetch using your computed quad index.

> **Comments:**
> **username_0**: Thanks, that's really clever! I think it almost doubles the number of 16bit indices, but isn't there some caching advantage to indexing too? TIL ES 3.1 has `gl_VertexID` and `primitive restart` (thought degenerate tris was the only way)... pity there's no `gl_PrimitiveID`. I see it's more flexible, but I think same memory overhead as the provoking-trick.  
> **username_1**: @username_0 Yeah, more indices. They're usually a pretty small memory overhead compared to vertex data, but YMMV. As for cache, a well optimized indexed mesh can be as good or better than strips for general meshes, but I'm not sure if that's true for pure grid meshes.  
> **username_0**: I can see it's much less than vertex data; but better to have no extra at all (*if* possible...). I probably shouldn't worry too much over efficiency at this stage - it seems a bit hard to predict. BTW I was thinking the way to cache-optimize a (plane) mesh is to split the rows, making it short enough so the vertices shared with the above tris are still in cache when needed (I don't think there's benefit to it being any shorter; and a small detriment with losing the horizontally shared vertices where the row is split.).  
> **username_1**: @username_0 You might be interested in this article: [Optimal grid rendering is not optimal](https://zeuxcg.org/2017/07/31/optimal-grid-rendering-is-not-optimal/)  
> **username_0**: Spot on. Definitely best to not worry about optimizing yet! I wonder if different on mobile GPUs, which probably do fewer clever things under the hood(?)  
> **username_0**: With using the same provoking vertex, the location will be for that vertex, not the center of the square. But because I have the normal, I can work out the gradient and because I have a 2D height map (i.e. heights over a uniform 2D grid), I can calculate the exact 3D location of the center. There'a  bit of calculation there, but probably faster than the bandwidth cost of explicitly storing the center.  
> **username_0**: I'm not sure of the meaning of `gl_VertexID`. With the "un-sharing", can you use the same indexing as for the first method? i.e. `gl_VertexID` is not the index of the vertex, but the index in the list of indices? So if the same vertex is used twice, that vertex has two different `gl_VertexID`'s?  
> **username_1**: @username_0 It's the index into the vertex buffer (ie the value from the index buffer). If a vertex is re-used, it has the same `gl_VertexID` every time. By "un-sharing" I mean that, e.g.: vertices 0–3 are the first quad, 4–7 are the second quad, etc. So if a vertex is used in multiple quads, it's duplicated in the vertex buffer for each quad.  
> **username_0**: Thanks, so that's much more buffer-expensive than the first ("provoking")  method. (I see what you mean: but at least you can reuse/share two vertices within the one quad.) Another approach to the heightmap might interact: my heights change, so 2D plane in a "static"-hinted buffer, and heights in a "dynamically"-hinted buffer. But, one could also calculate the 2D location, based on knowing which quad it's in (alternative: send in x,y coords, in just 16bit (or 8bit) Uints). But maybe caching won't catch the duplicates?  

---

### Answer by username_2 on 2017-12-18. Score: 0

The easiest fix would be to do your light calculations in the fragment shader rather than per-vertex—you’ll avoid the discontinuity you’re currently seeing and your lighting will appear more natural (while still fitting the “low-poly” aesthetic). If that’s not an option, then you’re probably stuck with passing in each quad’s center along with the normals you’re already supplying.

> **Comments:**
> **username_0**: Thanks. If I understand correctly, this will give a gradually changing specular highlight across the tri (because each pixel is in a slightly different location). The discontinuity between tris will vanish, because adjacent pixels in the different tris are very close in location. Is that what you mean? [BTW I've gotten a similar effect by letting the specular result from the vertex shader interpolate in the fragment shader]. I agree this is more natural - but I want uniform shading across the quad (so the discontinuity is between quads). A bit like the flashing facets of a jewel.  
> **username_3**: a common way to get that discontinuity is to interpolate position but not interpolate normals. maybe this works better for you  

---

### Answer by username_4 on 2017-12-18. Score: 0

You are probably mixing thing up. As I understood from you explanation, you are trying to do Phong shading and you want flat shading.

Your problem might be happening because you are calculating a specular component that depends on the view/camera direction.

It would help if you could add pictures explaining what is happening and what you want to happen.

> **Comments:**
> **username_0**: Thanks. Yes, "flat shading" as [here](https://wikipedia.org/wiki/File:Phong-shading-sample.jpg). And yes, the diffuse + specular reflection of [Phong shading](https://wikipedia.org/wiki/Phong_reflection_model), but without the interpolation (TIL the interpolation is also called "Phong shading"). I believe the specular component increases the angle between the angle of reflection and the viewing direction decreases (brightest when aligned).... specular highlights move as you move your head. I needed a diagram too! I'll look for an online diagram tool (do you know of one?)  
> **username_0**: typo, should be: "specular component *increases* **as** the angle between reflected ray and the direction of the viewer *decreases*"  

---

