#typescript #webgl
Вопрос:
Я часто получаю предупреждения о потере контекста и webglcontextlost
о событиях. Я хочу знать, почему это происходит так часто, хотя я не злоупотребляю графическим процессором. Я думаю, что в моем цикле рисования есть какая-то проблема с памятью.
Во-вторых webglcontextrestored
, никогда не стреляет, и я не могу восстановить контекст на данный момент.
Я настраиваю webgl2:
constructor(readonly $wrap: HTMLElement) {
this.$canvas = document.createElement('canvas')
this.$canvas.width = 320
this.$canvas.height = 180
$wrap.appendChild(this.$canvas)
let gl = this.$canvas.getContext('webgl2', { alpha: true, antialias: false });
if (gl !== null) {
this.gl = gl
}
this.$canvas.addEventListener('webglcontextlost', (event) => {
console.log('context lost')
event.preventDefault()
this.gl = undefined
})
this.$canvas.addEventListener('webglcontextrestored', () => {
console.log('restored')
if (gl !== null) {
this.gl = gl
}
})
}
Это мой код для рисования, называемый каждый requestAnimationFrame
:
flush = () => {
let { gl, attributeBuffer, indexBuffer } = this
if (!gl) {
return
}
let aIndex = 0
this.elements.forEach((element, i) => {
let {
vertexData,
indices } = element
let { texture, fsUv } = this.quads[i]
for (let k = 0; k < vertexData.length; k =2) {
attributeBuffer[aIndex ] = vertexData[k]
attributeBuffer[aIndex ] = vertexData[k 1]
attributeBuffer[aIndex ] = fsUv[k]
attributeBuffer[aIndex ] = fsUv[k 1]
}
for (let k = 0; k < indices.length; k ) {
indexBuffer[i * indices.length k] = i * 4 indices[k]
}
})
gl.viewport(0, 0, 320, 180)
gl.clearColor(0, 0, 0, 1)
gl.clear(gl.COLOR_BUFFER_BIT)
gl.enable(gl.BLEND)
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA)
let vao = gl.createVertexArray()
gl.bindVertexArray(vao)
let gl_abuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, gl_abuffer)
let gl_ibuffer = gl.createBuffer()
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl_ibuffer)
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indexBuffer, gl.STATIC_DRAW)
let program = generateProgram(gl, vSource, fSource)
gl.useProgram(program.program)
gl.uniformMatrix3fv(program.uniformData['projectionMatrix'].location, false, this.projectionMatrix.array_t)
gl.uniform1i(program.uniformData['uSampler'].location, 0)
gl.bindBuffer(gl.ARRAY_BUFFER, gl_abuffer)
gl.bufferData(gl.ARRAY_BUFFER, attributeBuffer, gl.STATIC_DRAW)
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl_ibuffer)
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indexBuffer, gl.STATIC_DRAW)
let stride = 2 * 4 2 * 4
let a1loc = program.attributeData['aVertexPosition'].location
gl.enableVertexAttribArray(a1loc)
gl.vertexAttribPointer(a1loc, 2, gl.FLOAT, false, stride, 0)
let a2loc = program.attributeData['aTextureCoord'].location
gl.enableVertexAttribArray(a2loc)
gl.vertexAttribPointer(a2loc, 2, gl.FLOAT, false, stride, 2*4)
let glTexture = gl.createTexture()
gl.bindTexture(gl.TEXTURE_2D, glTexture)
gl.texImage2D(gl.TEXTURE_2D, 0,
gl.RGBA,
1,
1,
0,
gl.RGBA,
gl.UNSIGNED_BYTE,
new Uint8Array([0, 0, 255, 255]))
let texture = this.quads[0].texture
gl.bindTexture(gl.TEXTURE_2D, glTexture)
gl.texImage2D(gl.TEXTURE_2D, 0,
gl.RGBA, texture.width, texture.height, 0, gl.RGBA, gl.UNSIGNED_BYTE,
texture)
//gl.generateMipmap(gl.TEXTURE_2D)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
gl.drawElements(gl.TRIANGLES, indexBuffer.length, gl.UNSIGNED_SHORT, 0)
this.elements = []
}
Может быть, я вызываю generateProgram, который компилирует и связывает программы gl каждый раз, когда в этом проблема?
Комментарии:
1. В значительной степени весь ваш цикл рендеринга должен выполняться только один раз: создание и заполнение буферов, создание программы шейдеров, загрузка данных текстур, настройка состояний сэмплера текстур, скорее всего, из-за этого.
Ответ №1:
Как отмечалось в комментарии, большую часть настройки можно выполнить только один раз. Я реорганизовал код так, что проблема решена.
glOnce = (texture: HTMLImageElement) => {
let { gl, attributeBuffer, indexBuffer } = this
if (!gl) { return }
gl.viewport(0, 0, 320, 180)
gl.clearColor(0, 0, 0, 1)
gl.enable(gl.BLEND)
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA)
let vao = gl.createVertexArray()
gl.bindVertexArray(vao)
this.glAttributeBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, this.glAttributeBuffer)
this.glIndexBuffer = gl.createBuffer()
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.glIndexBuffer)
let program = generateProgram(gl, vSource, fSource)
gl.useProgram(program.program)
gl.uniformMatrix3fv(program.uniformData['projectionMatrix'].location, false, this.projectionMatrix.array_t)
gl.uniform1i(program.uniformData['uSampler'].location, 0)
let stride = 2 * 4 2 * 4
let a1loc = program.attributeData['aVertexPosition'].location
gl.enableVertexAttribArray(a1loc)
gl.vertexAttribPointer(a1loc, 2, gl.FLOAT, false, stride, 0)
let a2loc = program.attributeData['aTextureCoord'].location
gl.enableVertexAttribArray(a2loc)
gl.vertexAttribPointer(a2loc, 2, gl.FLOAT, false, stride, 2*4)
let glTexture = gl.createTexture()
gl.bindTexture(gl.TEXTURE_2D, glTexture)
gl.texImage2D(gl.TEXTURE_2D, 0,
gl.RGBA,
1,
1,
0,
gl.RGBA,
gl.UNSIGNED_BYTE,
new Uint8Array([0, 0, 255, 255]))
gl.bindTexture(gl.TEXTURE_2D, glTexture)
gl.texImage2D(gl.TEXTURE_2D, 0,
gl.RGBA, texture.width, texture.height, 0, gl.RGBA, gl.UNSIGNED_BYTE,
texture)
//gl.generateMipmap(gl.TEXTURE_2D)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
}
flush = () => {
let { gl, attributeBuffer, indexBuffer } = this
if (!gl) {
return
}
let aIndex = 0
this.elements.forEach((element, i) => {
let {
vertexData,
indices } = element
let { texture, fsUv } = this.quads[i]
for (let k = 0; k < vertexData.length; k =2) {
attributeBuffer[aIndex ] = vertexData[k]
attributeBuffer[aIndex ] = vertexData[k 1]
attributeBuffer[aIndex ] = fsUv[k]
attributeBuffer[aIndex ] = fsUv[k 1]
}
for (let k = 0; k < indices.length; k ) {
indexBuffer[i * indices.length k] = i * 4 indices[k]
}
})
gl.clear(gl.COLOR_BUFFER_BIT)
gl.bindBuffer(gl.ARRAY_BUFFER, this.glAttributeBuffer)
gl.bufferData(gl.ARRAY_BUFFER, attributeBuffer, gl.STATIC_DRAW)
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.glIndexBuffer)
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indexBuffer, gl.STATIC_DRAW)
gl.drawElements(gl.TRIANGLES, indexBuffer.length, gl.UNSIGNED_SHORT, 0)
this.elements = []
}