与FBO(NVidia)分开模板

时间:2016-11-30 11:08:46

标签: opengl nvidia fbo stencil-buffer

我试图让FBO具有单独的深度和模板缓冲区。 我知道NVidia GPU历史上只支持打包深度/模板。 但是我偶然发现了ARB_texture_stencil8扩展,并想知道如何对FBO使用它。 此代码在glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_STENCIL_ATTACHMENT_EXT,GL_TEXTURE_2D,fboStencilTexture,0)上给出gl错误1159:

    static GLuint fboId, rboDepth, rboStencil, TEXTURE_WIDTH, TEXTURE_HEIGHT;
    if (!fboColorTexture) {
        fboDepthTexture = fboId = rboDepth = rboStencil = TEXTURE_WIDTH = TEXTURE_HEIGHT = 0; // vid restart?
        glGenTextures(1, &fboColorTexture);
        glBindTexture(GL_TEXTURE_2D, fboColorTexture);
        qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    }
    if (!fboDepthTexture) {
        glGenTextures(1, &fboDepthTexture);
        glBindTexture(GL_TEXTURE_2D, fboDepthTexture);
        qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    }   
    if (!fboStencilTexture) {
        glGenTextures(1, &fboStencilTexture);
        glBindTexture(GL_TEXTURE_2D, fboStencilTexture);
        qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    }
    GLuint curWidth = r_virtualResolution.GetFloat() * glConfig.vidWidth, curHeight = r_virtualResolution.GetFloat() * glConfig.vidHeight;
    if (curWidth != TEXTURE_WIDTH || curHeight != TEXTURE_HEIGHT) {
        TEXTURE_WIDTH = curWidth;
        TEXTURE_HEIGHT = curHeight;
        glBindTexture(GL_TEXTURE_2D, fboColorTexture);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5_A1, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL); //NULL means reserve texture memory, but texels are undefined
        glBindTexture(GL_TEXTURE_2D, fboDepthTexture);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
        glBindTexture(GL_TEXTURE_2D, fboStencilTexture);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_STENCIL_INDEX8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_STENCIL_INDEX, GL_FLOAT, 0);
    }
    //-------------------------
    if (!fboId) {
        // create a framebuffer object, you need to delete them when program exits.
        glGenFramebuffersEXT(1, &fboId);
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId);
        // attach a texture to FBO color attachement point
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fboColorTexture, 0);
        // attach a renderbuffer to depth attachment point
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, fboDepthTexture, 0);
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, fboStencilTexture, 0);
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    }
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId);

1 个答案:

答案 0 :(得分:1)

ARB_texture_stencil8的目的是允许您将仅模板格式用作纹理。也就是说,在着色器中读取它们。

这并不意味着您可以分离模板和深度缓冲区。 stencil-8纹理背后的想法是,您可以通过复制深度/模板纹理的模板部分来生成数据,或者您将完全渲染而不使用深度缓冲区。

因此,您无法使用此扩展来保证您可以渲染分离深度和模板图像。这仍然取决于硬件。

此外,如果您要使用ARB_texture_stencil8等新功能,则不应将它们与旧的EXT_framebuffer_object API相结合。因此,请停止使用glFramebufferTexture2DEXT并开始使用glFramebufferTexture