Проблемы с Cocos2dx CCRendertexture и framebuffer. Моя новая текстура не выглядит так же. Альфа-значения неверны
У меня возникла небольшая проблема при попытке использовать класс CCRenderTexture из Cocos2Dx для iPhone (который, насколько я понимаю, является просто классом FBO).
У меня есть класс, производный от CCSprite. В ней я пытаюсь нарисовать текстуру в текстуру CCrender, а затем сохранить ее на потом. Однако я заметил, что значения альфа в моей новой текстуре, похоже, усилились. Моя новая текстура выглядит немного более блеклой, чем оригинальная, кажется, что она воздействует только на пиксели с альфа-значением менее 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)
работать правильно.
После некоторых исследований я попытался заменить ccGLBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
с glBlendFuncSeparate(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA,GL_ONE, GL_SRC_ALPHA)
, Я надеялся, что это поддержит мои уровни альфа, изменяя значения цвета. К сожалению, это имело противоположный эффект и, казалось, фактически притупляло альфу, вызывая темноту текстуры.
Вот картина с моими тремя тестами. Этот актив снизу бикини позволяет легко увидеть эффект;)
Может кто-нибудь сказать мне, что я делаю, делаю неправильно и что вызывает эти эффекты? Это мой BlendFunc
? Я должен быть в состоянии привлечь к CCRenderTexture
(или FBO) несколько раз подряд, и я не хочу никаких нежелательных эффектов на изображении. Мне также нужно использовать мои шейдеры... так ccGLBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_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
,
После сравнения текстур в фотошопе оказалось, что glBlendFuncSeparate(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA,GL_ONE, GL_SRC_ALPHA)
умножил бы мои значения цвета на мое альфа-значение. Думаю, это имеет смысл, потому что я устанавливаю цветовую смесь на GL_ONE_MINUS_SRC_ALPHA
,
Поэтому мое решение состояло в том, чтобы полностью изменить этот эффект, разделив мои значения цвета на значение альфа в шейдере. Я добавил эти строки в конец моего шейдера.
texColor.r = texColor.r / texColor.a; \n\
texColor.b = texColor.b / texColor.a; \n\
texColor.g = texColor.g / texColor.a; \n\
Это кажется немного глупым, я бы предпочел найти способ, который вообще не вносит эти изменения в цвет, потому что этот шаг расточителен. Но это работает!