#javascript #3d #webgl #mapbox-gl-js #webgl2
#javascript #3D #webgl #mapbox-gl-js #webgl2
Вопрос:
Я использую MapboxGL для рендеринга geojson в виде полигона на карте. Страница загружается и отображается правильно, но когда я перемещаю карту, я получаю эту ошибку после некоторого числа (обычно между ~ 30-100) вызовов рендеринга, и полигон исчезает.
В Chrome:
GL_INVALID_OPERATION: Insufficient buffer size. (Chrome)
В Firefox:
WebGL warning: drawElementsInstanced: Index buffer too small. (FF)
Мне удалось (я думаю) сузить его до проблемы с:
gl.drawElements(gl.TRIANGLES, tResult.triangleIndices.length, gl.UNSIGNED_SHORT, 0);
Используя Spector.js расширение Я видел, что второй аргумент (count) в методе drawElements изменяется при каждом вызове (TResult.triangleIndices.длина не меняется, когда я ее регистрирую). Это может быть отвлекающим маневром, потому что он работает для 30-100 рендеров.
Я пробовал различные комбинации типов данных для типа буфера в BufferData() и drawElements(), но безуспешно.
Я пробовал использовать сетки с более низкой поляризацией.
Я пробовал вызывать различные методы gl.clear для каждого прохода рендеринга.
Это, вероятно, не имеет значения, но, черт возьми, это приложение vue-cli, поэтому оно загружает библиотеки из npm.
Вот соответствующий код:
Инициализация:
[...setting up shaders and stuff]
// link the two shaders into a WebGL program
this.program = gl.createProgram();
gl.attachShader(this.program, vertexShader);
gl.attachShader(this.program, fragmentShader);
gl.linkProgram(this.program);
this.aPos = gl.getAttribLocation(this.program, 'a_pos');
gl.clearColor(1.0, 1.0, 1.0, 1.0); // Clear to black, fully opaque
// create and initialize a WebGLBuffer to store vertex and color data
this.buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(tResult.triangleLocations), gl.STATIC_DRAW);
this.verticesIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.verticesIndexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new
Uint16Array(tResult.triangleIndices), gl.STATIC_DRAW);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.enable(gl.CULL_FACE);
gl.cullFace(gl.BACK);
Визуализация:
render: function (gl, matrix) {
gl.useProgram(this.program);
gl.uniformMatrix4fv(
gl.getUniformLocation(this.program, 'u_matrix'), false,matrix);
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
gl.enableVertexAttribArray(this.aPos);
gl.vertexAttribPointer(this.aPos, 2, gl.FLOAT, false, 0, 0);
gl.drawElements(gl.TRIANGLES, tResult.triangleIndices.length, gl.UNSIGNED_SHORT, 0);
}
Ответ №1:
Мне кажется, что проблема заключается в том, что вы не устанавливаете ELEMENT_ARRAY_BUFFER
при рендеринге.
Смотрите эту диаграмму состояния webgl
если вы не используете массивы вершин (чего вы не делаете), тогда атрибуты и привязки буфера являются глобальным состоянием. Итак, если что-то изменяет это состояние между временем инициализации объектов и временем рендеринга объектов (например, рендеринг mapbox), то при рендеринге вы будете использовать другие буферы, чем вы настроили в init.
Попробуйте добавить
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.verticesIndexBuffer);
Перед вызовом drawElements
Аналогично, другое состояние, которое вы настраиваете, например, отбраковка лиц, может длиться или не длиться до времени рендеринга, если что-то еще происходит в том же контексте webgl.
Если это не так, вы могли бы попробовать также webgl-lint для получения незначительной информативной ошибки. Особенно, если вы помечаете свои буферы
Комментарии:
1. Спасибо, это помогло! Мне явно нужно многому научиться, потому что я не понимаю, почему это будет работать для первого x числа рендерингов, а затем останавливаться. Я посмотрю на ссылки, которые вы включили. Спасибо!
2. Спасибо, у меня было много времени, чтобы определить причину этого.