我具有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
的使用是错误的。
答案 0 :(得分:1)
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>