我具有WebGL / OpenGL的基本知识,但没有gl.bufferSubData的知识。
所以我的目标是像这样在问题中创建一个SpriteBatch类First Question
由于我认为问题与gl.bufferSubData有关,因此我将仅发布与渲染调用相关的代码段。另外,我包括未知变量,但会在注释中显示其值。

因此,在构建SpriteBatch时,将调用这段代码(在内部构造函数中)

// this.capacity = 750, VERTEX_OFFSET = 18
this.vertexBuffer = this.gl.createBuffer();
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexBuffer);
this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(this.capacity * VERTEX_OFFSET), this.gl.STREAM_DRAW);
this.gl.enableVertexAttribArray(this.program.vertexLocation);
this.gl.vertexAttribPointer(this.program.vertexLocation, 3, gl.FLOAT, false, 0, 0);
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, null);


当我将一个精灵添加到SpriteBatch时,这段代码称为

//s == new Sprite()
// UNIT_QUAD_COORDS = new Float32Array([-0.5, -0.5, 1.0, 0.5, -0.5, 1.0, -0.5, 0.5, 1.0, -0.5, 0.5, 1.0, 0.5, -0.5, 1, 0.5, 0.5, 1.0]);
this.numberUsedVertices += VERTEX_OFFSET; //  VERTEX_OFFSET=18
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
let data = UNIT_QUAD_COORDS; // new Float32Array([-0.5, -0.5, 1.0, 0.5, -0.5, 1.0, -0.5, 0.5, 1.0, -0.5, 0.5, 1.0, 0.5, -0.5, 1, 0.5, 0.5, 1.0]);

for (let k = 0; k < VERTEX_OFFSET; k += 3) {
  let x = s.size * UNIT_QUAD_COORDS[k] * Math.cos(s.rotation) - s.size * UNIT_QUAD_COORDS[k + 1] * Math.sin(s.rotation);
  let y = s.size * UNIT_QUAD_COORDS[k] * Math.sin(s.rotation) + s.size * UNIT_QUAD_COORDS[k + 1] * Math.cos(s.rotation);
  x += s.x;
  y += s.y;
  data[k] = x;
  data[k + 1] = y;
}
// s.index = 0, VERTEX_OFFSET=18
gl.bufferSubData(gl.ARRAY_BUFFER, VERTEX_OFFSET * s.index, data)


最后,当我绘制SpriteBatch时:

gl.useProgram(this.program.program);
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
gl.vertexAttribPointer(this.program.vertexLocation, 3, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLES, 0, this.numberUsedVertices); // this.numberUsedVertices =18


请注意,使用gl.vertexAttribPointer(this.program.vertexLocation, 3, gl.FLOAT, false, 0, 0);时,我只会看到白屏。但是当我使用gl.vertexAttribPointer(this.program.vertexLocation, 2, gl.FLOAT, false, 0, 0);时,会看到许多不同的三角形。
另请注意,当我正常绘制时,这意味着没有gl.bufferSubData和SpriteBatch时,将显示四边形。

所以我的假设是我对gl.bufferSubData的用法是错误的。

最佳答案

gl.bufferSubData的偏移量以字节为单位,因此您可能需要

gl.bufferSubData(gl.ARRAY_BUFFER, VERTEX_OFFSET * s.index * 4, data);


或者如果您想学究

const offset = VERTEX_OFFSET * s.index * Float32Array.BYTES_PER_ELEMENT;
gl.bufferSubData(gl.ARRAY_BUFFER, offset, data);




const gl = document.querySelector("canvas").getContext("webgl");

const vs = `
attribute vec2 position;
void main() {
  gl_Position = vec4(position, 0, 1);
  gl_PointSize = 10.;
}
`
const fs = `
precision mediump float;
void main() {
  gl_FragColor = vec4(1, 0, 0, 1);
}
`

const program = twgl.createProgram(gl, [vs, fs]);

const positionLoc = gl.getAttribLocation(program, "position");

const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);

const numVerts = 100;
const vertSize = 2 * 4;  // 2 floats, 4 bytes each
gl.bufferData(gl.ARRAY_BUFFER, numVerts * vertSize, gl.STREAM_DRAW);

const vert = new Float32Array(2);

function render() {
  // replace one vertex
  const ndx = Math.random() * numVerts | 0;
  vert[0] = Math.random() * 2 - 1;
  vert[1] = Math.random() * 2 - 1;
  const offset = ndx * vertSize;
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  gl.bufferSubData(gl.ARRAY_BUFFER, offset, vert);

  gl.enableVertexAttribArray(positionLoc);
  gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0);

  gl.useProgram(program);

  gl.drawArrays(gl.POINTS, 0, numVerts);

  requestAnimationFrame(render);
}
requestAnimationFrame(render);

canvas { border: 1px solid black }

<canvas></canvas>
<script src="https://twgljs.org/dist/3.x/twgl.min.js"></script>

关于javascript - WebGL Quad未与gl.bufferSubData一起显示,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45122067/

10-12 14:37