<p>I figured out the mistake that I was making and confirmed the hypothesis in my comment above. I was rendering each quad with its distinct set of vertex normals calculated from the local parametrisation. With lighting enabled, the vertices were therefore shaded differently for adjacent quads owing to the different dot products between the local normal and the light direction vector.</p>

<p>What I did was average out the normals to create a unique normal at each vertex. Now when I fly into the clouds, I do not see the quad boundaries.</p>

<p>As Dan suggested, I could avoid the problem altogether by disabling lighting, but it would eliminate the ability to simulate different times of the day and in any case, the fix above worked and only involved about 30 lines of code!</p>

<p>Problem solved.</p>

<p>In case anyone else finds this useful, here's the code (I wrote it in VBA) to calculate averaged vertex normals given a set of vertices on a surface that is topologically rectangular.</p>

<pre><code>Sub Calculate_Averaged_Vertex_Normals(Vertx#(), M%, N%, VnormX#())
' INPUT:
'L,M: Array Dimensions
' Vertx - 3D array of vertex coordinates
' OUTPUT: VnormX: 3D array of Averaged Vertex Normals 

 Dim i%, j%, k%, p%, q%, w%, NormX#(3), Ncount%(), Vx#(), Fn#(3),Gn#(3),Hn#(3),A#
 ReDim Ncount%(0 To L, NF + 1), Vx(0 To L, NF + 1, 4, 3)
 For k = 0 To M - 1
  For i = 0 To N - 1
   Call Quad_Normal_Vector_Parametrisation(Vertx,k, i,Fn,Gn,Hn) ' Local Normals at each Vertex

     p = k: q = i: Ncount(p, q) = Ncount(p, q) + 1: j = Ncount(p, q)
     Call Quad_Vertex_Normal(0, 0, NormX,Fn,Gn,Hn)
     For w = 1 To 3: Vx(p, q, j, w) = NormX(w): Next w

     p = k: q = i + 1: Ncount(p, q) = Ncount(p, q) + 1: j = Ncount(p, q)
     Call Quad_Vertex_Normal(1, 0, NormX,Fn,Gn,Hn)
     For w = 1 To 3: Vx(p, q, j, w) = NormX(w): Next w

     p = k + 1: q = i + 1: Ncount(p, q) = Ncount(p, q) + 1: j = Ncount(p, q)
     Call Quad_Vertex_Normal(1, 1, NormX,Fn,Gn,Hn)
     For w = 1 To 3: Vx(p, q, j, w) = NormX(w): Next w

     p = k + 1: q = i: Ncount(p, q) = Ncount(p, q) + 1: j = Ncount(p, q)
     Call Quad_Vertex_Normal(0, 1, NormX,Fn,Gn,Hn)
     For w = 1 To 3: Vx(p, q, j, w) = NormX(w): Next w
  Next i
 Next k

 For k = 0 To M
  For i = 0 To N
   For w = 1 To 3
    A = 0#
    For j = 1 To Ncount(k, i)
     A = A + Vx(k, i, j, w)
    Next j
    VnormX(k, i, w) = A / Ncount(k, i)          ' Averaged Vertex Normal
   Next w
  Next i
 Next k
End Sub

Sub Quad_Normal_Vector_Parametrisation(Vertx#(),k%, i%,Fn#(),Gn#(),Hn#())
 Dim j%, Bv#(3), CV#(3), Dv#(3)
 For j = 1 To 3
  Bv(j) = Vertx(k, i + 1, j) - Vertx(k, i, j)           ' Tangent Vectors from Bilinear Parametrisation
  CV(j) = Vertx(k + 1, i, j) - Vertx(k, i, j)
  Dv(j) = Vertx(k + 1, i + 1, j) - Vertx(k, i + 1, j) - Vertx(k + 1, i, j) + Vertx(k, i, j)
 Next j
 Call CrossProd(Bv, CV, Fn)             ' Normal Vector from Cross Product of Tangent Vectors.
 Call CrossProd(Bv, Dv, Gn)
 Call CrossProd(Dv, CV, Hn)
End Sub

Sub Quad_Vertex_Normal(x#, y#, NormX#(),Fn#(),Gn#(),Hn#())
 Dim j%, Norm#
 Norm = 0#
 For j = 1 To 3
  NormX(j) = Fn(j) + Gn(j) * x + Hn(j) * y
  Norm = Norm + NormX(j) * NormX(j)
 Next j
 Norm = Sqr(Norm)
 For j = 1 To 3
  NormX(j) = NormX(j) / Norm
 Next j
End Sub

Sub CrossProd(x#(), y#(), Z#())
 Z(1) = x(2) * y(3) - y(2) * x(3)
 Z(2) = y(1) * x(3) - x(1) * y(3)
 Z(3) = x(1) * y(2) - y(1) * x(2)
End Sub
</code></pre>

CC BY-SA 3.0
2017-07-04T14:04:28.497Z
2017-07-04T16:44:40.883Z
2017-07-04T16:44:40.883Z
Sharat V Chandrasekhar
<p>I'm rendering clouds by applying a texture map on the inside of an ellipsoid. From a distance (at the center of the cloud ellipsoid) the texture looks quite nice and reasonably realistic. See image below:
<a href="https://i.sstatic.net/7eEYB.jpg" rel="nofollow noreferrer"><img src="https://i.sstatic.net/7eEYB.jpg" alt="enter image description here"></a></p>

<p>The problem is that as I fly close to the boundary of the ellipsoid (into the cloud) I see the boundaries of each of the quads that make up the ellipsoid. See image below:</p>

<p><a href="https://i.sstatic.net/OBo1n.jpg" rel="nofollow noreferrer"><img src="https://i.sstatic.net/OBo1n.jpg" alt="enter image description here"></a>
Any suggestions on how to get around this artifact would be appreciated. I'm using 50 grid segments in both the azimuthal and polar directions of the ellipsoid which is actually truncated 10 degrees below the poles. The texture map uses GL_MODULATE with GL_LINEAR and GL_LINEAR_MIPMAP_LINEAR for the Min and Mag filters. The ellipsoid base colour is white, so that there are no shading issues involved. I have also verified that the texture coordinates are correctly applied and the normals are oriented correctly.</p>

<p>Thanks in advance.</p>

<p>I could cheat and use a lot of fog which would mimic actually flying into a cloud, but I'd really like to implement an elegant robust solution.</p>

CC BY-SA 3.0
2017-07-04T12:02:44.047Z
Can you show us your shader?
Dan Hulme
CC BY-SA 3.0
2017-07-04T12:27:28.457Z
Well, since the base colour of all the quads (or triangles) is white upon which I overlay the cloud feature, I didn't think I needed to do anything specific with shading. For the light model I've used GL_SMOOTH, if hat helps.
Sharat V Chandrasekhar
CC BY-SA 3.0
2017-07-04T12:52:03.037Z
Well, there shouldn't be a light model at all. You're using the obsolete fixed-function shading, aren't you?
Dan Hulme
CC BY-SA 3.0
2017-07-04T12:52:05.600Z
I *think* I may have figured out the problem. For common vertices between adjacent quads, I'm using different normals depending on the quad being rendered. I calculate these vertex normals  as the local cross product of the unit tangent vectors that follow from the bilinear parametrisation of each quad. If I average out these normals, then that *should* address the issue. I'll need to do some coding.
Sharat V Chandrasekhar
CC BY-SA 3.0
2017-07-04T12:53:30.110Z
if you average them out, you'll get something that actually looks like an ellipsoid, but that shouldn't be necessary anyway for your use case.
Dan Hulme
CC BY-SA 3.0
2017-07-04T13:32:46.747Z
True,  but it would (hopefully!) eliminate the visible boundaries between adjacent quads due to the light model interacting with different normals at the common vertices of adjacent quads. What's encouraging is that when I disabled lighting, I confirmed that the quad boundaries were no longer visible, so back to coding it is for me!
Sharat V Chandrasekhar
CC BY-SA 3.0
2017-07-04T13:35:42.290Z
Well yes, disabling lighting is the right answer. It'll fix this problem as well as bias added by the lighting, which you haven't yet noticed. You should post that as an answer and then not worry about the normals at all.
Dan Hulme
<opengl><texture>
Hiding Boundaries with the Eye close to a set of adjacent textured quads
Sharat V Chandrasekhar
# Hiding Boundaries with the Eye close to a set of adjacent textured quads

(Asked by: username_0 on 2017-07-04)

I'm rendering clouds by applying a texture map on the inside of an ellipsoid. From a distance (at the center of the cloud ellipsoid) the texture looks quite nice and reasonably realistic. See image below:
[![enter image description here](https://i.sstatic.net/7eEYB.jpg)](https://i.sstatic.net/7eEYB.jpg)

The problem is that as I fly close to the boundary of the ellipsoid (into the cloud) I see the boundaries of each of the quads that make up the ellipsoid. See image below:

[![enter image description here](https://i.sstatic.net/OBo1n.jpg)](https://i.sstatic.net/OBo1n.jpg)
Any suggestions on how to get around this artifact would be appreciated. I'm using 50 grid segments in both the azimuthal and polar directions of the ellipsoid which is actually truncated 10 degrees below the poles. The texture map uses GL\_MODULATE with GL\_LINEAR and GL\_LINEAR\_MIPMAP\_LINEAR for the Min and Mag filters. The ellipsoid base colour is white, so that there are no shading issues involved. I have also verified that the texture coordinates are correctly applied and the normals are oriented correctly.

Thanks in advance.

I could cheat and use a lot of fog which would mimic actually flying into a cloud, but I'd really like to implement an elegant robust solution.

**Tags:** opengl, texture

> **Comments:**
> **username_1**: Can you show us your shader?  
> **username_0**: Well, since the base colour of all the quads (or triangles) is white upon which I overlay the cloud feature, I didn't think I needed to do anything specific with shading. For the light model I've used GL_SMOOTH, if hat helps.  
> **username_1**: Well, there shouldn't be a light model at all. You're using the obsolete fixed-function shading, aren't you?  
> **username_0**: I *think* I may have figured out the problem. For common vertices between adjacent quads, I'm using different normals depending on the quad being rendered. I calculate these vertex normals  as the local cross product of the unit tangent vectors that follow from the bilinear parametrisation of each quad. If I average out these normals, then that *should* address the issue. I'll need to do some coding.  
> **username_1**: if you average them out, you'll get something that actually looks like an ellipsoid, but that shouldn't be necessary anyway for your use case.  
> **username_0**: True,  but it would (hopefully!) eliminate the visible boundaries between adjacent quads due to the light model interacting with different normals at the common vertices of adjacent quads. What's encouraging is that when I disabled lighting, I confirmed that the quad boundaries were no longer visible, so back to coding it is for me!  
> **username_1**: Well yes, disabling lighting is the right answer. It'll fix this problem as well as bias added by the lighting, which you haven't yet noticed. You should post that as an answer and then not worry about the normals at all.  

---

## 1 answers

### Answer by username_0 on 2017-07-04. Score: 3

I figured out the mistake that I was making and confirmed the hypothesis in my comment above. I was rendering each quad with its distinct set of vertex normals calculated from the local parametrisation. With lighting enabled, the vertices were therefore shaded differently for adjacent quads owing to the different dot products between the local normal and the light direction vector.

What I did was average out the normals to create a unique normal at each vertex. Now when I fly into the clouds, I do not see the quad boundaries.

As Dan suggested, I could avoid the problem altogether by disabling lighting, but it would eliminate the ability to simulate different times of the day and in any case, the fix above worked and only involved about 30 lines of code!

Problem solved.

In case anyone else finds this useful, here's the code (I wrote it in VBA) to calculate averaged vertex normals given a set of vertices on a surface that is topologically rectangular.

```
Sub Calculate_Averaged_Vertex_Normals(Vertx#(), M%, N%, VnormX#())
' INPUT:
'L,M: Array Dimensions
' Vertx - 3D array of vertex coordinates
' OUTPUT: VnormX: 3D array of Averaged Vertex Normals 

 Dim i%, j%, k%, p%, q%, w%, NormX#(3), Ncount%(), Vx#(), Fn#(3),Gn#(3),Hn#(3),A#
 ReDim Ncount%(0 To L, NF + 1), Vx(0 To L, NF + 1, 4, 3)
 For k = 0 To M - 1
  For i = 0 To N - 1
   Call Quad_Normal_Vector_Parametrisation(Vertx,k, i,Fn,Gn,Hn) ' Local Normals at each Vertex

     p = k: q = i: Ncount(p, q) = Ncount(p, q) + 1: j = Ncount(p, q)
     Call Quad_Vertex_Normal(0, 0, NormX,Fn,Gn,Hn)
     For w = 1 To 3: Vx(p, q, j, w) = NormX(w): Next w

     p = k: q = i + 1: Ncount(p, q) = Ncount(p, q) + 1: j = Ncount(p, q)
     Call Quad_Vertex_Normal(1, 0, NormX,Fn,Gn,Hn)
     For w = 1 To 3: Vx(p, q, j, w) = NormX(w): Next w

     p = k + 1: q = i + 1: Ncount(p, q) = Ncount(p, q) + 1: j = Ncount(p, q)
     Call Quad_Vertex_Normal(1, 1, NormX,Fn,Gn,Hn)
     For w = 1 To 3: Vx(p, q, j, w) = NormX(w): Next w

     p = k + 1: q = i: Ncount(p, q) = Ncount(p, q) + 1: j = Ncount(p, q)
     Call Quad_Vertex_Normal(0, 1, NormX,Fn,Gn,Hn)
     For w = 1 To 3: Vx(p, q, j, w) = NormX(w): Next w
  Next i
 Next k

 For k = 0 To M
  For i = 0 To N
   For w = 1 To 3
    A = 0#
    For j = 1 To Ncount(k, i)
     A = A + Vx(k, i, j, w)
    Next j
    VnormX(k, i, w) = A / Ncount(k, i)          ' Averaged Vertex Normal
   Next w
  Next i
 Next k
End Sub

Sub Quad_Normal_Vector_Parametrisation(Vertx#(),k%, i%,Fn#(),Gn#(),Hn#())
 Dim j%, Bv#(3), CV#(3), Dv#(3)
 For j = 1 To 3
  Bv(j) = Vertx(k, i + 1, j) - Vertx(k, i, j)           ' Tangent Vectors from Bilinear Parametrisation
  CV(j) = Vertx(k + 1, i, j) - Vertx(k, i, j)
  Dv(j) = Vertx(k + 1, i + 1, j) - Vertx(k, i + 1, j) - Vertx(k + 1, i, j) + Vertx(k, i, j)
 Next j
 Call CrossProd(Bv, CV, Fn)             ' Normal Vector from Cross Product of Tangent Vectors.
 Call CrossProd(Bv, Dv, Gn)
 Call CrossProd(Dv, CV, Hn)
End Sub

Sub Quad_Vertex_Normal(x#, y#, NormX#(),Fn#(),Gn#(),Hn#())
 Dim j%, Norm#
 Norm = 0#
 For j = 1 To 3
  NormX(j) = Fn(j) + Gn(j) * x + Hn(j) * y
  Norm = Norm + NormX(j) * NormX(j)
 Next j
 Norm = Sqr(Norm)
 For j = 1 To 3
  NormX(j) = NormX(j) / Norm
 Next j
End Sub

Sub CrossProd(x#(), y#(), Z#())
 Z(1) = x(2) * y(3) - y(2) * x(3)
 Z(2) = y(1) * x(3) - x(1) * y(3)
 Z(3) = x(1) * y(2) - y(1) * x(2)
End Sub

```


---

