使用 FBO (NVidia) 分离模板

Separate stencil with FBO (NVidia)

我正在尝试使用具有独立深度和模板缓冲区的 FBO。 我知道 NVidia GPU 历史上只支持 packed depth/stencil。 然而,我偶然发现了 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);

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

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

所以你不能使用这个扩展来保证你可以渲染到分离的深度和模板图像。这仍然取决于硬件。

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