I am generating plane vertices where the y values are generated by a heightmap (noise) algorithm. This is how I produce my vertex array:
for (let row = 0; row < noise.length; row++) {
for (let col = 0; col < noise[0].length; col++) {
color = noise[row][col];
positions.push(row, color, col);
}
}
After that I generate index values like this (I know that there is a lot of optimization that can be done here):
const height = noise.length + 1;
const width = noise[0].length + 1;
for (let row = 0; row < height - 1; row++) {
if (row % 2 === 0) {
if (row === height - 2) break;
for (let col = 0; col < width - 1; col++) {
indices.push(col + row * (width));
indices.push(col - 1 + (row + 1) * (width));
}
} else {
for (let col = width - 2; col >= 0; col--) {
indices.push(col - 2 + (row + 1) * (width));
indices.push(col - 2 + row * (width));
}
}
}
indices.pop();
Finally I draw the plane using:
gl.drawElements(gl.TRIANGLE_STRIP, buffers.numIndices, gl.UNSIGNED_SHORT, 0);
So if I use POINTS
as mode, the plane seem to look as it should:
Whereas if I am using TRINGLE_STRIP
the result looks wrong:
First I thought wrong indices might be the reason but then I checked by scaling to a 3x3 grid/plane and the vertex and index output looked as I would have expected:
Vertices:
[-1, -43.89, -1,
-1, -82.27, 0,
-1, -23.06, 1,
0, -43.43, -1,
0, -54.85, 0,
0, -66.27, 1,
1, -61.89, -1,
1, -27.43, 0,
1, -59.89, 1]
Note:
The vertices might not exactly correspond to what you would have expected from above loop. That is because I am centering the
mesh
around origin after the loop.
Indices:
[0, 3, 1, 4, 2, 5, 8, 4, 7, 3, 6]
So my guess is that the problem is that I am pushing my triangles counterclockwise, that is why I tried to enable culling and depth testing but that did not help either:
gl.enable(gl.DEPTH_TEST);
gl.enable(gl.CULL_FACE);
gl.cullFace(gl.FRONT);
Any guess what might be the reason for wrong TRIANGLE_STRIP
rendering?
Update 1:
According to @PaulHK's recommendation I changed my index creation loop to insert the last index of a single strip twice.
for (let row = 0; row < rows - 1; row++) {
if (row % 2 === 0) {
for (let col = 0; col < cols; col++) {
indices.push(col + row * cols);
indices.push(col + (row + 1) * cols);
}
} else {
for (let col = cols - 1; col >= 0; col--) {
indices.push(col + (row) * cols);
indices.push(col + (row + 1) * cols);
}
}
}
For a 3x3 grid this produces:
Vertices:
[-1, -9.6, -1,
-1, -64.6, 0,
-1, -11.1, 1,
0, -38.8, -1,
0, -32.8, 0,
0, -26.8, 1,
1, -37.0, -1,
1, -1, 0,
1, -47.5, 1]
Indices:
[0, 3, 1, 4, 2, 5, 5, 8, 4, 7, 3, 6]
Unfortunately the rendered object still looks the same.
Update 2:
I use the Diamond-square algorithm to generate the mesh. This requires a grid of size (2^n) + 1
.
I.e.:
2, 3, 5, 9, 17, 33, 65, 129, 257, 513 ...
Maybe it's just a coincidence but it seems to me that the grid can be displayed correctly for sizes 3 - 129
with the procedure from Update 1. For a size of 257 and above the mesh has errors.
[0, 3, 1, 4, 2, 5, 5, 8, 4, 7, 3, 6]
, right? But it still does not seem to work properly. $\endgroup$