Cocos2dx CCRendertexture 和 framebuffer 对象问题。我的新纹理看起来不一样。 Alpha 值不正确

Posted

技术标签:

【中文标题】Cocos2dx CCRendertexture 和 framebuffer 对象问题。我的新纹理看起来不一样。 Alpha 值不正确【英文标题】:Cocos2dx CCRendertexture and framebuffer object problems. My new texture doesn't look the same. Alpha values are incorrect 【发布时间】:2013-05-23 02:43:55 【问题描述】:

我在尝试将 Cocos2Dx 中的 CCRenderTexture 类用于 iPhone 时遇到了一点问题(据我所知,它只是一个 FBO 类)。

我有一个派生自 CCSprite 的类。在其中,我尝试将纹理绘制到 CCrenderTexture,然后将其保存以备后用。但是,我注意到我的新纹理中的 alpha 值似乎已经增强了。我的新纹理看起来比原始纹理更褪色,它似乎只影响 alpha 小于 1.0 的像素。

这是我正在使用的代码:

CCRenderTexture* myRenderTexture = CCRenderTexture::create((int)getContentSize().width, (int)getContentSize().height);   //set RenderTexture to same size as sprite

myRenderTexture->begin();

CC_NODE_DRAW_SETUP();

ccGLEnableVertexAttribs(kCCVertexAttribFlag_PosColorTex);

ccGLBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);      //Is this where my problem is?  

glActiveTexture(GL_TEXTURE0);


glBindTexture( GL_TEXTURE_2D, finalTexture->getName());     //finalTexture is created before this code is run
glUniform1i(textureLocation, 0);


long offset = (long)&m_sQuad;

// vertex
int diff = offsetof( ccV3F_C4B_T2F, vertices);
glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (void*) (offset + diff));
// texCoods
diff = offsetof( ccV3F_C4B_T2F, texCoords);
glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (void*)(offset + diff));
// color
diff = offsetof( ccV3F_C4B_T2F, colors);
glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (void*)(offset + diff));

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glActiveTexture(GL_TEXTURE0);


myRenderTexture->end();
finalTexture = myRenderTexture->getSprite()->getTexture();   //Replace Final Texture with my new texture (Should be exact same)

finalTexture->retain();
myRenderTexture->release();

作为测试,我连续运行了 4 次以上代码。每一次,质地似乎都淡化了一点。但我期望它每次看起来都一样。

我采取的下一步是将ccGLBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) 替换为ccGLBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA) 这似乎解决了我的问题,因为无论我运行多少次,生成的纹理看起来都是一样的。然而,我也在这个纹理上运行一个自定义片段着色器(着色器在这个测试期间没有显示并且没有运行),它需要ccGLBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) 才能正常工作。

经过一番研究,我尝试用glBlendFuncSeparate(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA,GL_ONE, GL_SRC_ALPHA) 替换ccGLBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)。我希望这将保持我的 alpha 水平,同时改变颜色值。不幸的是,这产生了相反的效果,似乎实际上使 alpha 变暗,导致纹理变暗。

这是我的三个测试的图片。这个比基尼底部资产很容易看到效果;)

谁能告诉我我做错了什么以及是什么导致了这些影响?是我的BlendFunc吗?我需要能够连续多次绘制CCRenderTexture(或FBO),并且我不希望对图像产生任何不良影响。我还需要使用我的着色器……所以ccGLBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA) 不起作用……

感谢任何帮助!提前致谢!

【问题讨论】:

可能是预乘 alpha 问题 【参考方案1】:

我能够找到适合我的解决方案。我不确定它是否理想或是否有更好的方法,但它似乎有效。

正如我之前所说,使用 ccGLBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA) 可以让我尽可能多次地使用 CCRenderTexture,但我的着色器无法正常工作。

更改为glBlendFuncSeparate(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA,GL_ONE, GL_SRC_ALPHA) 允许着色器,但每次我将其渲染为CCRenderTexture 时纹理都会变暗。

在 Photoshop 中比较纹理后,glBlendFuncSeparate(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA,GL_ONE, GL_SRC_ALPHA) 似乎会将我的颜色值乘以我的 alpha 值。我想这是有道理的,因为我将颜色混合设置为GL_ONE_MINUS_SRC_ALPHA

所以我的解决方案是通过将我的颜色值除以着色器中的 alpha 值来反转这种效果。我将这些行添加到我的着色器的末尾。

texColor.r = texColor.r / texColor.a;      \n\
texColor.b = texColor.b / texColor.a;      \n\
texColor.g = texColor.g / texColor.a;      \n\ 

看起来有点傻,我宁愿找到一种根本不对颜色进行这些更改的方法,因为这一步很浪费。但它有效!

【讨论】:

以上是关于Cocos2dx CCRendertexture 和 framebuffer 对象问题。我的新纹理看起来不一样。 Alpha 值不正确的主要内容,如果未能解决你的问题,请参考以下文章

cocos2dx截整屏截部分屏

使用 CCRenderTexture 在 CoCos2d V2.xx 中保存屏幕截图

关于cocos2dx触摸的问题

cocos2dx3.3 csb帧动画怎么加载

cocos2dx android 代码混淆

cocos2dx android 代码混淆