Я пишу приложение гистограммы в webgl, используя библиотеку twgl.js.
Я успешно реализовал это. Но он очень легко вылетает из браузера.
Я добавил планкр здесь @ https://plnkr.co/edit/hK9YXyT0Cj9BEUowYiKVSubH?p=info.
В основном часть рендеринга находится в renderer.js.
Пожалуйста, найдите jpeg с вашего локального компьютера и контролируйте память Chrome GPU, используя SHIFT + ESC после включения памяти GPU.
После того, как изображение загружено, оно вычислит гистограмму для этой области на изображении и само увеличит / уменьшит масштаб, и память увеличивается с каждым увеличением.
Проблема в том, что он вылетает из GPU только с одним изображением.
Чтобы быстрее решить проблему, я добавил setInterval, который вызывается каждые 100 мсек, чтобы перерисовать изображение и вычислить гистограмму.
Код:
`
var prepareHistogram = function (img) {
//arrays.texcoord = [0.2, 0.2, 1.0, 0.2, 0.2, 1.0, 1.0, 1.0];
gl.arrays = arrays;
gl.arrays.position.data = [-1, -1, 1, -1, -1, 1, 1, 1];
gl.arrays.position.numComponents = 2;
gl.arrays.texcoord.numComponents = 2;
//gl.arrays.texcoord = [0.2, 0.2, 1.0, 0.2, 0.2, 1.0, 1.0, 1.0];
quadBufferInfo = twgl.createBufferInfoFromArrays(gl, gl.arrays);
//quadBufferInfo = twgl.primitives.createXYQuadBufferInfo(gl);
quadBufferInfo.indices = null;
var newFbi = twgl.createFramebufferInfo(gl);
twgl.bindFramebufferInfo(gl, newFbi);
gl.useProgram(newProgramInfo.program);
twgl.setBuffersAndAttributes(gl, newProgramInfo, quadBufferInfo);
twgl.setUniforms(newProgramInfo, {
u_texture: texture,
u_resolution: [img.width, img.height]
});
twgl.drawBufferInfo(gl, gl.TRIANGLES, quadBufferInfo);
/* twgl.bindFramebufferInfo(gl, null);
twgl.drawBufferInfo(gl, gl.TRIANGLES, quadBufferInfo);
return; */
numIds = img.width * img.height;
pixelIds = dummyPixelIds.subarray(0, numIds);
var pixelIdBufferInfo = twgl.createBufferInfoFromArrays(gl, {
pixelId: {
size: 2,
data: pixelIds,
numComponents : 1
}
});
// make a 256x1 RGBA floating point texture and attach to a framebuffer
var sumFbi = twgl.createFramebufferInfo(gl, [{
type: gl.FLOAT,
min: gl.NEAREST,
mag: gl.NEAREST,
wrap: gl.CLAMP_TO_EDGE,
}, ], 256, 1);
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) !== gl.FRAMEBUFFER_COMPLETE) {
alert("can't render to floating point texture");
}
// Render sum of each color
// we're going to render a gl.POINT for each pixel in the source image
// That point will be positioned based on the color of the source image
// we're just going to render vec4(1,1,1,1). This blend function will
// mean each time we render to a specific point that point will get
// incremented by 1.
gl.blendFunc(gl.ONE, gl.ONE);
gl.enable(gl.BLEND);
gl.useProgram(histProgramInfo.program);
twgl.setBuffersAndAttributes(gl, histProgramInfo, pixelIdBufferInfo);
twgl.bindFramebufferInfo(gl, sumFbi);
// render each channel separately since we can only position each POINT
// for one channel at a time.
gl.colorMask(true, true, true, false);
twgl.setUniforms(histProgramInfo, {
u_texture: newFbi.attachments[0],
u_resolution: [img.width, img.height]
});
twgl.drawBufferInfo(gl, gl.POINTS, pixelIdBufferInfo);
gl.colorMask(true, true, true, true);
gl.blendFunc(gl.ONE, gl.ZERO);
gl.disable(gl.BLEND);
// render-compute min
// We're rendering are 256x1 pixel sum texture to a single 1x1 pixel texture
// make a 229x1 pixel RGBA, FLOAT texture attached to a framebuffer
var maxFbi = twgl.createFramebufferInfo(gl, [{
type: gl.FLOAT,
min: gl.NEAREST,
mag: gl.NEAREST,
wrap: gl.CLAMP_TO_EDGE,
}, ], 229, 1);
twgl.bindFramebufferInfo(gl, maxFbi);
gl.useProgram(maxProgramInfo.program);
twgl.setBuffersAndAttributes(gl, maxProgramInfo, quadBufferInfo);
twgl.setUniforms(maxProgramInfo, {
u_texture: sumFbi.attachments[0],
pixelCount : pixelCount
});
twgl.drawBufferInfo(gl, gl.TRIANGLES, quadBufferInfo);
// render histogram.
//twgl.bindFramebufferInfo(gl, null);
var newFbi2 = twgl.createFramebufferInfo(gl);
twgl.bindFramebufferInfo(gl, newFbi2);
gl.useProgram(showProgramInfo.program);
twgl.setBuffersAndAttributes(gl, showProgramInfo, quadBufferInfo);
twgl.setUniforms(showProgramInfo, {
u_resolution: [img.width, img.height],
u_res: [img.width, img.height],
u_maxTexture: maxFbi.attachments[0],
inputImage : newFbi.attachments[0]
});
twgl.drawBufferInfo(gl, gl.TRIANGLES, quadBufferInfo);
twgl.bindFramebufferInfo(gl, null);
gl.useProgram(showProgramInfo2.program);
twgl.setUniforms(showProgramInfo2, {
u_texture: newFbi2.attachments[0],
u_resolution: [gl.canvas.width, gl.canvas.height]
});
//arrays.texcoord.numComponents = 2;
//arrays.position.data = [ar.x1, ar.y1, ar.x2, ar.y1, ar.x1, ar.y2, ar.x2, ar.y2];
//gl.arrays = arrays;
//quadBufferInfo = twgl.primitives.createXYQuadBufferInfo(gl);
//gl.arrays = arrays;
gl.arrays.position.data = [ar.x1, ar.y1, ar.x2, ar.y1, ar.x1, ar.y2, ar.x2, ar.y2];
//gl.arrays.texcoord = [0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0];
/* gl.arrays.texcoord = [0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0];
gl.arrays.texcoord.numComponents = 2;
gl.arrays.position.numComponents = 2; */
quadBufferInfo = twgl.createBufferInfoFromArrays(gl, gl.arrays);
quadBufferInfo.indices = null;
twgl.setBuffersAndAttributes(gl, showProgramInfo2, quadBufferInfo);
twgl.drawBufferInfo(gl, gl.TRIANGLES, quadBufferInfo);
}
`