iPhone OpenGL ES 2.0与Cocos2D的混合产生了意想不到的结果
我有一个非常简单的CCScene,只有一个CCLayer包含:iPhone OpenGL ES 2.0与Cocos2D的混合产生了意想不到的结果,iphone,cocos2d-iphone,opengl-es-2.0,alpha,blending,Iphone,Cocos2d Iphone,Opengl Es 2.0,Alpha,Blending,我有一个非常简单的CCScene,只有一个CCLayer包含: 标准混合模式背景的CCSprite CCRenderTexture绘制画笔,其精灵附着到背景精灵上方的根CCLayer: 当用户使用第一个彩色笔刷时,它会像预期的那样与背景混合。 但是,如果继续在上一个笔刷的顶部使用另一种颜色刷牙,则会出现错误(当两个笔刷相互重叠时,软alpha边将失去不透明度): [_renderTexture begin]; glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE
[_renderTexture begin];
glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE, GL_ONE); // 1.
// calculate vertices code,etc...
glDrawArrays(GL_TRIANGLES, 0, (GLsizei)count);
[_renderTexture end];
我尝试了许多混合选项,但不知何故,我找不到正确的一个
CCRenderTexture是否有一些特殊之处,使其无法像预期的那样与自身(先前绘制的内容)混合?
我的用于刷牙的片段着色器只是标准纹理着色器,只需稍作更改即可在纹理中保留输入颜色alpha:
void main()
{
gl_FragColor = texture2D(u_texture, v_texCoord);
gl_FragColor.a = v_fragmentColor.a;
}
在呈现代码时(代替//1.
和
这非常有效,可以满足我的需求……
…但仅当重新渲染为完全不透明度时。
当\u rendertexture.sprite
的不透明度降低时,画笔会变亮,而不是像预期的那样淡出:
为什么当父纹理处于完全不透明度时,画笔的字母正确地与背景混合,而当不透明度降低时,画笔的字母会变得异常?如何使画笔正确地与背景混合?编辑
混合笔刷->图层->背景
好的,现在发生的是glBlendFunc(GL_SRC_ALPHA,GL_ONE_减去GL_SRC_ALPHA)
正在将笔刷笔划混合到笔刷纹理中,但纹理中产生的alpha值是错误的。每个添加的片段需要1.将其alpha值添加到最终alpha值-它必须准确地移除交互所需的光线,2.将之前的alpha值按剩余值缩放-之前的曲面减少light是以前的值,但由于添加了一个新的表面,它们减少的光线就更少了。我不确定这是否有意义,但这导致了
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
现在,笔刷纹理的颜色通道包含要与背景混合的总颜色(与alpha预先相乘),alpha通道给出权重(或颜色遮挡背景的量)。由于颜色与alpha预先相乘,默认的渲染纹理混合GL_SRC_alpha,GL_ONE_减_SRC_alpha
再次与alpha缩放,从而使整体颜色变暗。现在需要使用以下函数将笔刷纹理与背景混合,我收集的函数必须在Cocos2D中设置:
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
希望这是可能的。对于如何设置笔刷纹理以与GL_SRC_ALPHA,GL_ONE_减号_SRC_ALPHA
混合的可能性,我没有过多考虑,但它可能需要浮点纹理和/或额外的过程来分割/规格化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
笔刷层不透明度
使用GL\u ONE,GL\u ONE\u减去\u SRC\u ALPHA
会导致库在层混合中实现不透明度的问题,因为它假设颜色乘以ALPHA。通过减少不透明度
值,笔刷层的ALPHA在混合过程中会缩小。GL\u ONE\u减去\u SRC\u ALPHA
然后会导致背景色要增加,但画笔层的总颜色为100%,使图像过饱和
imo最简单的解决方案是找到一种方法,通过全局图层不透明度来缩小颜色比例,并继续使用GL\u ONE,GL\u ONE\u减去\u SRC\u ALPHA
- 实际上使用
GL\u CONSTANT\u COLOR,GL\u ONE\u减去SRC\u ALPHA
可能是一个答案,如果库支持它,但显然它不支持
- 您可以使用固定管道渲染来缩放颜色:
glColor4f(不透明度、不透明度、不透明度、不透明度)
,但这将需要第二个渲染目标并手动进行混合,类似于上面的代码,在上面的代码中,您为背景绘制一次全屏四元图,为笔刷层绘制一次全屏四元图
- 如果您手动进行混合,则使用片段着色器而不是
glColor
方法将更为稳健。如果您想要使用更复杂的混合函数,这将允许进行更大的控制,尤其是在涉及0到1范围之外的分割和临时性时:
gl\u FragColour=纹理(画笔纹理,坐标)*图层能力;
结束编辑
标准的alpha混合函数是glBlendFunc(GL_SRC_alpha,GL_ONE_减去_SRC_alpha);
,而不是GL“initial”/default函数
在glBlendFuncSeparate中对alpha值求和将使alpha过饱和,下面的颜色将被完全替换。饱和混合可能会产生不错的结果:。如果支持,还可能值得尝试和MAX混合。使用MAX的好处是减少重叠的人工制品(硬三角形位)从您的线条绘制代码-例如,替换颜色,但仅在达到总阿尔法值X之前。编辑:两种情况都需要在每个笔划后混合和清除
我只能假设将渲染纹理混合到背景上实际上是可行的。(不适用于当前层值)
另一方面,也有“欠混合”,即保留透射比值,而不是alpha/opacity(从):
glBlendFunc(GL_SRC_ALPHA_SATURATE,GL_ONE)不起作用-请参阅问题的更新部分(在底部)。我假设您
glBlendFunc(GL_ONE, 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
glBlendEquation(GL_FUNC_ADD);
glBlendFuncSeparate(GL_DST_ALPHA, GL_ONE, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);