Framebuffer 和 Renderbuffer 的 Webgl 绑定
Posted
技术标签:
【中文标题】Framebuffer 和 Renderbuffer 的 Webgl 绑定【英文标题】:Webgl binding of a Framebuffer and Renderbuffer 【发布时间】:2015-04-11 13:42:20 【问题描述】:我想从帧缓冲区中获取像素颜色。 我尝试绑定帧缓冲区,但收到消息“此附件组合不起作用”。
RenderingEngine.prototype.getPixel = function(x, y, drawObject)
var framebuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
framebuffer.width = this.canvas.width;
framebuffer.height = this.canvas.height;
var depthBuffer = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer);
// allocate renderbuffer
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, this.canvas.width, this.canvas.height);
// attach renderebuffer
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer);
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE)
alert("this combination of attachments does not work");
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
drawObject.draw();
var pixel = new Uint8Array(4);
gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
console.log(pixel);
return pixel;
更新 #1
我像这样更改了我的代码。但我总是得到黑色([0, 0, 0, 0])。你能说现在是什么问题吗?
RenderingEngine.prototype.getPixel = function(x, y, drawObject)
var framebuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
framebuffer.width = this.canvas.width;
framebuffer.height = this.canvas.height;
var depthBuffer = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer);
// allocate renderbuffer
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, framebuffer.width, framebuffer.height);
// attach renderebuffer
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer);
var colorBuffer = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer);
// allocate colorBuffer
gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, framebuffer.width, framebuffer.height);
// attach colorbuffer
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer);
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE)
alert("this combination of attachments does not work");
renderingEngine.draw(drawObject);
var pixel = new Uint8Array(4);
gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
console.log(pixel);
return pixel;
更新 #2
我的错误是绘画。此代码有效。但是有一些奇怪的东西。渲染的场景被水平镜像。你知道为什么吗?
RenderingEngine.prototype.getPixel = function(x, y, drawObject)
var framebuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
framebuffer.width = this.canvas.width;
framebuffer.height = this.canvas.height;
var depthBuffer = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer);
// allocate renderbuffer
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, framebuffer.width, framebuffer.height);
// attach renderebuffer
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer);
var colorBuffer = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer);
// allocate colorBuffer
gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, framebuffer.width, framebuffer.height);
// attach colorbuffer
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer);
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE)
alert("this combination of attachments does not work");
renderingEngine.draw(drawObject);
var pixel = new Uint8Array(4);
gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
console.log(pixel);
return pixel;
【问题讨论】:
您只附加了一个深度渲染缓冲区。您还需要附加颜色渲染缓冲区或颜色纹理。我认为您不能只渲染到深度渲染缓冲区。 我这样修改了我的代码: 我将您的更新复制到您上面的问题。您能否删除下面的2个答案?将您的问题的更新发布为 SO 的答案并不合适。否则,至于为什么翻转,我假设您的意思是垂直而不是水平?请记住,WebGL 中的 0,0 是左下角。 【参考方案1】:这对我有用
function log(msg)
var pre = document.createElement("pre");
pre.appendChild(document.createTextNode(msg));
document.body.appendChild(pre);
var gl = document.getElementById("c").getContext("webgl");
var framebuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
var depthBuffer = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer);
// allocate renderbuffer
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, gl.canvas.width, gl.canvas.height);
// attach renderebuffer
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer);
var colorBuffer = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer);
// allocate colorBuffer
gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, gl.canvas.width, gl.canvas.height);
// attach colorbuffer
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer);
if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE)
alert("this combination of attachments does not work");
gl.clearColor(0.5, 0.25, 1, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
var pixel = new Uint8Array(4);
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
log(pixel[0] + "," + pixel[1] + "," + pixel[2] + "," + pixel[3]);
canvas border: 1px solid black;
<body>
<canvas id="c"></canvas>
</body>
虽然如果是我,我会为颜色附件附加纹理而不是渲染缓冲区。
【讨论】:
为什么是 136 ?第一种颜色是 0.5,或者 255 * 0.5 不是 136 ahh ok RGBA 是 4 位浮点数(整数中的 4 位 = 0..15)。 136 = (8/15) * 255 ; 68 = (4/15) * 255 !【参考方案2】:引自WebGLFundamentals: 重要的是要注意 WebGL 只承诺 3 种附件组合有效。根据the spec,唯一保证的附件组合是:
COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture
COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_ATTACHMENT = DEPTH_COMPONENT16 renderbuffer
COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE texture + DEPTH_STENCIL_ATTACHMENT = DEPTH_STENCIL renderbuffer
【讨论】:
以上是关于Framebuffer 和 Renderbuffer 的 Webgl 绑定的主要内容,如果未能解决你的问题,请参考以下文章
OpenGL中Framebuffer和Renderbuffer的概念和区别是啥?
如何在Android上实现FrameBuffer和Overlay的blend