使用子缓冲区webgl绘制缓冲区

时间:2016-10-24 06:14:28

标签: javascript webgl

如何在webgl中绘制带缓冲区的缓冲区? 例如,我有一个不同的点来创建一条线,但包含我不想连接的部分。

///Example code
    var lines = [
        [0, 0, 0, 1, 1, 1],
        [2, 2, 2, 3, 3, 3],
        [5, 5, 5, 7, 7, 7]
    ];
    var colores = [
        [10, 43, 100, 1, ],
        [0, 100, 0, 1],
        [100, 100, 0, 1]
    ]
    for (var i = 0; i < lines.length; i++) {
        lineVertexPositionBuffer[i] = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, lineVertexPositionBuffer[i]);
        lineVertexPositionBuffer[i].itemSize = 3;
        lineVertexPositionBuffer[i].numItems = line[i].length / 3;

        colorVertexBuffer[i] = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, colorVertexBuffer[i]);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colores[i]), gl.DYNAMIC_DRAW);
        colorVertexBuffer[i].itemSize = 4;
        colorVertexBuffer[i].numItems = colores[i].length / 4;

    }

    function DrawScene() {
        for (var i = 0; i < lineVertexPositionBuffer.length; i++) {
            gl.bindBuffer(gl.ARRAY_BUFFER, colorVertexBuffer[i]);
            gl.vertexAttribPointer(currentProgram.textureCoordAttribute, colorVertexBuffer[i].itemSize, gl.FLOAT, false, 0, 0);
            gl.bindBuffer(gl.ARRAY_BUFFER, null);

            gl.bindBuffer(gl.ARRAY_BUFFER, lineVertexPositionBuffer[i]);
            gl.vertexAttribPointer(currentProgram.vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
            gl.drawArrays(gl.LINE_STRIP, 0, lineVertexPositionBuffer[i].numItems);
            gl.bindBuffer(gl.ARRAY_BUFFER, null);
        }
    }

2 个答案:

答案 0 :(得分:0)

您可以使用gl.drawElements并提供索引列表,告诉GL实际使用哪些顶点。要允许通过单个调用绘制多个段,您可以使用gl.LINES。如果你有点p0..p6,其中0,1,2和4,5连接你需要索引为0,1,1,2,4,5。基本上两个索引来自gl告诉gl连接哪个顶点线。您甚至可以按顺序执行索引,如0,5,4,3,5,3。

要将顶点和颜色数据放到相同的缓冲区,您可以将它们交错或将它们放在彼此之后,如

/* interleaved. Padding isn't mandator but it keeps math simpler
   and GPUs often prefer cache aligned data. */
[x0, y0, z0, pad0, r0, g0, b0, a0,
x1, y1, z1, pad1, r1, g1, b1, a1,...]
gl.vertexAttribPointer(vertexLocation, 3, gl.FLOAT, false, 4*4*2, 0);
gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 4*4*2, 4*4);

/* n positions followed by n colors */
[x0, y0, z0, pad0,
x1, y1, z1, pad1,
...
r0, g0, b0, a0,
r1, g1, b1, a1,...] /* to WebGLBuffer in ARRAY_BUFFER_BINDING */
gl.vertexAttribPointer(vertexLocation, 3, gl.FLOAT, false, 4*4, 0);
gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 4*4, 4*4*n);

/* Index buffer to draw lines between vertices 0->1,1->3, 1->4 and 7->9 with gl.LINES */
[0, 1, 1, 3, 1, 4, 7, 9] /* to WebGLBuffer in ELEMENT_ARRAY_BUFFER_BINDING */

/* gl.drawArrays can't duplicate same drawing
   because vertices are referenced out of order. drawElements 
   also allows using a vertex for multiple lines. */
gl.drawElements(gl.LINES, 4*2, GL_UNSIGNED_BYTE, 0);

/* Alternative with only inorder but skiped vertices that can be duplicated with DrawArrays.
   Connections are 0->1, 1->2, 4->5 and 6->7*/
[0, 1, 1, 2, 4, 5, 6, 7] /* to WebGLBuffer in ELEMENT_ARRAY_BUFFER_BINDING */
gl.drawElements(GL.LINES, 4*2, GL_UNSIGNED_BYTE, 0);

/* Same rendering with multiple drawArrays calls */
gl.DrawArrays(gl.LINE_STRIP, 0, 3) /* Draw strip from 0 to 3 */
gl.DrawArrays(gl.LINES, 4, 2) /* Draw line between 4 and 5 */
gl.DrawArrays(gl.LINES, 6, 2) /* Draw line between 6 and 7 */

这有助于您找到答案吗?

答案 1 :(得分:0)

目前尚不清楚你要做什么。如果您的线条是动态的,只需将它们放入缓冲区并绘制,然后将新线条放入缓冲区并绘制,冲洗并重复。

var gl = document.querySelector("canvas").getContext("webgl", {
  preserveDrawingBuffer: true, 
});

var program = twgl.createProgramFromScripts(gl, ["vs", "fs"]);
var positionLoc = gl.getAttribLocation(program, "position");
var colorLoc = gl.getUniformLocation(program, "u_color");

var buffer = gl.createBuffer();

function putRandomLinesInBuffer(buf, numLines) {
  var points = new Float32Array(numLines * 4);
  for (var i = 0; i < numLines; ++i) {
    points[i * 4 + 0] = Math.random() * 2 - 1;
    points[i * 4 + 1] = Math.random() * 2 - 1;
    points[i * 4 + 2] = Math.random() * 2 - 1;
    points[i * 4 + 3] = Math.random() * 2 - 1;
  }
  gl.bindBuffer(gl.ARRAY_BUFFER, buf);
  gl.bufferData(gl.ARRAY_BUFFER, points, gl.DYNAMIC_DRAW);
}

function render() {
  var numLines = 5 + Math.random() * 10 | 0;
  putRandomLinesInBuffer(buffer, numLines);
  
  gl.useProgram(program);
  
  gl.enableVertexAttribArray(positionLoc);
  gl.bindBuffer(gl._ARRAY_BUFFER, buffer);
  gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0);
  
  gl.uniform4f(colorLoc, Math.random(), Math.random(), Math.random(), 1);
  
  gl.drawArrays(gl.LINES, 0, numLines * 2);
  requestAnimationFrame(render);
}
requestAnimationFrame(render);
<script src="https://twgljs.org/dist/2.x/twgl.min.js"></script>
<canvas></canvas>
<script id="vs" type="foo">
attribute vec4 position;
void main() {
  gl_Position = position;
}
</script>
<script id="fs" type="foo">
precision mediump float;
uniform vec4 u_color;
void main() {
  gl_FragColor = u_color;
}
</script>

如果您不想在每次分配最大尺寸时更换整个缓冲区并使用gl.bufferSubData,尽管根据我的经验gl.bufferData在大多数情况下比gl.bufferSubData快。

此外,如果您还没有结帐http://webglfundamentals.org