关于 rendertexture的问题



代码是参考ray wenderlish的一个教程,每点击一次鼠标创建一次rendertexture,
在rendertexture对象里面添加了customcommand

然后我在customcommand对应的render()函数里面添加了opengl代码,并在其最后添加glBlendFunc(GL_ZERO, GL_ZERO);

最后的结果就是,第一次rendertexture的内容正确显示,但第二次以后屏幕全黑




#include "HelloWorldScene.h"


Scene* HelloWorld::createScene()
{
// 'scene' is an autorelease object
auto scene = Scene::create();

// 'layer' is an autorelease object
auto layer = HelloWorld::create();

// add layer as a child to scene
scene->addChild(layer);

// return the scene
return scene;
}

bool HelloWorld::init()
{

if ( !Layer::init() )
{
return false;
}
_screenSize = Director::getInstance()->getVisibleSize();
Point origin = Director::getInstance()->getVisibleOrigin();

auto listener = EventListenerTouchOneByOne::create();
listener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this);

_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);

this->schedule(schedule_selector(HelloWorld::step));

return true;
}

Sprite* HelloWorld::initSpriteWithColor(Color4F c1, Color4F c2, float textureWidth, float textureHeight, int nStripes)
{

_c2 = c2;
_nStripes = nStripes;

auto rt = RenderTexture::create(textureWidth, textureHeight);
rt->beginWithClear(c1.r, c1.g, c1.b, c1.a);
auto render = Director::getInstance()->getRenderer();

_customCommand.init(rt->getGlobalZOrder());
_customCommand.func = CC_CALLBACK_0(HelloWorld::render, this);
render->addCommand(&_customCommand);

rt->end();



auto sprite = Sprite::createWithTexture(rt->getSprite()->getTexture());

return sprite;
}

Color4F HelloWorld::randomBrightColor()
{
while(true)
{
float requiredBrightness = 192;
Color4B randomColor =
Color4B(std::rand() % 255, std::rand() % 255, std::rand() % 255, 255);
if(randomColor.r > requiredBrightness ||
randomColor.g > requiredBrightness ||
randomColor.b > requiredBrightness)
{
return Color4F(randomColor);
}
}
}

void HelloWorld::genBackGround()
{
srand(time(NULL));

auto bgColor = this->randomBrightColor();
auto color2 = this->randomBrightColor();

int nSprites = ((rand() % 4) + 1) * 2;

_backGround = this->initSpriteWithColor(bgColor, color2, _screenSize.width , _screenSize.height, nSprites);
_backGround->setPosition(Point(_screenSize.width / 2, _screenSize.height / 2));

_backGround->setScale(0.5);

this->addChild(_backGround, -1);
}

void HelloWorld::onEnter()
{
log("entered");
Node::onEnter();

this->genBackGround();

}


bool HelloWorld::onTouchBegan(Touch *touch, Event *unused_event)
{
log("touched");
_backGround->removeFromParentAndCleanup(true);

this->genBackGround();
return true;
}


void HelloWorld::step(float dt)
{

}

void HelloWorld::render()
{
log("HelloWorld::render()");
float textureWidth = _screenSize.width;
float textureHeight = _screenSize.height;

this->setShaderProgram(ShaderCache::getInstance()->getProgram(GLProgram::SHADER_NAME_POSITION_COLOR));

CC_NODE_DRAW_SETUP();

Point* vertices = new Point;
Color4F* colors = new Color4F;

int nVertices = 0;

float x1 = -textureWidth;
float x2;
float y1 = textureWidth;
float y2 = 0;
float dx = textureWidth / _nStripes * 2;


float stripeWidth = dx / 2;
for(int i = 0; i < _nStripes; i++)//changed _nStripes
{
x2 = x1 + textureWidth;

vertices = Point(x1, y1);
colors = Color4F(_c2.r, _c2.g, _c2.b, _c2.a);

vertices = Point(x1 + stripeWidth, y1);
colors = Color4F(_c2.r, _c2.g, _c2.b, _c2.a);

vertices = Point(x2, y2);
colors = Color4F(_c2.r, _c2.g, _c2.b, _c2.a);

vertices = vertices;
colors = Color4F(_c2.r, _c2.g, _c2.b, _c2.a);

vertices = vertices;
colors = Color4F(_c2.r, _c2.g, _c2.b, _c2.a);

vertices = Point(x2 + stripeWidth, y2);
colors = Color4F(_c2.r, _c2.g, _c2.b, _c2.a);

x1 += dx;
}
GL::enableVertexAttribs( GL::VERTEX_ATTRIB_FLAG_POSITION | GL::VERTEX_ATTRIB_FLAG_COLOR);


glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);

glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_FLOAT, GL_TRUE, 0, colors);

glDrawArrays(GL_TRIANGLES, 0, (GLsizei)nVertices);


float gradientAlpha = 0.5f;

nVertices = 0;

vertices = Point(0, 0);
colors = Color4F(0.0, 0.0, 1.0, gradientAlpha);

vertices = Point (textureWidth - 300, 0);
colors = Color4F(0.0, 0.0, 1.0, gradientAlpha);

vertices = Point (0, textureHeight - 300);
colors = Color4F(0.0, 0.0, 1.0, gradientAlpha);

vertices = Point (textureWidth - 300, textureHeight - 300);
colors = Color4F(0.0, 0.0, 1.0, gradientAlpha);


glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_FLOAT, GL_TRUE, 0, colors);
glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei)nVertices);


float boardHeight = textureHeight / 16;
float boardAlpha = 1.0f;

nVertices = 0;

vertices = Point(0, 0);
colors = Color4F(1.0f, 0.0f, 1.0f, boardAlpha);

vertices = Point(textureWidth, 0);
colors = Color4F(1.0f, 0.0f, 1.0f, boardAlpha);

vertices = Point(0, boardHeight);
colors = Color4F(1.0f, 0.0f, 1.0f, boardAlpha);

vertices = Point(textureWidth, boardHeight);
colors = Color4F(1.0f, 0.0f, 1.0f, boardAlpha);

glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_FLOAT, GL_TRUE, 0, colors);
glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei)nVertices);


glBlendFunc(GL_ZERO, GL_ZERO); /////添加了这句并点击后出现问题

}

```

要知道cocos2d的render顺序,应该必须要看底层,我尝试去看了以下cocos2dx的底层实现,但看不懂,请教一下大家

问题已经解决了,我在render()程序的最后加上glBlendFunc(CC_BLEND_SRC, CC_BLEND_DST),就可以了。
我没看底层,但估计是由于若在customCommand.func的自定义opengl画图代码里面最后加了glBlendFunc()会影响之后的opengl画图操作,因为cocos里面sprite->draw()函数默认是调用glBlendFunc(CC_BLEND_SRC, CCBLEND_DST)的,而当我在render()最后加上glBlendFunc(GL_ZERO, GL_ZERO),结果二次addchild该sprite的时候显示一片黑色。然而由于我不清楚cocos的render顺序,看了底层没太认真看有点看不懂,因此影响了哪一步我不知道,还需要仔细看懂底层实现才能解决。