首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OpenGL光铺加铺共混模式

OpenGL光铺加铺共混模式
EN

Stack Overflow用户
提问于 2013-10-18 21:22:34
回答 3查看 5.7K关注 0票数 5

我试图实现一个粒子系统(使用OpenGL 2.0 ES),其中每个粒子都是由一个具有简单纹理的四角体组成的。

红色像素是透明的。每个粒子的α值从50%到100%不等。

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

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

我也考虑过使用一个框架缓冲对象,但是我想我需要把我的帧缓冲对象重新渲染成一个纹理,因为每个粒子每个帧,因为我需要计算出粒子重叠时的片段颜色。

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

我希望能有这样的效果:

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-10-21 17:48:03

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

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

代码语言:javascript
复制
// compute srcColor earlier in shader or get from varying
gl_FragColor = abs(srcColor - gl_LastFragData[0]);

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

代码语言:javascript
复制
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中完成各种混合模式,而不需要framebuffer,但这需要呈现到多个纹理,然后用混合纹理的着色器绘制一个四边形。与framebuffer相比,这是一个额外的绘图调用,并且在共享内存和平铺内存之间来回切换许多像素--这种方法要快得多。

除此之外,没有人说帧缓冲数据必须是彩色的.如果在OpenGL es3.0中使用多个呈现目标,则可以从其中读取数据并使用它计算写入另一个对象的数据。(但请注意,在GLSL3.0中,扩展的工作方式不同。上面的例子是GLSL1.0,您仍然可以在ES3上下文中使用它。请参阅等级库,了解如何在#version 300 es着色器中使用framebuffer。)

票数 11
EN

Stack Overflow用户

发布于 2013-10-18 21:41:36

我怀疑您需要这样的配置:源: GL_SRC_ALPHA目的地: GL_ONE。方程: GL_ADD

如果不是,如果你能解释你希望得到的过滤器的数学,那可能会很有帮助。

票数 1
EN

Stack Overflow用户

发布于 2013-10-18 22:55:28

编辑:下面的答案适用于OpenGL和OpenGL ES,除了iOS之外,其他地方都是如此。有关EXT_shader_framebuffer_fetch的信息,请参阅rickster的答案,该信息允许将目标缓冲区标记为inout,并在ES2.0下引入相应的内置变量。在撰写本文时,iOS 6.0已经一年多了,所以我没有什么特别的理由来解释我的无知;我决定不删除这个答案,因为它可能对那些基于opengl、opengl 2.0和着色器标签找到这个问题的人有效。

简短地确认:

  • OpenGL混合模式在硬件上实现,并在碎片着色器结束后出现;
  • 无法以编程方式指定混合模式;
  • 你说得对,唯一的解决办法是乒乓球,交换目标缓冲区和每个几何图形的源纹理(所以你画的是从第一个到第二个,然后从第二个到第一个等等)。

根据维基百科和您提供的链接,Photoshop的覆盖模式被定义为来自背景值a和前景颜色bf(a, b)的输出像素为2ab,如果a < 0.51 - 2(1 - a)(1 - b)不同的话。

因此,混合模式改变每像素取决于颜色已经在颜色缓冲器。每一次连续抽签的决定都取决于先前留下的颜色缓冲器的状态。

所以你不可能不把它写成乒乓球。

在没有所有昂贵的缓冲交换的情况下,你能得到的最接近的可能是,正如索林所建议的那样,尝试使用纯加性的混合来生产类似的东西。你可以加入一个最后的乒乓球阶段,把所有的值从线性比例转换成S-曲线,这样你就可以看到,如果你把同样的颜色覆盖在自己身上,你就能看到它的效果。这应该会给你很大的变化,其中多个圆圈重叠。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19459255

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档