获取使用 gl.texImage2D 绘制的纹理的“红色”像素值
Posted
技术标签:
【中文标题】获取使用 gl.texImage2D 绘制的纹理的“红色”像素值【英文标题】:Getting the 'red' pixel value of the texture drawn using gl.texImage2D 【发布时间】:2017-12-11 21:37:14 【问题描述】:我正在使用纹理将 Float32array 发送到我的片段着色器(这里的目标是使用纹理将数据发送到着色器,在着色器中处理此数据,然后将其发送回 javascript)。由于我的数据实际上不是图像,因此我决定通过“gl.R32F”发送它,并且在使用 gl.readPixels 处理后尝试读取这些数据。这是我的代码,例如,尚未处理数据,首先我试图找到一种将数据发送回javascript的方法;
var canvas = document.getElementById('webgl-canvas');
var bbb = 4096*4096;
var widthcanvas = Math.sqrt(bbb)
canvas.width = widthcanvas;
canvas.height = widthcanvas;
var gl = initGL(canvas);
var boxVertices = new Float32Array([
-1.0, 1.0, 0, 0,
-1.0, -1.0, 0, 1,
1.0, 1.0, 1, 0,
1.0, -1.0, 1, 1
]);
var boxVertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, boxVertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, boxVertices, gl.STATIC_DRAW);
var boxTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, boxTexture);
gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
var data= new Float32Array(bbb);
for(var i = 0; i < bbb; i++)
data[i] = -i;
gl.texImage2D(gl.TEXTURE_2D, 0, gl.R32F, widthcanvas, widthcanvas, 0, gl.RED, gl.FLOAT, data);
gl.bindTexture(gl.TEXTURE_2D, null);
var a_position = gl.getAttribLocation(shaderProgram, 'a_position');
var a_textCoords = gl.getAttribLocation(shaderProgram, 'a_textCoords');
gl.vertexAttribPointer (a_position, 2, gl.FLOAT, gl.FALSE, 4 * Float32Array.BYTES_PER_ELEMENT, 0);
gl.vertexAttribPointer(a_textCoords, 2, gl.FLOAT, gl.FALSE, 4 * Float32Array.BYTES_PER_ELEMENT, 2 * Float32Array.BYTES_PER_ELEMENT);
gl.enableVertexAttribArray(a_position);
gl.clearColor(0.75, 0.85, 0.8, 1.0);
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.bindTexture(gl.TEXTURE_2D, boxTexture);
gl.activeTexture(gl.TEXTURE0);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
var framebuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, boxTexture, 0);
var pixels = new Float32Array(gl.drawingBufferWidth * gl.drawingBufferHeight);
gl.readPixels(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight, gl.RED, gl.FLOAT, pixels);
console.log(pixels);
gl.deleteFramebuffer(framebuffer);
当我尝试将数据写入纹理时,我没有收到任何错误(虽然我不知道数据是否在没有任何更改的情况下发送,因为我无法读回它)。但是,当我尝试使用 gl.readPixels 读取它时,出现以下错误,
ERROR :GL_INVALID_FRAMEBUFFER_OPERATION : glReadPixels: framebuffer incomplete
所以,我的问题是这样的;
-
如果我使用纹理发送数据的方式是正确的,并且我的数据在这个过程中没有改变,我该如何将它发送回 JavaScript?
如果我发送数据的方式不对,我该如何实现我的目标?
如果您能帮我解决这个问题,我将不胜感激。谢谢。
P.s:数据并不总是完美的正方形。
【问题讨论】:
这是一个WebGL 2
的问题,对吧?
是的,这是一个 WebGL 2 问题
R32F 需要扩展才能变得可渲染,因此附加到 FBO。 khronos.org/registry/OpenGL/specs/es/3.0/es_spec_3.0.pdf 第 3.8.3.1 节,了解有关可用的详细信息。这个扩展khronos.org/registry/webgl/extensions/EXT_color_buffer_float需要使用R32F
感谢您的评论,我会阅读pdf,看看我能做什么。
【参考方案1】:
pleup 是对的。 R32F 需要扩展才能变得可渲染。当我将以下内容添加到我的代码中时,一切正常,
var ext = gl.getExtension('EXT_color_buffer_float');
再次感谢您的回答。
【讨论】:
你应该检查扩展名不是null
。例如,大多数手机或平板电脑上不存在该扩展程序。以上是关于获取使用 gl.texImage2D 绘制的纹理的“红色”像素值的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 texSubImage2D 在 webgl 中显示精灵?
WebGL - 发送数组缓冲区 VS 将图像/画布/位图从 CPU 发送到 GPU