EDIT
混合画笔->图层->背景
好吧,发生的事情是glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
正在将画笔描边混合到画笔纹理中,但纹理中生成的 alpha 值是错误的。每个添加的片段都需要 1. 将其 alpha 添加到最终的 alpha 值 - 它必须精确地去除交互所需的光量,并且 2. 按余数缩放先前的 alpha - 先前的表面将光减少先前的值,但由于添加了一个新的表面,可以减少的光线更少。我不确定这是否有意义,但它导致了这个......
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
现在画笔纹理的颜色通道包含要与背景混合的总颜色(预先乘以 Alpha),而 Alpha 通道给出权重(或颜色遮盖背景的量)。由于颜色预先与 Alpha 相乘,因此默认的 RenderTexture 混合GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
与阿尔法缩放again从而使整体颜色变暗。现在,您需要使用以下函数将画笔纹理与背景混合,我认为该函数必须在 Cocos2D 中设置:
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
希望这是可能的。我没有过多考虑如何管理设置画笔纹理以与其混合的可能性GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
但它可能需要浮点纹理和/或额外的通道来划分/标准化阿尔法,这听起来很痛苦。
或者,在绘制之前将背景放入渲染纹理中,并将背景保留在那里,而不进行任何图层混合。
这对我有用:
glDisable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
fbo.bind();
glClear(GL_COLOR_BUFFER_BIT);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
drawTexture(brush1);
drawTexture(brush2);
fbo.unbind();
drawTexture(grassTex); //tex alpha is 1.0, so blending doesn't affect background
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
drawTexture(fbo.getColour(0)); //blend in the brush layer
画笔层不透明度
Using GL_ONE, GL_ONE_MINUS_SRC_ALPHA
导致库在图层混合中实现不透明度的问题,因为它假设颜色乘以 alpha。通过减少opacity
值,画笔层的 Alpha 在混合过程中按比例缩小。GL_ONE_MINUS_SRC_ALPHA
然后导致背景颜色的数量增加,但是GL_ONE
笔刷层的总和为 100%,并使图像过饱和。
我认为最简单的解决方案是找到一种方法来自行缩小全局图层不透明度的颜色并继续使用GL_ONE, GL_ONE_MINUS_SRC_ALPHA
.
- 实际使用
GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_ALPHA
如果图书馆支持它,这可能是一个答案,但显然不支持。
- 您可以使用固定管道渲染来缩放颜色:
glColor4f(opacity, opacity, opacity, opacity)
,但这将需要第二个渲染目标并手动进行混合,类似于上面的代码,您为背景绘制一次全屏四边形,然后为画笔层绘制一次。
- 如果您手动进行混合,那么使用片段着色器而不是使用片段着色器会更稳健
glColor
方法。如果您想要使用更复杂的混合函数,这将允许更大的控制,特别是在涉及 0 到 1 范围之外的除法和临时函数时:gl_FragColour = texture(brushTexture, coord) * layerOpacity;
END EDIT
标准的 alpha 混合函数是glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
,不完全是 GL“初始”/默认功能。
像在 glBlendFuncSeparate 中那样对 alpha 值求和将使 alpha 过度饱和,并且下面的颜色将被完全替换。饱和度混合可能会给出不错的结果:glBlendFunc(GL_SRC_ALPHA_SATURATE, GL_ONE) http://www.opengl.org/sdk/docs/man/xhtml/glBlendFunc.xml。也许也值得尝试glBlend方程分离 http://www.opengl.org/wiki/GLAPI/glBlendEquationSeparate和 MAX 混合(如果支持)。使用 MAX 的优点是减少线条绘制代码中的重叠伪像(硬三角形位) - 例如替换颜色,但仅限于达到总 alpha 值 X。编辑:这两种情况都需要在每次笔划后进行混合和清除.
我只能假设将渲染纹理混合到背景上实际上是有效的。(不适用于当前图层值)
顺便说一句,基本上不相关的还有“混合不足”,您可以在其中保留透射率值而不是 alpha/不透明度(来自here http://developer.download.nvidia.com/SDK/10/opengl/src/dual_depth_peeling/doc/DualDepthPeeling.pdf):
glBlendEquation(GL_FUNC_ADD);
glBlendFuncSeparate(GL_DST_ALPHA, GL_ONE, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);