我正在生成平面顶点,其中y值是由高度图(噪声)算法生成的。这就是我生成顶点数组的方式:

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);
    }
}


之后,我生成像这样的索引值(我知道可以在这里进行很多优化) :

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();


最后我使用以下方式绘制平面:

gl.drawElements(gl.TRIANGLE_STRIP, buffers.numIndices, gl.UNSIGNED_SHORT, 0);

所以如果我使用POINTS作为模式,飞机看起来应该是这样的:



如果我使用的是TRINGLE_STRIP,结果看起来是错误的:



首先我以为索引可能是错误的原因,但是随后我通过缩放到3x3的网格/平面进行了检查,顶点和索引的输出看起来像我期望的那样:

顶点:

[-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]


注:


顶点可能与您从上述循环中所期望的不完全对应。这是因为在循环之后,我将mesh
居中放置在原点附近。


索引:我的猜测是问题是我正在逆时针推动三角形,这就是为什么我尝试启用剔除和深度测试,但是却无济于事的原因:

[0, 3, 1, 4, 2, 5, 8, 4, 7, 3, 6]




您猜猜是什么原因导致TRIANGLE_STRIP渲染错误?

更新1:

根据@PaulHK的建议,我更改了索引创建循环两次将单个条的最后一个索引插入。

gl.enable(gl.DEPTH_TEST);
gl.enable(gl.CULL_FACE);
gl.cullFace(gl.FRONT);


对于3x3网格,它产生:

顶点:

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);
        }
    }
}


>索引:

[-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]


不幸的是,渲染的对象看起来仍然相同。

更新2:

我使用Diamond-square算法生成网格。这需要一个大小为(2^n) + 1的网格。
即:


2、3、5、9、17、33、65、129、257、513 ...


也许这只是一个巧合,但在我看来,可以使用Update 1中的步骤正确显示大小为3 - 129的网格。对于大小为257及以上的网格,有错误。 :




257x257似乎不正确:


评论

您是否打算将其绘制为一条条?您应该将其绘制为一系列条带。仍然可以在1个绘制调用中完成此操作,但是您需要在每个带状列的末尾插入一个退化的三角形(复制最后一个顶点)。
@PaulHK对于3x3的飞机,它应该是[0、3、1、4、2、5、5、8、4、7、3、6],对吗?但它似乎仍然无法正常工作。

它应该是[Col(n),Col(n)+ 1,Col(n + 1),Col(n + 1)+ 1,Col(n + 2),Col(n + 2)+1,.. .. Col(n + 8)+1,Col(n + 8)+1] ..因此,对于每对索引,我们为当前列取一个顶点,从其相邻列取一个顶点,这与您的带区相同。最后,我们插入一个重复的顶点,这将创建一个退化的三角形。这将导致下一组带状索引开始新的带状,而没有任何三角形连接到最后一列。

computergraphics.stackexchange.com/questions/3746/…

好的,有趣的3x3版本有效,而257x257无效。您是否正在使用16位索引?因为您只能使用16位索引来寻址256x256。对于您的情况,您需要使用32位索引。

#1 楼

这看起来像是您的indice缓冲区中16位截断的情况。对于257x257的网格,您将要处理65536个以上的顶点,因此您将需要使用32位索引缓冲区。
>
gl.drawElements(gl.TRIANGLE_STRIP, buffers.numIndices, gl.UNSIGNED_SHORT, 0);


还要更改缓冲区分配代码以匹配此类型(Uint16Array-> Java的Uint32Array)。

评论


$ \ begingroup $
您可能要提到的是,在JavaScript / WebGL中,包含索引的数组必须是Uint32Array而不是Uint16Array。
$ \ endgroup $
– indexoutofbounds
18/09/10'9:19

$ \ begingroup $
感谢您的建议,我已经修正了答案。我想使答案语言不可知,因为这在任何GL实现中都可能发生。
$ \ endgroup $
–PaulHK
18/09/11在2:59