Opengl 在缓冲区中绘画。阿尔法·香奈儿的问题

Opengl 在缓冲区中绘画。阿尔法·香奈儿的问题,opengl,buffer,blending,fbo,Opengl,Buffer,Blending,Fbo,我试图实现一些类似于绘画工具的东西,但遇到了画笔的阿尔法通道问题。我的画笔是带有透明背景的.PNG纹理。我在RGBA缓冲区中绘制。我的代码: initFBO(...) ... glEnable(GL_BLEND); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClearColor(1.0f, 0.0f, 0.0f, 1.0f); glBindFramebuffer(GL_FRAMEBUFFER, FBO); glBlendFun

我试图实现一些类似于绘画工具的东西,但遇到了画笔的阿尔法通道问题。我的画笔是带有透明背景的.PNG纹理。我在RGBA缓冲区中绘制。我的代码:

initFBO(...)
...

glEnable(GL_BLEND);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);

glBindFramebuffer(GL_FRAMEBUFFER, FBO);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

drawBrush(...)

glBindFramebuffer(GL_FRAMEBUFFER, 0); 

drawFBO(...)
它的作品,但如果我停止我的画笔,阿尔法通道从画笔将积累在缓冲区,以取代颜色从

我不太熟悉Opengl中的混合,而且混合参数也有问题。我的问题是混合还是别的

更新:

initFBO(GLuint &framebuff, GLuint &text)
{
    glGenFramebuffers(1, &framebuff);
    glBindFramebuffer(GL_FRAMEBUFFER, framebuff);
    glGenTextures(1, &text);

    glBindTexture(GL_TEXTURE_2D, text);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, screenWidth, screenHeight, 0, GL_RGB, GL_FLOAT, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, text, 0);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

drawBrush(glm::vec2 mousePosition, GLuint texture, Shader shader)
{
    glm::mat4 model;
    model = glm::translate(model, glm::vec3(mousePosition, 1.0));

    GLfloat brushVertices[] =
    {
        -0.1f, 0.1f, 0.0f, 0.0f, 1.0f,
        -0.1f,-0.1f, 0.0f, 0.0f, 0.0f,
         0.1f, 0.1f, 0.0f, 1.0f, 1.0f,
         0.1f,-0.1f, 0.0f, 1.0f, 0.0f
    };

    glGenVertexArrays(1, &brushVAO);
    glGenBuffers(1, &brushVBO);
    glBindVertexArray(brushVAO);
    glBindBuffer(GL_ARRAY_BUFFER, brushVBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(brushVertices), &brushVertices, GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
    glBindVertexArray(0);

    shader.set();
    glUniform1i(glGetUniformLocation(shader.Program, "texture"), 0);
    glUniformMatrix4fv(glGetUniformLocation(shader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture);

    glBindVertexArray(brushVAO);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    glBindVertexArray(0);
}

drawFBO(GLuint texture, Shader shader)
{
    GLfloat screenquadVertices[] =
    {
    -1.0f, 1.0f, 0.0f,  0.0f, 1.0f,
    -1.0f, -1.0f,0.0f,  0.0f, 0.0f,
    1.0f, 1.0f, 0.0f,  1.0f, 1.0f,
    1.0f, -1.0f,  0.0f,  1.0f, 0.0f
    };

    glGenVertexArrays(1, &screenquadVAO);
    glGenBuffers(1, &screenquadVBO);
    glBindVertexArray(screenquadVAO);
    glBindBuffer(GL_ARRAY_BUFFER, screenquadVBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(screenquadVertices), &screenquadVertices, GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
    glBindVertexArray(0);

    shader.set();
    glUniform1i(glGetUniformLocation(shader.Program, "texture"), 0);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture);

    glBindVertexArray(screenquadVAO);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    glBindVertexArray(0);
}
更新2

嗯。我尝试了你的两个建议,但结果相似,不能解释我的问题。看看:

1)
glBlendFunc(GL_ONE,GL_ONE减去SRC_ALPHA)和两个预乘.PNG纹理-带黑色和白色

2)
glBlendFuncSeparate(GL_SRC_ALPHA,GL_ONE减去SRC_ALPHA,GL_ONE,GL_ONE减去SRC_ALPHA)和直线alpha纹理


当混合到具有直alpha通道的纹理中时,正确的混合方程涉及到alpha值的除法,并且此类方程不能在OpenGL(和GPU)随
glBlendFunc
glBlendFuncSeparate
提供的线性公式中表示

相反,应该使用预乘alpha。原则上,你可以通过打电话来做到这一点

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
一次,并确保所有输入和输出都是预乘alpha

然而,标准PNG是直阿尔法(尽管存在具有预乘阿尔法的非标准PNG…可能不是您的情况)。要处理此问题,您可以在加载PNG时对其进行预乘,或者在
drawBrush
中使用以下方法:

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

这将获得直接的alpha着色器输出,并将其混合到预乘alpha帧缓冲区中。因此,在将该帧缓冲区渲染到屏幕时,请记住对预乘alpha(第一个)使用
glBlendFunc

是否禁用深度测试?是。如果我启用它,一切都不会改变。你发布的图片是什么的图片?什么是“绘制FBO”代码,“绘制笔刷”代码,以及您是如何设置FBO的?好的,我会更新它。想象一下当我试图在opengl窗口中绘制时得到的图像。当我停止画笔时,它开始慢慢“燃烧”我以前画的东西,如果你理解我的话。@OpenGLNoob:不,我不知道。你不清理缓冲区吗?很难从代码中分辨出来,因为它只是不连贯的片段。请以后再发。至于现在,我怀疑问题在于渲染到的透明纹理不是预乘alpha。谢谢你的回答!我会记住它对渲染结果的影响。我尝试了您的解决方案以及其他与和w/o预乘(look-update)的组合,但在我看来问题似乎出在其他地方。我的帧缓冲区在游戏循环中不仅累积颜色,而且累积alpha值,这会影响FBO。当我停止画笔时,它开始像纸上的墨水一样流血。现在我试着想办法解决这个问题,但我做不到((@OpenGLNoob:你知道你没有发布与鼠标相关的代码,因此我们无法帮助你完成这一部分吗?请学习发布a。是的,你是对的。我的错误是我没有通过鼠标移动控制更新我的FBO,并将绘画管道直接放入游戏循环中。FBO每帧都在积累alpha,这是我pr的原因问题,谢谢!