gpt4 book ai didi

iPhone OpenGL ES 2.0 与 Cocos2D 混合给出了意想不到的结果

转载 作者:行者123 更新时间:2023-12-03 19:06:47 25 4
gpt4 key购买 nike

我有非常简单的 CCScene,只有 1 个 CCLayer,其中包含:

  • CCSprite 用于标准混合模式的背景
  • CCRenderTexture 用于绘制画笔,其 Sprite 附加到背景 Sprite 上方的根 CCLayer:
  • _bgSprite = [CCSprite spriteWithFile:backgroundPath];_renderTexture = [CCRenderTexture renderTextureWithWidth:self.contentSize.width height:self.contentSize.height];[_renderTexture.sprite setBlendFunc:(ccBlendFunc){GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA}];[self addChild:_bgSprite z:-100];[self addChild:_renderTexture];

    Brush rendering code:

    [_renderTexture begin];
    glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE, GL_ONE); // 1.
    // calculate vertices code,etc...
    glDrawArrays(GL_TRIANGLES, 0, (GLsizei)count);
    [_renderTexture end];

    当用户用第一个彩色画笔刷时,它 按预期与背景混合 .
    但是什么时候继续 在前一个画笔上刷上另一种颜色,会出错(当 2 个画笔相互重叠时,软 alpha 边缘会失去不透明度):

    enter image description here

    我尝试了许多混合选项,但不知何故我找不到正确的选项。

    CCRenderTexture 有什么特别之处,它没有按预期与自身(与先前绘制的内容)混合?

    我用于刷的片段着色器只是标准纹理着色器,稍作更改以保留纹理中的输入颜色 alpha:
    void main(){    gl_FragColor = texture2D(u_texture, v_texCoord);    gl_FragColor.a = v_fragmentColor.a;}

    UPDATE - ALMOST PERFECT SOLUTION : by jozxyqk

    glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
    GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

    在渲染代码中(代替 // 1.
    [_renderTexture.sprite setBlendFunc:(ccBlendFunc){GL_ONE, GL_ONE_MINUS_SRC_ALPHA}];
    这很好用,给了我我想要的...

    enter image description here

    ...但仅当 _rederTexture 完全不透明时。

    当不透明度为 _rendertexture.sprite降低,画笔变亮而不是像人们预期的那样淡出:

    enter image description here

    为什么当父纹理处于完全不透明度时,画笔的 alpha 与背景正确混合,但在不透明度降低时变得香蕉?如何使画笔与背景正确融合?

    最佳答案

    编辑

    混合画笔 -> 图层 -> 背景

    好的,发生的事情是 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);

    现在,笔刷纹理的颜色 channel 包含要与背景混合的总颜色(与 alpha 预乘),并且 alpha channel 给出权重(或颜色遮盖背景的量)。由于颜色预先与 alpha 相乘,因此默认的 RenderTexture 混合 GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA再次与 alpha 缩放,从而使整体颜色变暗。您现在需要使用以下函数将画笔纹理与背景混合,我认为必须在 Cocos2D 中设置:
    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

    希望这是可能的。我还没有考虑如何管理设置画笔纹理以与 GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA 混合的可能性。但它可能需要浮点纹理和/或额外的 channel 来划分/规范化 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

    small test in GL

    画笔图层不透明度

    使用 GL_ONE, GL_ONE_MINUS_SRC_ALPHA导致库在图层混合中实现不透明度的问题,因为它假定颜色乘以 alpha。通过减少 opacity值,画笔层的 alpha 在混合过程中按比例缩小。 GL_ONE_MINUS_SRC_ALPHA然后导致背景颜色的数量增加,但是 GL_ONE将画笔层的 100% 相加并使图像过饱和。

    最简单的解决方案imo是自己找到一种方法通过全局图层不透明度来缩小颜色并继续使用 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;

  • 结束编辑

    标准的 alpha 混合函数是 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); ,不完全是 GL 的“初始”/默认功能。

    像在 glBlendFuncSeparate 中一样对 alpha 值求和会使 alpha 过饱和,并且完全替换下面的颜色。饱和度混合可能会得到不错的结果: glBlendFunc(GL_SRC_ALPHA_SATURATE, GL_ONE) .也可能值得尝试 glBlendEquationSeparate和 MAX 混合(如果支持)。使用 MAX 的好处是减少线条绘制代码中的重叠伪影(硬三角位) - 例如替换颜色,但仅在达到总 alpha 值 X 之前。编辑:这两种情况都需要在每次中风后混合和清除。

    我只能假设将渲染纹理混合到背景上实际上是有效的。 (不适用于当前图层值)

    顺便提一下,在很大程度上不相关的还有“混合不足”,您可以在其中保留透射率值而不是 alpha/不透明度(来自 here ):
    glBlendEquation(GL_FUNC_ADD); 
    glBlendFuncSeparate(GL_DST_ALPHA, GL_ONE, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);

    关于iPhone OpenGL ES 2.0 与 Cocos2D 混合给出了意想不到的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18735542/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com