I'm working on a heightmap algorithm using webgl. I thought I had it working but I realised a critical problem with my grid generation. If I set my grid size > 128 iterations, something strange happens: the grid stops growing on the z axis and I end up with a rectangular instead of a squared grid.
This is the code I'm using:
/*
v1---v0
| / |
| / |
| / |
v2---v3
*/
var size = 5; // max size of terrain
var width = 128; // texture width
var l = size/width;
this.vertices = [];
for(var j=0; j<width; j++){ // y
for(var i=0; i<width; i++){ // x
var p0 = new Point3D(l*(i+1), 0, l * (j+1)); // Upper right
var p1 = new Point3D(l*i, 0, l * (j+1)); // Upper left
var p2 = new Point3D(l*i, 0, l * j); // Bottom left
var p3 = new Point3D(l*(i+1), 0, l * j); // Bottom right
var base = this.vertices.length/3;
this.vertices.push(p0.x, p0.y, p0.z); // v0
this.vertices.push(p1.x, p1.y, p1.z); // v1
this.vertices.push(p2.x, p2.y, p2.z); // v2
this.vertices.push(p3.x, p3.y, p3.z); // v3
// Add indices
this.indices.push(base); // 0
this.indices.push(base+1); // 1
this.indices.push(base+2); // 2
this.indices.push(base); // 0
this.indices.push(base+2); // 2
this.indices.push(base+3); // 3
}
}
/*** Later in my draw method: *****/
{....}
gl.drawElements(gl.LINE_STRIP, this.mesh.vjsBuffer.numItems, gl.UNSIGNED_SHORT, 0);
If I use size=128 it works fine; the problem comes when I try to use a 256x256 or any higher image size
After some trial and error, I discovered that the limit is 128. If I use 129 or higher, the grid stops growing and starts shrinking.
I finally found out what the issue was. It turns out that WebGL has a limit of 65536 indices per ELEMENT_ARRAY_BUFFER. So if you try to load objects with a lot of vertices it will result in unexpected behaviours.
There seems to be a couple solutions to solve this issue:
enable the gl extension "OES_element_index_uint" and use Uint32Array when you bind your index buffer.
Split your Mesh into chunks and render 1 at the time
Don't use gl.drawElements but gl.drawArrays instead.
I ended up using the 3rd alternative. Bear in mind that this may not be the most efficient way, as you need to define the same vertex multiple times.
The result now is a good looking terrain (after calculating normals and applying lighting)