如何将模板从一个帧缓冲区传递到另一个帧缓冲区



我正在努力理解为什么在下面的代码中,当我直接渲染到屏幕时,模板测试按预期工作,而当我试图使用framebuffers时却没有。我没有问题使用这些帧缓冲区对纹理进行多通道后处理,所以我怀疑我在深度上做错了什么。模板缓冲区。

首先初始化上下文:

        gl = canvas.getContext("webgl",{stencil:true});
然后

function initFBO()
{
for (var i = 0; i < shaderPrograms.length; i++) 
{
    var texture = createTexture(imgWidth,imgHeight);
    textures.push(texture);
    var fbo = gl.createFramebuffer();
    framebuffers.push(fbo);
    gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
    var renderbuffer = gl.createRenderbuffer();
    gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
    gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, imgWidth, imgHeight);
    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
    gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, renderbuffer);
}
}

function drawScene() 
{
gl.enable(gl.STENCIL_TEST);
gl.enable(gl.DEPTH_TEST);
if(!useFBO)
{
    computeProgFBO(9,null,imgHeight,imgHeight,textureId,null,null,false);
    computeProgFBO(8,null,imgHeight,imgHeight,textureId,null,null,false);
}else{
    computeProgFBO(9,framebuffers[0],imgHeight,imgHeight,textureId,null,null,false);
    computeProgFBO(8,null,imgHeight,imgHeight,textures[0],null,null,false);
}
// Restore the original matrix
mvPopMatrix();
gl.disable(gl.STENCIL_TEST);
gl.disable(gl.DEPTH_TEST);
}
function computeProgFBO(progId,fboId,w,h,textureId0,textureId1,textureId2,flip)
{
    currentProgram=shaderPrograms[progId];
    gl.useProgram(currentProgram);
    if(progId==9)
    {
        transform(w,h,0.0);
        gl.stencilMask(1);
        gl.stencilFunc(gl.ALWAYS,1,0);
        gl.stencilOp(gl.KEEP,gl.KEEP,gl.REPLACE);
        gl.colorMask(true, true, true, true);
        gl.depthMask(false);
        setMatrixUniformsView();
    }else{
        gl.colorMask(true, true, true, true);
        gl.depthMask(true);
        gl.stencilFunc(gl.EQUAL,0,1);
        gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP);
        setMatrixUniforms();
    }
    setMyUniforms(progId,flip);
    setMyTexture(textureId0, textureId1,textureId2);
    gl.activeTexture(gl.TEXTURE1);
    gl.bindFramebuffer(gl.FRAMEBUFFER, fboId);
//the below is commented out for now as i'm only testing the stencil buffer for now        
//  gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, textures[progId], 0);


    gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
    gl.bindFramebuffer(gl.FRAMEBUFFER, null);
    gl.bindTexture(gl.TEXTURE_2D , null);
}

我认为展示不同的制服和纹理功能没有任何意义,但请务必让我知道。顺便说一句,progId 9画了一个小的绿色正方形,progId 8在它上面画了一个更大的红色正方形。所以,我希望看到一个绿色的正方形被一些红色的边缘包围,因为它目前显示当我直接渲染到屏幕。

****继第一个答案之后,我修改了下面的*****

if(!useFBO)
{
    computeProgFBO(9,null,imgHeight,imgHeight,textureId,null,null,false,null);
    computeProgFBO(8,null,imgHeight,imgHeight,textureId,null,null,false,null);
    computeProgFBO(6,null,imgHeight,imgHeight,textureId,null,null,false,null);
}else{
    computeProgFBO(9,framebuffers[0],imgHeight,imgHeight,textureId,null,null,false,null);
    computeProgFBO(8,framebuffers[1],imgHeight,imgHeight,textures[0],null,null,false,renderbuffers[0]);
    computeProgFBO(6,null,imgHeight,imgHeight,textures[1],null,null,false,null);
}

,我将函数参数更改为

computeProgFBO(progId,fboId,w,h,textureId0,textureId1,textureId2,flip,render)

和后面的注释

//the below is commented out for now as i'm only testing the stencil buffer for now        
//  gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, textures[progId], 0);

我添加了

if(render!=null)
    {
        gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, render);
    }

结果稍微好一点,但还没有完全达到我的预期,即:我得到了一个大的红色正方形,而不是里面的小绿色正方形,我得到了一个白色的正方形。我觉得这是一件微不足道的事情,但目前还不能真正解决。直接渲染到屏幕上仍然可以正常工作。

*****对于其他人的评论,我添加了******

我想我明白了这个问题,并找到了一个解决方法[不是很优雅]。基本上,第一次通过使用stencil写入framebuffers[0]的纹理[0],第二次通过使用framebuffers[0]的renderbuffers[0]写入framebuffers[1]的纹理[1],但不写入纹理[0]。因此,我最终只是用一个小的白色(而不是绿色)正方形包围着一个红色正方形。因为,我不能blit,我已经意识到,我可以只画两次在第一次通过按如下:

....
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
if(progId==9) 
    {
        gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffers[1]);
        gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
    }

这个可以工作,但是看起来很丑!还有别的办法吗?

当涉及到渲染最终纹理到屏幕,似乎我不需要做太多,即:我只发送颜色缓冲区到屏幕(而不是模板& &;(深度缓冲)和所有的最终纹理得到显示的预期。

另外,请注意,我的片段着色器只做以下

shader9: gl_FragColor = vec4(0.0,1.0,0.0,1.0);

shader8: gl_FragColor = vec4(1.0,vec2(0.0),1.0);

shader6: gl_FragColor = texture2D(u_Texture0,vTextureCoord);

你不能在webgl中复制缓冲区的内容,但是你可以通过在同一个renderbuffer上调用gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, renderbuffer);来在许多FBOS之间共享深度模板缓冲区。

如果你想在启用模板测试的情况下渲染到默认的framebuffer,你必须首先渲染到带有所需的模板渲染缓冲区附件的FBO。然后使用FBO的颜色纹理绘制到默认的framebuffer

相关内容

  • 没有找到相关文章

最新更新