为啥 GL_RASTERIZER_DISCARD 不能让我写入模板缓冲区?

Posted

技术标签:

【中文标题】为啥 GL_RASTERIZER_DISCARD 不能让我写入模板缓冲区?【英文标题】:Why GL_RASTERIZER_DISCARD does not enable me to write to stencil buffer?为什么 GL_RASTERIZER_DISCARD 不能让我写入模板缓冲区? 【发布时间】:2020-05-14 12:56:32 【问题描述】:

我想在 3 遍中使用模板缓冲区绘制轮廓。

    正常绘图过程 轮廓蒙版生成通道 轮廓图传递

第二遍不需要片段着色器工作,因为它只写入模板缓冲区,所以我使用glEnable(GL_RASTERIZER_DISCARD); 来完全防止接触片段着色器。

问题是没有生成掩码(这是我的想法,也许是别的东西),因此轮廓四边形片段不会被丢弃。它被绘制但在我想要概述的四边形的顶部。如果这有意义的话。

int main()

    //create window, gl context etc. etc...

    Shader colorShader("colorShader.glsl");
    Shader maskShader("maskShader.glsl");

    //Creates geometry for quad, also creates vertex array, vertex buffer and adds data glBufferData.
    //this code is tested and works, so it is not neccessery to show what it does internaly.
    Quad sceneQuad(colorShader);
    Quad maskQuad(maskShader);
    Quad outlineQuad(colorShader);

    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);
    glEnable(GL_STENCIL_TEST);
    glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
    glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);

    bool quit = false;

    while(!quit) 
        glClearColor(0.25f, 0.25f, 0.25f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glDisable(GL_RASTERIZER_DISCARD);
        glStencilMask(0x00);

        //binds everything, and call glDraw*, its parameter is model matrix and u_r uniform
        //it is also tested and works fine
        sceneQuad->Draw(Scale(1.0f), 1.0f);

        glEnable(GL_RASTERIZER_DISCARD);

        glStencilFunc(GL_ALWAYS, 1, 0xFF);
        glStencilMask(0xFF);
        maskQuad->Draw(); // it does not need matrix or u_r, because it uses different shader

        glDisable(GL_RASTERIZER_DISCARD);

        glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
        glStencilMask(0x00);
        glDisable(GL_DEPTH_TEST);

        oulineQuad->Draw(Scale(1.1), 0.0f); //a bit scaled 
    

颜色着色器:

#version 460 core

layout (location = 0) in vec2 a_position;

uniform mat4 u_model;

void main()

    gl_Position = u_model * vec4(a_position, 0.0f, 1.0f);


//-------------------------------------------------------------------

#version 460 core

layout (location = 0) out vec4 f_color;

uniform float u_r;

void main()
        
    f_color = vec4(u_r, 0.0f, 1.0f, 1.0f);

遮罩着色器,只是顶点程序:

#version 460 core

layout (location = 0) in vec2 a_position;

void main()

    gl_Position = vec4(a_position, 0.0f, 1.0f);

我期望的是绘制紫色四边形, 然后再次绘制它但没有片段着色器,只绘制到模板缓冲区 然后在所有内容之上绘制蓝色四边形,但丢弃模板缓冲区中由蒙版绘制的像素。

它的作用是绘制蓝色四边形而不丢弃蒙版像素。

如何解决?

【问题讨论】:

【参考方案1】:

来自"What actually does GL_RASTERIZE_DISCARD":

启用后,在光栅化阶段之前,但在可选的变换反馈阶段之后(参见第 13.2 节),原语将被丢弃

鉴于您想绘制到模板缓冲区,您仍然需要光栅化,而不是颜色缓冲区。 为此,您可以使用

glDrawBuffer(GL_NONE)

glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE)

请参阅this post 进行比较,但我认为无论哪种方式都适合您的应用程序。

【讨论】:

哦,好吧,我看过“GL_RASTERIZE_DISCARD到底做了什么”,但看起来我没看懂。现在可以了。谢谢

以上是关于为啥 GL_RASTERIZER_DISCARD 不能让我写入模板缓冲区?的主要内容,如果未能解决你的问题,请参考以下文章

为啥使用 glTranslatef?为啥不直接更改渲染坐标?

为啥 DataGridView 上的 DoubleBuffered 属性默认为 false,为啥它受到保护?

为啥需要softmax函数?为啥不简单归一化?

为啥 g++ 需要 libstdc++.a?为啥不是默认值?

为啥或为啥不在 C++ 中使用 memset? [关闭]

为啥临时变量需要更改数组元素以及为啥需要在最后取消设置?