使用 twgl.js 来简化东西,但由于某种原因我收到此警告:
[.WebGL-000031BC01680600] GL_INVALID_OPERATION: Must have element array buffer bound.
屏幕上什么也没有出现。然而,使用 twgl.js 创建者的实例化示例效果非常好。目标是在屏幕上画出圆圈,每个圆圈都有自己的位置和大小。我不太使用 webgl,而且之前也没有做过实例,所以我不确定我哪里出错了
我也在用包裹
文件结构相当简单:
index.html
index.cjs
src/
| renderer.cjs
渲染器.cjs:
const twgl = require("twgl.js")
const VERT_SHADER = `precision mediump float;
attribute vec2 points;
attribute vec2 position;
attribute float size;
uniform vec2 resolution;
void main() {
vec2 transform = vec2((points * size + position) / resolution);
vec2 clipSpace = transform * vec2(2.0, -2.0) - vec2(1.0, 1.0);
gl_Position = vec4(clipSpace, 1.0, 1.0);
}`
const FRAG_SHADER = `precision mediump float;
void main() {
gl_FragColor = vec4(0.19, 0.43, 0.69, 1.0);
}`
module.exports = class {
arrays = {
points: {
numComponents: 2,
data: [],
},
position: {
numComponents: 2,
data: [],
divisor: 1,
},
size: {
numComponents: 1,
data: [],
divisor: 1,
}
}
constructor(canvas) {
this.gl = canvas.getContext("webgl")
twgl.addExtensionsToContext(this.gl)
this.programInfo = twgl.createProgramInfo(this.gl, [VERT_SHADER, FRAG_SHADER])
}
setCircleSides(sides) {
this.sides = sides
const theta = 2 * Math.PI / sides
let data = []
// adding the vertices of the triangles in a circle
for (let i = 0; i < sides; ++i) {
data.push(
0, 0,
Math.cos(i * theta), Math.sin(i * theta),
Math.cos((i + 1) * theta), Math.sin((i + 1) * theta),
)
}
this.arrays.points.data = data
}
addCircle(x, y, size) {
this.arrays.position.data.push(x, y)
this.arrays.size.data.push(size)
}
updateBuffers() {
this.bufferInfo = twgl.createBufferInfoFromArrays(this.gl, this.arrays)
this.vertexArrayInfo = twgl.createVertexArrayInfo(this.gl, this.programInfo, this.bufferInfo)
}
render() {
this.gl.canvas.width = innerWidth
this.gl.canvas.height = innerHeight
twgl.resizeCanvasToDisplaySize(this.gl.canvas)
this.gl.viewport(0, 0, innerWidth, innerHeight)
this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT)
const uniforms = {
resolution: [innerWidth, innerHeight]
}
this.updateBuffers()
this.gl.useProgram(this.programInfo.program)
twgl.setBuffersAndAttributes(this.gl, this.programInfo, this.vertexArrayInfo)
twgl.setUniforms(this.programInfo, uniforms)
this.gl.drawElementsInstanced(this.gl.TRIANGLES, this.vertexArrayInfo.numElements, this.gl.UNSIGNED_SHORT, 0, this.arrays.size.data.length)
}
}
index.cjs:
const Renderer = require("./src/renderer.cjs")
// using defer in the html, so it runs after elements are loaded
const canvas = document.querySelector("canvas")
function main() {
const renderer = new Renderer(canvas)
renderer.setCircleSides(8)
for (let i = 0; i < 100; ++i) {
renderer.addCircle(Math.random() * 200, Math.random() * 200, Math.random() * 10)
}
renderer.render()
}
main()
我尝试过的效果非常好的示例在这篇文章中:在 twgl.js 中使用实例扩展
您正在调用
drawElementsInstanced
,但您没有索引。致电drawArraysInstanced