OpenGL photoshop叠加混合模式

时间:2013-10-18 21:22:35

标签: ios opengl-es opengl-es-2.0 shader

我正在尝试实现一个粒子系统(使用OpenGL 2.0 ES),其中每个粒子都由具有简单纹理的四边形组成

the red pixels are transparent

红色像素是透明的。每个粒子的随机α值为50%至100%

现在棘手的部分是我喜欢每个粒子都有一个像Photoshop一样的混合模式" overlay"我尝试了很多与glBlendFunc()的不同组合,但没有运气。

我不明白我是如何在片段着色器中实现这一点的,因为我需要有关片段当前颜色的信息。这样我就可以根据当前和纹理颜色计算出一种新颜色。

我还想过使用一个帧缓冲对象,但我想我需要将我的frame-buffer-object重新渲染成一个纹理,因为每个粒子因为每个粒子每个帧,因为我需要计算的片段颜色粒子相互重叠。

我找到了数学'和其他信息重新划分覆盖计算,但我很难确定我可以去实现这个方向。

我希望能有这样的效果:

overlapping particles and how they blend together

3 个答案:

答案 0 :(得分:10)

可以获取有关iOS设备上帧缓冲区中当前片段颜色的信息。自iOS 6.0开始,可通过EXT_shader_framebuffer_fetch扩展程序提供可编程混合(在该版本支持的每个设备上)。只需在片段着色器中声明该扩展名(通过将指令#extension GL_EXT_shader_framebuffer_fetch : require置于顶部),您将获得gl_LastFragData[0]中的当前片段数据。

然后,是的,您可以在片段着色器中使用它来实现您喜欢的任何混合模式,包括所有Photoshop风格的混合模式。以下是差异混合的示例:

// compute srcColor earlier in shader or get from varying
gl_FragColor = abs(srcColor - gl_LastFragData[0]);

您也可以将此扩展名用于不混合两种颜色的效果。例如,您可以将整个场景转换为灰度 - 正常渲染,然后使用着色器绘制四边形,该着色器读取最后一个片段数据并对其进行处理:

mediump float luminance = dot(gl_LastFragData[0], vec4(0.30,0.59,0.11,0.0));
gl_FragColor = vec4(luminance, luminance, luminance, 1.0);

你可以在没有帧缓冲区提取的情况下在GLSL中进行各种混合模式,但这需要渲染到多个纹理,然后使用混合纹理的着色器绘制四边形。与帧缓冲提取相比,这是一个额外的绘制调用,并且在共享和平铺内存之间来回切换许多像素 - 这种方法要快得多。

最重要的是,没有说帧缓冲数据必须是彩色的......如果你在OpenGL ES 3.0中使用多个渲染目标,你可以从一个读取数据并使用它来计算你写入的数据另一个。 (请注意,扩展在GLSL 3.0中的工作方式不同。上面的示例是GLSL 1.0,您仍然可以在ES3上下文中使用。请参阅spec了解如何在#version 300 es中使用framebuffer fetch着色器。)

答案 1 :(得分:1)

我怀疑你想要这个配置: 资料来源:GL_SRC_ALPHA 目的地:GL_ONE。 公式:GL_ADD

如果没有,如果您可以解释您希望获得的过滤器的数学计算可能会有所帮助。

答案 2 :(得分:1)

[编辑:以下答案适用于OpenGL和OpenGL ES几乎无处不在除了 iOS 6.0之后。有关EXT_shader_framebuffer_fetch的信息,请参阅rickster的答案,在ES 3.0中,它允许将目标缓冲区标记为inout,并在ES 2.0下引入相应的内置变量。在撰写本文时,iOS 6.0已经超过一年了,所以我的无知没有特别的借口;我决定不删除答案,因为它可能对那些根据其opengl-es,opengl-es-2.0和着色器标签找到这个问题的人有效。]

简要确认:

  • OpenGL混合模式在硬件中实现,并在片段着色器结束后发生;
  • 您无法以编程方式指定混合模式;
  • 你是对的,唯一的解决方法是打乒乓,交换目标缓冲区和每个几何体的源纹理(所以你从第一个到第二个,然后从第二个到第一个,等等) )。

根据维基百科和您提供的链接,定义了Photoshop的叠加模式,以便背景值a和前景色bf(a, b)的输出像素为{{ 1}}如果2ab,则a < 0.5

因此,混合模式会根据颜色缓冲区中已有的颜色更改每个像素。并且每个连续绘制的决定取决于前一个颜色缓冲区留下的状态。

所以你无法避免把它写成乒乓球。

如果没有那么昂贵的缓冲区交换,你最接近的就是索林建议,尝试使用纯添加剂混合来制作类似的东西。您可以通过添加最终的乒乓球阶段来稍微榨汁,将所有值从其线性比例转换为您看到的S曲线,如果您将相同的颜色叠加到自身上。这应该会给你多个圆圈重叠的大变化。