我对WebGL相当陌生,我正在制作一个动态地在玩家周围生成土地的3D游戏。所以,我试图在游戏中添加顶点。事情工作得很好,直到我开始添加此功能,每帧调用数百个gl.drawArrays()
,这使得它超级滞后。在做了一些研究之后,我发现一个更好的方法是制作一个包含所有顶点(每个形状由退化三角形分隔)的巨大数组,然后每帧调用一个gl.drawArray()
。动态WebGL在游戏循环中的绘制
这里是我的代码,在负载运行的部分:
function loadGraphics() {
// ground
// buffers
quadVertexPositionBuffer = gl.createBuffer();
vertices = [];
verticesItemCount = 0;
quadVertexColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, quadVertexColorBuffer);
var colors = [
0.0, 0.4, 0.0, 1.0,
0.0, 0.4, 0.0, 1.0,
0.0, 0.4, 0.0, 1.0,
0.0, 0.4, 0.0, 1.0,
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.DYNAMIC_DRAW);
quadVertexColorBuffer.itemSize = 4;
quadVertexColorBuffer.numItems = 4;
}
这里是每帧运行部分:
function drawGraphics() {
// draw code for graphics
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.clearColor(0.35, 0.4, 1.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
mat4.perspective(45, gl.viewportWidth/gl.viewportHeight, 0.1, 100.0, pMatrix);
mat4.identity(mvMatrix);
// perspective
var cameraX = camera.x, cameraY = camera.y, cameraZ = camera.z;
mat4.rotate(mvMatrix, rotMatrix[1], [1, 0, 0]);
mat4.rotate(mvMatrix, rotMatrix[0], [0, 1, 0]);
mat4.translate(mvMatrix, [-cameraX/33, -cameraY/33, -cameraZ/33]);
debug.add("{camera} x:"+camera.x+",y:"+camera.y+",z:"+camera.z+";");
debug.add("\n{mouse delta} x:"+mouse.x-mouse.prevX+",y:"+mouse.y-mouse.prevY+";");
debug.add("\n{rm}[0]:"+rotMatrix[0]+",[1]:"+rotMatrix[1]);
// ground
gl.bindBuffer(gl.ARRAY_BUFFER, quadVertexColorBuffer);
gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, quadVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
// land plots
vertices = [];
verticesItemCount = 0;
for (var i = 0; i < landPlots.length; i++) {
var oX = landPlots[i].x*3;
var oZ = landPlots[i].z*3;
var plotVertices = [
-1.5+oX, 0.0, 1.5+oZ, 1.0,
1.5+oX, 0.0, 1.5+oZ, 1.0,
-1.5+oX, 0.0, -1.5+oZ, 1.0,
1.5+oX, 0.0, -1.5+oZ, 1.0
];
pushDrawArray(plotVertices, 4);
for(var j = 1; j <= 2; j++) {
debug.add(" " + renderLandPlotIntersection(landPlots[i], j));
}
}
gl.bindBuffer(gl.ARRAY_BUFFER, quadVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 4, gl.FLOAT, false, 0, 0);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.DYNAMIC_DRAW);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, verticesItemCount);
}
function renderLandPlotIntersection(landPlot, side) {
var x = landPlot.x;
var z = landPlot.z;
var lvl = landPlot.level;
var olvl = null;
var plot;
switch (side) {
case 0: plot =getLandPlot(x-1, z ); if (plot !== null) olvl = plot.level/66; else return 0; break;
case 1: plot =getLandPlot(x, z+1); if (plot !== null) olvl = plot.level/66; else return 0; break;
case 2: plot =getLandPlot(x+1, z ); if (plot !== null) olvl = plot.level/66; else return 0; break;
case 3: plot =getLandPlot(x, z-1); if (plot !== null) olvl = plot.level/66; else return 0; break;
default: throw "Land plot intersection drawing: side out of range."; return -1;
}
var intersectionVertices = [
x*3, lvl, z*3,
x*3, lvl, z*3,
x*3, olvl, z*3,
x*3, olvl, z*3
];
pushDrawArray(intersectionVertices, 4);
return +1;
}
function pushDrawArray(array, itemCount) {
if (vertices.length > 0) {
// degenerate
vertices.push(vertices[vertices.length-3]);
vertices.push(vertices[vertices.length-2]);
vertices.push(vertices[vertices.length-1]);
vertices.push(array[0]);
vertices.push(array[1]);
vertices.push(array[2]);
verticesItemCount += 2 ;
}
gl.bufferSubData(gl.ARRAY_BUFFER, verticesItemCount*4, array);
verticesItemCount += itemCount;
}
我开始使用DYNAMIC_DRAW
,但我真的不知道如何使用它。 verticesItemCount
表示vertices
阵列中有多少个顶点。
gl.drawArrays()
返回此错误:
[.Offscreen-For-WebGL-060B7ED8]GL ERROR :GL_INVALID_OPERATION : glDrawArrays: attempt to access out of range vertices in attribute 1 localhost/:1 WebGL: too many errors, no more errors will be reported to the console for this context.
我怎样才能解决这个问题的代码不会导致错误?
这是什么问题? –
对不起。 'gl.drawArrays()''误码[.Offscreen-FOR-WebGL的-060B7ED8] GL ERROR:GL_INVALID_OPERATION:调用glDrawArrays:尝试访问超出范围的顶点在属性1 本地主机/:1的WebGL:太多错误,不再有错误将被报告给控制台用于这个上下文。 我只是想动态绘制一个指针。 – clabe45