WebGL 无效操作缓冲区大小不足
WebGL INVALID OPERATION insufficient buffer size
我正在尝试用 WebGL 编写一个简单的程序,并且 javascript 从 .obj 文件中绘制一个简单的 object。我正在使用 npm 的 webgl-obj-loader 来加载 object。正如标题所说,我不断收到缓冲区大小不足 (Edge) 和索引缓冲区太小 (FF)。我使用了 gl.geterror 函数,我得到了 1282 错误代码,这意味着 INVALID_OPERATION.
window.onload = function () {
OBJ.downloadMeshes(
{
'dragon_vrip': 'models/dragon_vrip.obj',
'cube2': 'models/cube2.obj'
}, webGLStart);
}
这是我加载obj文件的方式。
app.meshes = meshes;
OBJ.initMeshBuffers(gl, app.meshes.dragon_vrip);
OBJ.initMeshBuffers(gl, app.meshes.cube2);
vertArray = app.meshes.cube2.vertices.slice();
normArray = app.meshes.cube2.vertexNormals.slice();
indicesArray = app.meshes.cube2.indices.slice();
texCoord = app.meshes.cube2.textures.slice();
var myMesh=app.meshes.cube2;
var pointsBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, pointsBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertArray, gl.STATIC_DRAW);
gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(0);
var textureBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, textureBuffer);
gl.bufferData(gl.ARRAY_BUFFER, texCoord, gl.STATIC_DRAW);
gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(1);
var normalBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
gl.bufferData(gl.ARRAY_BUFFER, normArray, gl.STATIC_DRAW);
gl.vertexAttribPointer(2, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(2);
var indices = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indices);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indicesArray, gl.STATIC_DRAW);
console.log(indices.size);
第二步:初始化缓冲区。
function drawFunc() {
rotateAngleX += 0.01;
rotateAngleY += 0.02;
mat4.fromXRotation(rotateXMatrix, rotateAngleX);
mat4.fromYRotation(rotateYMatrix, rotateAngleY);
mat4.multiply(modelMatrix, rotateXMatrix, rotateYMatrix);
gl.uniformMatrix4fv(modelMatrixLocation, false, modelMatrix);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawElements(gl.TRIANGLES, indicesArray.length, gl.UNSIGNED_SHORT, 0);
requestAnimationFrame(drawFunc);
}
requestAnimationFrame(drawFunc);
我在这里尝试绘制一个简单的立方体。
数组大小为:vertices:72 indices:36 texCoords:48 normals:72
考虑到顶点是 x、y、z 点的三元组,顶点缓冲区包含 24 个点(vertex[0]=x, vertex[1]=y, vertex[2]=z, ...),并且indices 数组不包含大于 23 的数字,所以我不明白错误发生在哪里。还有什么方法可以调试缓冲区?我尝试了 spector.js 但没有太大帮助,因为绘制调用因错误而无能为力。
好的,出于某种原因,我不得不在 bufferdata 函数中添加新类型的数组,如下所示。
var indices = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indices);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint32Array(indicesArray),gl.STATIC_DRAW);
其余缓冲区也是如此。
查看下面的完整示例:
"use strict";
var m = ThreeDMath;
function main() {
var cubeVertices = [-1, -1, -1,
1, -1, -1,
1, 1, -1, -1, 1, -1, -1, -1, 1,
1, -1, 1,
1, 1, 1, -1, 1, 1,
];
var indices = [
0, 1,
1, 2,
2, 3,
3, 0,
4, 5,
5, 6,
6, 7,
7, 4,
0, 4,
1, 5,
2, 6,
3, 7,
];
var canvas = document.getElementById("c");
var gl = canvas.getContext("webgl");
if (!gl) {
alert("no webgl");
return;
}
var program = webglUtils.createProgramFromScripts(
gl, ["2d-vertex-shader", "2d-fragment-shader"]);
gl.useProgram(program);
var positionLoc = gl.getAttribLocation(program, "a_position");
var worldViewProjectionLoc =
gl.getUniformLocation(program, "u_worldViewProjection");
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array(cubeVertices),
gl.STATIC_DRAW);
gl.enableVertexAttribArray(positionLoc);
gl.vertexAttribPointer(positionLoc, 3, gl.FLOAT, false, 0, 0);
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer);
gl.bufferData(
gl.ELEMENT_ARRAY_BUFFER,
new Uint16Array(indices),
gl.STATIC_DRAW);
function render(clock) {
clock *= 0.001;
var scale = 4;
webglUtils.resizeCanvasToDisplaySize(gl.canvas, window.devicePixelRatio);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.clear(gl.COLOR_BUFFER_BIT);
var fieldOfView = Math.PI * 0.25;
var aspect = canvas.clientWidth / canvas.clientHeight;
var projection = m.perspective(fieldOfView, aspect, 0.0001, 500);
var radius = 5;
var eye = [
Math.sin(clock) * radius,
1,
Math.cos(clock) * radius,
];
var target = [0, 0, 0];
var up = [0, 1, 0];
var view = m.lookAt(eye, target, up);
var worldViewProjection = m.multiplyMatrix(view, projection);
gl.uniformMatrix4fv(worldViewProjectionLoc, false, worldViewProjection);
gl.drawElements(gl.LINES, indices.length, gl.UNSIGNED_SHORT, 0);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
main();
<script src="https://webglfundamentals.org/webgl/resources/webgl-utils.js"></script>
<script src="https://webglfundamentals.org/webgl/resources/webgl-lessons-helper.js"></script>
<script src="https://webglfundamentals.org/webgl/lessons/resources/3d-math.js"></script>
<!-- vertex shader -->
<script id="2d-vertex-shader" type="x-shader/x-vertex">
attribute vec4 a_position; uniform mat4 u_worldViewProjection; void main() { gl_Position = u_worldViewProjection * a_position; }
</script>
<!-- fragment shader -->
<script id="2d-fragment-shader" type="x-shader/x-fragment">
void main() { gl_FragColor = vec4(0,0,0,1); }
</script>
<canvas id="c"></canvas>
我正在尝试用 WebGL 编写一个简单的程序,并且 javascript 从 .obj 文件中绘制一个简单的 object。我正在使用 npm 的 webgl-obj-loader 来加载 object。正如标题所说,我不断收到缓冲区大小不足 (Edge) 和索引缓冲区太小 (FF)。我使用了 gl.geterror 函数,我得到了 1282 错误代码,这意味着 INVALID_OPERATION.
window.onload = function () {
OBJ.downloadMeshes(
{
'dragon_vrip': 'models/dragon_vrip.obj',
'cube2': 'models/cube2.obj'
}, webGLStart);
}
这是我加载obj文件的方式。
app.meshes = meshes;
OBJ.initMeshBuffers(gl, app.meshes.dragon_vrip);
OBJ.initMeshBuffers(gl, app.meshes.cube2);
vertArray = app.meshes.cube2.vertices.slice();
normArray = app.meshes.cube2.vertexNormals.slice();
indicesArray = app.meshes.cube2.indices.slice();
texCoord = app.meshes.cube2.textures.slice();
var myMesh=app.meshes.cube2;
var pointsBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, pointsBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertArray, gl.STATIC_DRAW);
gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(0);
var textureBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, textureBuffer);
gl.bufferData(gl.ARRAY_BUFFER, texCoord, gl.STATIC_DRAW);
gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(1);
var normalBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
gl.bufferData(gl.ARRAY_BUFFER, normArray, gl.STATIC_DRAW);
gl.vertexAttribPointer(2, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(2);
var indices = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indices);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indicesArray, gl.STATIC_DRAW);
console.log(indices.size);
第二步:初始化缓冲区。
function drawFunc() {
rotateAngleX += 0.01;
rotateAngleY += 0.02;
mat4.fromXRotation(rotateXMatrix, rotateAngleX);
mat4.fromYRotation(rotateYMatrix, rotateAngleY);
mat4.multiply(modelMatrix, rotateXMatrix, rotateYMatrix);
gl.uniformMatrix4fv(modelMatrixLocation, false, modelMatrix);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawElements(gl.TRIANGLES, indicesArray.length, gl.UNSIGNED_SHORT, 0);
requestAnimationFrame(drawFunc);
}
requestAnimationFrame(drawFunc);
我在这里尝试绘制一个简单的立方体。
数组大小为:vertices:72 indices:36 texCoords:48 normals:72
考虑到顶点是 x、y、z 点的三元组,顶点缓冲区包含 24 个点(vertex[0]=x, vertex[1]=y, vertex[2]=z, ...),并且indices 数组不包含大于 23 的数字,所以我不明白错误发生在哪里。还有什么方法可以调试缓冲区?我尝试了 spector.js 但没有太大帮助,因为绘制调用因错误而无能为力。
好的,出于某种原因,我不得不在 bufferdata 函数中添加新类型的数组,如下所示。
var indices = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indices);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint32Array(indicesArray),gl.STATIC_DRAW);
其余缓冲区也是如此。
查看下面的完整示例:
"use strict";
var m = ThreeDMath;
function main() {
var cubeVertices = [-1, -1, -1,
1, -1, -1,
1, 1, -1, -1, 1, -1, -1, -1, 1,
1, -1, 1,
1, 1, 1, -1, 1, 1,
];
var indices = [
0, 1,
1, 2,
2, 3,
3, 0,
4, 5,
5, 6,
6, 7,
7, 4,
0, 4,
1, 5,
2, 6,
3, 7,
];
var canvas = document.getElementById("c");
var gl = canvas.getContext("webgl");
if (!gl) {
alert("no webgl");
return;
}
var program = webglUtils.createProgramFromScripts(
gl, ["2d-vertex-shader", "2d-fragment-shader"]);
gl.useProgram(program);
var positionLoc = gl.getAttribLocation(program, "a_position");
var worldViewProjectionLoc =
gl.getUniformLocation(program, "u_worldViewProjection");
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array(cubeVertices),
gl.STATIC_DRAW);
gl.enableVertexAttribArray(positionLoc);
gl.vertexAttribPointer(positionLoc, 3, gl.FLOAT, false, 0, 0);
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer);
gl.bufferData(
gl.ELEMENT_ARRAY_BUFFER,
new Uint16Array(indices),
gl.STATIC_DRAW);
function render(clock) {
clock *= 0.001;
var scale = 4;
webglUtils.resizeCanvasToDisplaySize(gl.canvas, window.devicePixelRatio);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.clear(gl.COLOR_BUFFER_BIT);
var fieldOfView = Math.PI * 0.25;
var aspect = canvas.clientWidth / canvas.clientHeight;
var projection = m.perspective(fieldOfView, aspect, 0.0001, 500);
var radius = 5;
var eye = [
Math.sin(clock) * radius,
1,
Math.cos(clock) * radius,
];
var target = [0, 0, 0];
var up = [0, 1, 0];
var view = m.lookAt(eye, target, up);
var worldViewProjection = m.multiplyMatrix(view, projection);
gl.uniformMatrix4fv(worldViewProjectionLoc, false, worldViewProjection);
gl.drawElements(gl.LINES, indices.length, gl.UNSIGNED_SHORT, 0);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
main();
<script src="https://webglfundamentals.org/webgl/resources/webgl-utils.js"></script>
<script src="https://webglfundamentals.org/webgl/resources/webgl-lessons-helper.js"></script>
<script src="https://webglfundamentals.org/webgl/lessons/resources/3d-math.js"></script>
<!-- vertex shader -->
<script id="2d-vertex-shader" type="x-shader/x-vertex">
attribute vec4 a_position; uniform mat4 u_worldViewProjection; void main() { gl_Position = u_worldViewProjection * a_position; }
</script>
<!-- fragment shader -->
<script id="2d-fragment-shader" type="x-shader/x-fragment">
void main() { gl_FragColor = vec4(0,0,0,1); }
</script>
<canvas id="c"></canvas>