Hi,
I am trying to use a rendertexture in helloworld application win32 but always an rendering exception is happening.
I don’t know how to solve it. I am using cocos2dx-v3.6
Assert failed: Cannot add command while rendering
Assertion failed!
Program: …ShaderTestv3\proj.win32\Debug.win32\libcocos2d.dll
File: …\renderer\CCRenderer.cpp
Line: 379
Expression: !_isRendering
But I am adding the command when the init code of the scene is running.
The exception happens in line “mRTex->beginWithClear(0, 0, 0, 1);”
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if (!Layer::init())
{
return false;
}
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
mRTex = RenderTexture::create(visibleSize.width, visibleSize.height);
this->addChild(mRTex, 0, 0);
mRTex->setScale(1.0);
mRTex->setPosition(Point(visibleSize.width / 2, visibleSize.height / 2));
//mRTex->getSprite()->getTexture()->setAliasTexParameters();
// add "HelloWorld" splash screen"
auto sprite = Sprite::create("HelloWorld.png");
// position the sprite on the center of the screen
sprite->setPosition(Vec2(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y));
// add the sprite as a child to this layer
mRTex->addChild(sprite, 0);
this->scheduleUpdate();
// 3: Draw into the texture
//Caution!!! if you want to use your own opengl draw call ,you must wrap them with a custom command
_customCommand.init(mRTex->getGlobalZOrder());
_customCommand.func = CC_CALLBACK_0(HelloWorld::onDraw, this);
auto renderer = Director::getInstance()->getRenderer();
renderer->addCommand(&_customCommand);
return true;
}
void HelloWorld::visit(cocos2d::Renderer* renderer, const cocos2d::Mat4 &transform, uint32_t flags)
{
}
void HelloWorld::draw(cocos2d::Renderer* renderer, const cocos2d::Mat4 &transform, uint32_t flags)
{
}
void HelloWorld::onDraw()
{
mRTex->beginWithClear(0, 0, 0, 1);
Vector<Node*>& lChildren = this->getChildren();
for (int i = 0; i < lChildren.size(); i++)
{
cocos2d::Sprite* lNode = (cocos2d::Sprite*)lChildren.at(i);
lNode->visit();
}
mRTex->end();
}
void HelloWorld::update(float dt)
{
}
guys? any reply? this forum seems really not so active :-/
You need to add render commands in the overridden draw() method, not in the init() method, if I’m not mistaken.
Tried this already and done it again. I get same exception.
And did you set that up with:
void MyNode::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
_customCommand.init(_globalZOrder);
_customCommand.func = CC_CALLBACK_0(MyNode::onDraw, this, transform, flags);
renderer->addCommand(&_customCommand);
}
void MyNode::onDraw(const Mat4 &transform, uint32_t flags)
{
Director *director = Director::getInstance();
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, transform);
CHECK_GL_ERROR_DEBUG();
// Drawing code here
CHECK_GL_ERROR_DEBUG();
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
}
First, I want to thank you for your help! I really appreciate it!
But, unfortunately it still does not work 
I have cleaned up the cpp and h file. Maybe you can try it? Thank you!
Btw, I am using Visual Studio 2013.
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
class HelloWorld : public cocos2d::Layer
{
private:
cocos2d::RenderTexture* mRTex;
cocos2d::CustomCommand _customCommand;
public:
// there's no 'id' in cpp, so we recommend returning the class instance pointer
static cocos2d::Scene* createScene();
// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init();
virtual void draw(cocos2d::Renderer* renderer, const cocos2d::Mat4 &transform, uint32_t flags);
void onDraw(const cocos2d::Mat4 &transform, uint32_t flags);
// implement the "static create()" method manually
CREATE_FUNC(HelloWorld);
};
#endif // __HELLOWORLD_SCENE_H__
cpp file:
#include "HelloWorldScene.h"
USING_NS_CC;
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;
}
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if (!Layer::init())
{
return false;
}
auto s = Director::getInstance()->getWinSize();
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
mRTex = RenderTexture::create(s.width, s.height);
//mRTex->retain(); // should not be required
mRTex->setPosition(s / 2);
this->addChild(mRTex);
// add "HelloWorld" splash screen"
auto sprite = Sprite::create("HelloWorld.png");
// position the sprite on the center of the screen
sprite->setPosition(Vec2(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y));
// add the sprite as a child to this layer
mRTex->addChild(sprite, 0);
return true;
}
void HelloWorld::draw(cocos2d::Renderer* renderer, const cocos2d::Mat4 &transform, uint32_t flags)
{
_customCommand.init(mRTex->getGlobalZOrder());
_customCommand.func = std::bind(&HelloWorld::onDraw, this, transform, flags);
renderer->addCommand(&_customCommand);
}
void HelloWorld::onDraw(const Mat4 &transform, uint32_t flags)
{
Director *director = Director::getInstance();
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, transform);
CHECK_GL_ERROR_DEBUG();
mRTex->beginWithClear(0, 0, 0, 1);
Vector<Node*>& lChildren = this->getChildren();
for (int i = 0; i < lChildren.size(); i++)
{
cocos2d::Sprite* lNode = (cocos2d::Sprite*)lChildren.at(i);
lNode->visit();
}
mRTex->end();
CHECK_GL_ERROR_DEBUG();
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
}
Same issue in Xcode 6.4
CCASSERT(!_isRendering, “Cannot add command while rendering”);
I am astounded, there is nothing special on my code, or?
I am no expert in this area, however calling visit() within draw() is probably the cause. What are you trying to achieve as it looks like you want to draw child sprites, which is done automatically?
I want to render my sprites to a rendertexture and apply a shader afterwards.
In cocos v2.2.6 this scenario works without any problems.
I am having the same issue, I moved my visit code into my game loop…it works but it maxes out at 30 fps.
I would like a better solution as I should be looking toward 60fps.
When I find a solution I’ll let you know.