2016-10-08 67 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

我知道我做了什麼。我使頂點位置數組比我的頂點顏色數組長,所以它試圖訪問一些界限以外的東西。修復方法是保持頂點顏色數組的長度與頂點位置數組的長度相同。