【问题标题】:Images and mask in OpenGL ES 2.0OpenGL ES 2.0 中的图像和蒙版
【发布时间】:2013-09-04 04:56:00
【问题描述】:

我正在学习 OpenGL ES 2.0,我想创建一个应用程序以更好地了解它的工作原理。 该应用程序有一组过滤器,用户可以将其应用于图像(我知道,没什么新东西:P)。

其中一个过滤器需要两张图像和一个蒙版,它将通过蒙版显示它们的两张图像混合在一起(这里的图像可以更好地解释我想要获得的内容)

目前我真的很困惑,我不知道从哪里开始创建这种效果。 我不明白我是否必须使用多个纹理和多个帧缓冲区,或者我只能使用单个着色器。

你有什么提示可以帮助我做这个项目吗?

编辑--------

我找到了这个解决方案,但是当我使用遮罩线而不是圆圈时,结果真的很“邋遢”,尤其是当线条旋转时。

precision highp float;

varying vec4 FragColor;
varying highp vec2 TexCoordOut;

uniform sampler2D textureA;
uniform sampler2D textureB;
uniform sampler2D mask;

void main(void){
    vec4 mask_color = texture2D(mask, TexCoordOut);

    if (mask_color.a > 0.0){
        gl_FragColor =  texture2D(textureA, TexCoordOut);
    }else {
        gl_FragColor =  texture2D(textureB, TexCoordOut);
    }
}

使用模板缓冲或混合可能更好吗?

【问题讨论】:

  • 顺便说一句,您不必使用 alpha (mask_color.a) 通道进行遮罩。您可以使用任何其他r,g,b 通道,这样您就可以通过使用不带 Alpha 通道的遮罩纹理来节省 GPU 内存。
  • @MatterGoal 或许你可以回答这个问题,stackoverflow.com/questions/24486729/…

标签: opengl-es-2.0 shader


【解决方案1】:

您可以在一行中应用掩码,而无需使用昂贵的if

gl_FragColor = step( 0.5, vMask.r ) * vColor_1 + ( 1.0 - step( 0.5, vMask.r ) ) * vColor_2;

或者,最好只在两种颜色之间进行插值:

gl_FragColor = mix( vColor_1, vColor_2, vMask.r );

在这种情况下,可以平滑蒙版(即使用高斯模糊)以减少锯齿。与单值阈值相比,这将产生非常好的结果。

【讨论】:

  • 我必须使用多通道来创建模糊蒙版吗?或者您建议使用相同的着色器创建模糊?
  • 您可以使用相同的着色器创建模糊,方法是执行多次(即 5 次)蒙版纹理获取并平均结果。然后使用这个平均值而不是vMask.r
  • 在这里您可以找到片段着色器中高斯模糊的实现:xissburg.com/faster-gaussian-blur-in-glsl
  • 不得不提醒:为什么人们会认为 ifmultiply 更昂贵
  • @PsychoDad 分支预测与乘法相比需要更多的 CPU 周期?这让我难以置信。有参考吗?
【解决方案2】:

不需要多个着色器或帧缓冲区,只需要多个纹理单元。只需使用全部由相同纹理坐标索引的 3 个纹理单元,并使用 Mask 纹理在其他两个纹理之间进行选择。片段着色器看起来像这样:

uniform sampler2D uTextureUnit_1;
uniform sampler2D uTextureUnit_2;
uniform sampler2D uTextureMask;
varying vec2 vTextureCoordinates;

void main()
{
    vec4 vColor_1 = texture2D(uTextureUnit_1, vTextureCoordinates);
    vec4 vColor_2 = texture2D(uTextureUnit_2, vTextureCoordinates);
    vec4 vMask = texture2D(uTextureMask, vTextureCoordinates);

    if (vMask.r > 0.5)
        gl_FragColor = vColor_1;
    else
        gl_FragColor = vColor_2;
}

您可以看到,使用第三个纹理单元仅对红色通道进行二进制测试效率不高,因此最好将蒙版编码到纹理 1 或 2 的 alpha 通道中,但这应该得到你开始了。

【讨论】:

  • 您是否建议将任何特定设置应用于场景以获得完美的结果?对于一些“非线性”面具,我得到了一个糟糕的最终结果。
  • OpenGL 特别不提供像素完美的结果,但您可以通过增加纹理的尺寸来提高质量。对于 glTexParameteri(),将 GL_LINEAR 用于 MAG_FILTER 和 MIN_FILTER。 MIP_MAP 只有在缩小时才有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-06
  • 2012-04-05
  • 2012-02-12
  • 2012-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多