c++ - 柔软、透明的笔画纹理没有像我预期的那样混合

标签 c++ opengl 2d alphablending compositing

我正在尝试在我的 GL 4.5 应用程序中实现软刷。我已经实现了 100% 的硬刷,但软刷功能低于标准。我尝试实现的这种绘画模式在 Krita 中称为“水洗”绘画,是 GIMP 中的普通模式。

例如:在 Photoshop 中,我有一个硬度低且不透明度为 10% 的圆刷,按住鼠标并拖动光标,我得到一个均匀的笔触,纹理构建为10% 的不透明度,除了它淡出的边缘。如果我再次单击,由于添加剂混合 (?),它会增加 10% 的白色。

在我使用软笔刷纹理的应用程序中,由于纹理的不透明度逐渐降低,我总是会在鼠标移动时出现条纹。在混合当前笔划和 BG 纹理后,我尝试了各种混合模式并限制不透明度,它们或多或少看起来如下所示:

http://i.imgur.com/bZWDhoF.jpg

pPaintStroke_washF 全屏四边形着色器

#version 450 core
#extension GL_ARB_bindless_texture : require

in Vert
{
    vec2 uv;
} v;

layout(bindless_sampler, location = 0) uniform sampler2D blended_64; // blended bg + stroke
layout(location = 0) out vec4 Ci;

uniform vec4 brushRGBA = vec4(1.f, 1.f, 1.f, .001f);

void main()
{
    vec4 blended = texture(blended_64, v.uv);

    if (blended.a == 0.f)
        Ci = vec4(0.f);

    else
    {
        Ci.rgb = brushRGBA.rgb;
        Ci.a = clamp(blended.a, 0.f, brushRGBA.a);
        // Ci.a = clamp(blended.a, blended.a, brushRGBA.a);
    }
}

申请

glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

for (int i = 0; i < Bresenham.size(); ++i)
{
    /*
        //bind brushTempN.fbo1
        //render Bresenham[i] into it
    */

    glBindFramebuffer(GL_FRAMEBUFFER, brushTempN.fbo1);
    glViewport(0, 0, brushTempN.width, brushTempN.height);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(0.f, 0.f, 0.f, 0.f);

    myWin.myGLWidgetSh->glUseProgram2("pPaintStroke_unwashed");

    myWin.paintStroke->s->val_3 = glm::vec3((float)Bresenham[i].size / 100);
    myWin.paintStroke->t->val_3 = glm::vec3(Bresenham[i].coord, 0.f);
    myWin.paintStroke->mvpGet(myWin.allGL[GLidx]);
    myWin.paintStroke->render(myWin.allGL[GLidx]);

    /*
        //bind brushTempN.fbo2
        //render bg - starts as 0 (brushBGN.tex1)
        //render curr stroke (brushTempN.tex1)
        //this blends them
    */

    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glBindFramebuffer(GL_FRAMEBUFFER, brushTempN.fbo2);
    glViewport(0, 0, brushTempN.width, brushTempN.height);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(0.f, 0.f, 0.f, 0.f);

    myWin.myGLWidgetSh->glUseProgram2("pPaintStroke_washBlend");

    washBlendPhase = 0; myWin.myFSQ->render(myWin.allGL[GLidx]); //render BG

    washBlendPhase = 1; myWin.myFSQ->render(myWin.allGL[GLidx]); //render the curr stroke (brushTempN.tex1)

    /*
        //bind brushN.fbo1
        //read brushTempN.tex2_64
        //clamp the blended alpha with Ci.a = clamp(in.a, 0.f, brushRGBA.a)
    */

    glBindFramebuffer(GL_FRAMEBUFFER, brushN.fbo1);
    glViewport(0, 0, brushN.width, brushN.height);

    myWin.myGLWidgetSh->glUseProgram2("pPaintStroke_wash");
    myWin.myFSQ->render(myWin.allGL[GLidx]);

    /*
        //bind brushBGN.fbo1
        //copy the above brushN.tex1 into it
    */

    glBindFramebuffer(GL_FRAMEBUFFER, brushBGN.fbo1);
    glViewport(0, 0, brushBGN.width, brushBGN.height);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(0.f, 0.f, 0.f, 0.f);

    myWin.myGLWidgetSh->glUseProgram2("pPaintStroke_washBlend");

    washBlendPhase = 2; myWin.myFSQ->render(myWin.allGL[GLidx]); //render new BG
}

最佳答案

您也应该使用添加剂混合。

glBlendFunc(GL_SRC_ALPHA, GL_ONE);

关于c++ - 柔软、透明的笔画纹理没有像我预期的那样混合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33738442/

相关文章:

java - LWJGL 在纹理上绘制矩形

python - 模拟机器人运动的最佳 3D 库

java - 具有输入值的二维 boolean 数组

android - 在 Android canvas 中绘制 2D 曲线?

javascript - 如何在 JavaScript 中使用 X 和 Y 坐标移动对象

c++ - 为什么在使用迭代器时添加到 vector 不起作用?

c++ - 如何让程序确定最大的用户输入

c++ - SFML 2.1 RenderWindow 链接错误

c++ - 检查十六进制前缀后将字符串转换为 int 的更简洁方法?

opengl - 用于遮挡剔除的分层 Z 缓冲