cocos2dx 3.2 渲染(Director::drawScene 在游戏loop里每帧调用。 内部实际通过调用场景内每个node的 visit方法完成渲染)
2014-09-12 14:27
639 查看
Cocos2d-x 3.2与OpenGL渲染总结(一):Cocos2d-x 3.2的渲染流程
Node
/**
* Override this method to draw your own node.
* The following GL states will be enabled by default:
* - `glEnableClientState(GL_VERTEX_ARRAY);`
* - `glEnableClientState(GL_COLOR_ARRAY);`
* - `glEnableClientState(GL_TEXTURE_COORD_ARRAY);`
* - `glEnable(GL_TEXTURE_2D);`
* AND YOU SHOULD NOT DISABLE THEM AFTER DRAWING YOUR NODE
* But if you enable any other GL state, you should disable it after drawing your node.
*/
virtual void Node::draw(Renderer
*renderer, constMat4& transform,uint32_t
flags);
{
auto renderer = Director::getInstance()->getRenderer();
draw(renderer, _modelViewTransform, true);
}
virtual voidNode::draw() final;
{
}
/**
* Visits this node's children and draw them recursively.
*/
virtual voidNode::visit(Renderer
*renderer, const Mat4& parentTransform, uint32_t parentFlags);
{
// quick return if not visible. children won't be drawn.
if (!_visible)
{
return;
}
uint32_t flags = processParentFlags(parentTransform, parentFlags);
/////////////////////
&按位与 | 按位或
uint32_t Node::processParentFlags(const Mat4& parentTransform, uint32_t parentFlags)
{
uint32_t flags = parentFlags;
flags |= (_transformUpdated ? FLAGS_TRANSFORM_DIRTY : 0);
flags |= (_contentSizeDirty ? FLAGS_CONTENT_SIZE_DIRTY : 0);
if(_usingNormalizedPosition && (flags & FLAGS_CONTENT_SIZE_DIRTY)) {
CCASSERT(_parent, "setNormalizedPosition() doesn't work with orphan nodes");
auto s = _parent->getContentSize();
_position.x = _normalizedPosition.x * s.width;
_position.y = _normalizedPosition.y * s.height;
_transformUpdated = _transformDirty = _inverseDirty = true;
}
if(flags & FLAGS_DIRTY_MASK)
_modelViewTransform = this->transform(parentTransform);
_transformUpdated = false;
_contentSizeDirty = false;
return flags;
}
/////////////
// IMPORTANT:
// To ease the migration to v3.0, we still support the Mat4 stack,
// but it is deprecated and your code should not rely on it
Director* director = Director::getInstance();
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform);
int i = 0;
if(!_children.empty())
{
sortAllChildren();
// draw children zOrder < 0
for( ; i < _children.size(); i++ )
{
auto node = _children.at(i);
if ( node && node->_localZOrder < 0 )
node->visit(renderer, _modelViewTransform, flags);
else
break;
}
// self draw
this->draw(renderer, _modelViewTransform, flags);
for(auto it=_children.cbegin()+i; it != _children.cend(); ++it)
(*it)->visit(renderer, _modelViewTransform, flags);
}
else
{
this->draw(renderer, _modelViewTransform, flags);
}
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
}
virtual voidNode::visit()
final;
{
auto renderer = Director::getInstance()->getRenderer();
Mat4 parentTransform = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
visit(renderer, parentTransform, true);
}
/*
* Update method will be called automatically every frame if "scheduleUpdate" is called, and the node is "live"
*/
virtual voidNode::update(float
delta);
{
#if CC_ENABLE_SCRIPT_BINDING
if (0 != _updateScriptHandler)
{
//only lua use
SchedulerScriptData data(_updateScriptHandler,fDelta);
ScriptEvent event(kScheduleEvent,&data);
ScriptEngineManager::getInstance()->getScriptEngine()->sendEvent(&event);
}
#endif
if (_componentContainer && !_componentContainer->isEmpty())
{
_componentContainer->visit(fDelta); //node update 1 更新组件事件状态
}
}
voidNode::scheduleUpdate(void);
voidNode::scheduleUpdateWithPriority(int
priority);
Component* getComponent(const std::string& name);
virtual bool Node::addComponent(Component *component)
{
// lazy alloc
if( !_componentContainer )
_componentContainer = new ComponentContainer(this);
return _componentContainer->add(component);
}
virtual bool removeComponent(const std::string& name);
virtual void removeAllComponents();
protected:
ComponentContainer *_componentContainer;
————————————————————————————————————————————————————————————————————————————————————ponent
ComponentContainer
ComponentContainer::ComponentContainer(Node
*pNode);
virtual void ComponentContainer::visit(float delta); //node update 2
{
if (_components != nullptr)
{
CC_SAFE_RETAIN(_owner);
for (auto iter = _components->begin(); iter != _components->end(); ++iter)
{
iter->second->update(delta); //node update 3
}
CC_SAFE_RELEASE(_owner);
}
}
private:
Map<std::string, Component*>* _components;
Node *_owner;
friend class Node;
————————————————————————————————————————————————————————————————————————————————————
Component
#if CC_ENABLE_SCRIPT_BINDING
static bool sendComponentEventToJS(Component* node, int action) //作用域文件内可用 生存期全局
{
auto scriptEngine = ScriptEngineManager::getInstance()->getScriptEngine();
if (scriptEngine->isCalledFromScript())
{
scriptEngine->setCalledFromScript(false);
}
else
{
BasicScriptData data(node,(void*)&action);
ScriptEvent scriptEvent(kComponentEvent,(void*)&data);
if (scriptEngine->sendEvent(&scriptEvent))
return true;
}
return false;
}
#endif
virtual void Component::update(float delta) //node update 4
{
#if CC_ENABLE_SCRIPT_BINDING
if (_scriptType == kScriptTypeJavascript)
{
if (sendComponentEventToJS(this, kComponentOnUpdate)) //将组件绑定node 组件事件触发时通知js 有时间细看
return;
}
#endif
}
protected:
Node *_owner;
std::string _name;
bool _enabled;
————————————————————————————————————————————————————————————————————————————————————
CCDirector(Director::drawScene 在游戏loop里每帧调用。 内部实际通过调用场景内每个node的 visit方法完成渲染)
/** Draw the scene.
This method is called every frame. Don't call it manually.
*/
// Draw the Scene
void Director::drawScene()
{
// calculate "global" dt
calculateDeltaTime();
// skip one flame when _deltaTime equal to zero.
if(_deltaTime < FLT_EPSILON)
{
return;
}
if (_openGLView)
{
_openGLView->pollInputEvents();
////////////////////////
/**
* Polls input events. Subclass must implement methods if platform
* does not provide event callbacks.
*/
virtual void pollInputEvents();
////////////////////////
}
//tick before glClear: issue #533
if (! _paused) //只要游戏没有暂停,调度器神马的就会在这里被执
{
_scheduler->update(_deltaTime);
_eventDispatcher->dispatchEvent(_eventAfterUpdate);
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除指定的缓冲区
(颜色缓冲以及深度缓冲)
/* to avoid flickr(网络相簿), nextScene MUST be here: after tick and before draw.
XXX: Which bug is this one. It seems that it can't be reproduced(重现 重制的)
with v0.9 */
if (_nextScene)
{
setNextScene();
}
pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);//设置gl使用的矩阵类型
//////////////////////////
enum class MATRIX_STACK_TYPE
{
MATRIX_STACK_MODELVIEW,
MATRIX_STACK_PROJECTION,
MATRIX_STACK_TEXTURE
};
OpenGL 的ModelView矩阵
/////////////////////////
// draw the scene
if (_runningScene)
{
//visit() 这个函数在cocos3.2工程内部基本没用到了 被visit(_renderer, Mat4::IDENTITY, false)取代
_runningScene->visit(_renderer, Mat4::IDENTITY, false);
/** Dispatches(调度) the event
* Also removes all EventListeners marked for deletion(删除) from the
* event dispatcher list.
*/
_eventDispatcher->dispatchEvent(_eventAfterVisit);//visit完成后调度事件
cocos3.2貌似什么都没做
}
// draw the notifications node
if (_notificationNode)
{
_notificationNode->visit(_renderer, Mat4::IDENTITY, false);
}
if (_displayStats)
{
showStats();
}
_renderer->render();
_eventDispatcher->dispatchEvent(_eventAfterDraw); //Draw完成后调度事件
cocos3.2貌似什么都没做
popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
_totalFrames++;
// swap buffers
if (_openGLView)
{
_openGLView->swapBuffers();
}
if (_displayStats)
{
calculateMPF();
}
}
Node
/**
* Override this method to draw your own node.
* The following GL states will be enabled by default:
* - `glEnableClientState(GL_VERTEX_ARRAY);`
* - `glEnableClientState(GL_COLOR_ARRAY);`
* - `glEnableClientState(GL_TEXTURE_COORD_ARRAY);`
* - `glEnable(GL_TEXTURE_2D);`
* AND YOU SHOULD NOT DISABLE THEM AFTER DRAWING YOUR NODE
* But if you enable any other GL state, you should disable it after drawing your node.
*/
virtual void Node::draw(Renderer
*renderer, constMat4& transform,uint32_t
flags);
{
auto renderer = Director::getInstance()->getRenderer();
draw(renderer, _modelViewTransform, true);
}
virtual voidNode::draw() final;
{
}
/**
* Visits this node's children and draw them recursively.
*/
virtual voidNode::visit(Renderer
*renderer, const Mat4& parentTransform, uint32_t parentFlags);
{
// quick return if not visible. children won't be drawn.
if (!_visible)
{
return;
}
uint32_t flags = processParentFlags(parentTransform, parentFlags);
/////////////////////
&按位与 | 按位或
uint32_t Node::processParentFlags(const Mat4& parentTransform, uint32_t parentFlags)
{
uint32_t flags = parentFlags;
flags |= (_transformUpdated ? FLAGS_TRANSFORM_DIRTY : 0);
flags |= (_contentSizeDirty ? FLAGS_CONTENT_SIZE_DIRTY : 0);
if(_usingNormalizedPosition && (flags & FLAGS_CONTENT_SIZE_DIRTY)) {
CCASSERT(_parent, "setNormalizedPosition() doesn't work with orphan nodes");
auto s = _parent->getContentSize();
_position.x = _normalizedPosition.x * s.width;
_position.y = _normalizedPosition.y * s.height;
_transformUpdated = _transformDirty = _inverseDirty = true;
}
if(flags & FLAGS_DIRTY_MASK)
_modelViewTransform = this->transform(parentTransform);
_transformUpdated = false;
_contentSizeDirty = false;
return flags;
}
/////////////
// IMPORTANT:
// To ease the migration to v3.0, we still support the Mat4 stack,
// but it is deprecated and your code should not rely on it
Director* director = Director::getInstance();
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform);
int i = 0;
if(!_children.empty())
{
sortAllChildren();
// draw children zOrder < 0
for( ; i < _children.size(); i++ )
{
auto node = _children.at(i);
if ( node && node->_localZOrder < 0 )
node->visit(renderer, _modelViewTransform, flags);
else
break;
}
// self draw
this->draw(renderer, _modelViewTransform, flags);
for(auto it=_children.cbegin()+i; it != _children.cend(); ++it)
(*it)->visit(renderer, _modelViewTransform, flags);
}
else
{
this->draw(renderer, _modelViewTransform, flags);
}
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
}
virtual voidNode::visit()
final;
{
auto renderer = Director::getInstance()->getRenderer();
Mat4 parentTransform = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
visit(renderer, parentTransform, true);
}
/*
* Update method will be called automatically every frame if "scheduleUpdate" is called, and the node is "live"
*/
virtual voidNode::update(float
delta);
{
#if CC_ENABLE_SCRIPT_BINDING
if (0 != _updateScriptHandler)
{
//only lua use
SchedulerScriptData data(_updateScriptHandler,fDelta);
ScriptEvent event(kScheduleEvent,&data);
ScriptEngineManager::getInstance()->getScriptEngine()->sendEvent(&event);
}
#endif
if (_componentContainer && !_componentContainer->isEmpty())
{
_componentContainer->visit(fDelta); //node update 1 更新组件事件状态
}
}
voidNode::scheduleUpdate(void);
voidNode::scheduleUpdateWithPriority(int
priority);
Component* getComponent(const std::string& name);
virtual bool Node::addComponent(Component *component)
{
// lazy alloc
if( !_componentContainer )
_componentContainer = new ComponentContainer(this);
return _componentContainer->add(component);
}
virtual bool removeComponent(const std::string& name);
virtual void removeAllComponents();
protected:
ComponentContainer *_componentContainer;
————————————————————————————————————————————————————————————————————————————————————ponent
ComponentContainer
ComponentContainer::ComponentContainer(Node
*pNode);
virtual void ComponentContainer::visit(float delta); //node update 2
{
if (_components != nullptr)
{
CC_SAFE_RETAIN(_owner);
for (auto iter = _components->begin(); iter != _components->end(); ++iter)
{
iter->second->update(delta); //node update 3
}
CC_SAFE_RELEASE(_owner);
}
}
private:
Map<std::string, Component*>* _components;
Node *_owner;
friend class Node;
————————————————————————————————————————————————————————————————————————————————————
Component
#if CC_ENABLE_SCRIPT_BINDING
static bool sendComponentEventToJS(Component* node, int action) //作用域文件内可用 生存期全局
{
auto scriptEngine = ScriptEngineManager::getInstance()->getScriptEngine();
if (scriptEngine->isCalledFromScript())
{
scriptEngine->setCalledFromScript(false);
}
else
{
BasicScriptData data(node,(void*)&action);
ScriptEvent scriptEvent(kComponentEvent,(void*)&data);
if (scriptEngine->sendEvent(&scriptEvent))
return true;
}
return false;
}
#endif
virtual void Component::update(float delta) //node update 4
{
#if CC_ENABLE_SCRIPT_BINDING
if (_scriptType == kScriptTypeJavascript)
{
if (sendComponentEventToJS(this, kComponentOnUpdate)) //将组件绑定node 组件事件触发时通知js 有时间细看
return;
}
#endif
}
protected:
Node *_owner;
std::string _name;
bool _enabled;
————————————————————————————————————————————————————————————————————————————————————
CCDirector(Director::drawScene 在游戏loop里每帧调用。 内部实际通过调用场景内每个node的 visit方法完成渲染)
/** Draw the scene.
This method is called every frame. Don't call it manually.
*/
// Draw the Scene
void Director::drawScene()
{
// calculate "global" dt
calculateDeltaTime();
// skip one flame when _deltaTime equal to zero.
if(_deltaTime < FLT_EPSILON)
{
return;
}
if (_openGLView)
{
_openGLView->pollInputEvents();
////////////////////////
/**
* Polls input events. Subclass must implement methods if platform
* does not provide event callbacks.
*/
virtual void pollInputEvents();
////////////////////////
}
//tick before glClear: issue #533
if (! _paused) //只要游戏没有暂停,调度器神马的就会在这里被执
{
_scheduler->update(_deltaTime);
_eventDispatcher->dispatchEvent(_eventAfterUpdate);
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除指定的缓冲区
(颜色缓冲以及深度缓冲)
/* to avoid flickr(网络相簿), nextScene MUST be here: after tick and before draw.
XXX: Which bug is this one. It seems that it can't be reproduced(重现 重制的)
with v0.9 */
if (_nextScene)
{
setNextScene();
}
pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);//设置gl使用的矩阵类型
//////////////////////////
enum class MATRIX_STACK_TYPE
{
MATRIX_STACK_MODELVIEW,
MATRIX_STACK_PROJECTION,
MATRIX_STACK_TEXTURE
};
OpenGL 的ModelView矩阵
/////////////////////////
// draw the scene
if (_runningScene)
{
//visit() 这个函数在cocos3.2工程内部基本没用到了 被visit(_renderer, Mat4::IDENTITY, false)取代
_runningScene->visit(_renderer, Mat4::IDENTITY, false);
/** Dispatches(调度) the event
* Also removes all EventListeners marked for deletion(删除) from the
* event dispatcher list.
*/
_eventDispatcher->dispatchEvent(_eventAfterVisit);//visit完成后调度事件
cocos3.2貌似什么都没做
}
// draw the notifications node
if (_notificationNode)
{
_notificationNode->visit(_renderer, Mat4::IDENTITY, false);
}
if (_displayStats)
{
showStats();
}
_renderer->render();
_eventDispatcher->dispatchEvent(_eventAfterDraw); //Draw完成后调度事件
cocos3.2貌似什么都没做
popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
_totalFrames++;
// swap buffers
if (_openGLView)
{
_openGLView->swapBuffers();
}
if (_displayStats)
{
calculateMPF();
}
}
相关文章推荐
- 【iOS-cocos2d-X 游戏开发之十三】详细讲解在Xcode中利用预编译并通过Jni调用Android的Java层代码(cocos2dx里访问调用Android函数)!
- 利用cocos2dx 3.2开发消灭星星(四)游戏主场景
- 09_通过读取配置文件的方式来使用反射完成对实例对象方法调用
- Cocos2d-xna : 横版战略游戏开发实验3 Scene和Director场景切换
- 无法通过方法调用转换将实际参数android.app.FragmentManager转换为FragmentTransaction
- Vue在页面数据渲染完成之后的调用方法
- 通过bindservice调用服务内部方法
- Cocos2d-x游戏开发之Cocos2dx通过JNI调用Android的Java代码(webView实例)
- 通过反射调用类内部的方法
- cocos2dx3.2 整体概览(三)—— Scene(场景)
- cocos2dx[3.2] ——核心类Director/Scene/Layer/Sprite详细讲解
- 通过函数指针调用对象内部方法
- 【iOS-cocos2d-X 游戏开发之十三】cocos2dx通过Jni调用Android的Java层代码(上)
- 【Cocos2dx】利用导演类、场景类完成重新开始游戏、暂停游戏、关闭游戏功能
- JavaScript调用App原生代码(iOS、Android)通用解决方案 实际场景 场景:现在有一个H5活动页面,上面有一个登陆按钮,要求点击登陆按钮以后,唤出App内部的登录界面,当登录成功
- 300.33通过读取配置文件方式来使用反射完成实例对象调用方法
- Angularjs通过指令监听ng-repeat渲染完成后执行脚本的方法
- 【cocos2dx 3.2】一个都不能死7 游戏结束场景
- cocos2dx-3.2(34) DrawNode 绘图API
- 【iOS-cocos2d-X 游戏开发之十三】详细讲解在Xcode中利用预编译并通过Jni调用Android的Java层代码(cocos2dx里访问调用Android函数)!