您的位置:首页 > 移动开发 > Cocos引擎

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();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐