2016-10-08 23 views
1

我对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.

我怎样才能解决这个问题的代码不会导致错误?

+0

这是什么问题? –

+0

对不起。 'gl.drawArrays()''误码[.Offscreen-FOR-WebGL的-060B7ED8] GL ERROR:GL_INVALID_OPERATION:调用glDrawArrays:尝试访问超出范围的顶点在属性1 本地主机/:1的WebGL:太多错误,不再有错误将被报告给控制台用于这个上下文。 我只是想动态绘制一个指针。 – clabe45

回答

1

我知道我做了什么。我使顶点位置数组比我的顶点颜色数组长,所以它试图访问一些界限以外的东西。修复方法是保持顶点颜色数组的长度与顶点位置数组的长度相同。