Scene *scene=Scene::create();
director->runWithScene(scene);
//目标
auto layer = LayerColor::create(Color4B(0,255,0,255),100,100);
//主要的步骤就是设置了node 的 _position
layer->setPosition(10,10);
scene->addChild(layer);
bool LayerColor::initWithColor(const Color4B& color,GLfloat w,GLfloat h)
{
if (Layer::init())
{
// default blend function
//指定混合模式
_blendFunc = BlendFunc::ALPHA_NON_PREMULTIPLIED;
/*
realColor和displayedColor 记录元素本身的颜色属性
displayedColor和displayedOpacity方法用于表示和父亲元素叠加过后的最终绘制颜色
sprite用于父亲颜色和自己纹理的混合,LayColor默认一致,不叠加颜色
*/
_displayedColor.r = _realColor.r = color.r;
_displayedColor.g = _realColor.g = color.g;
_displayedColor.b = _realColor.b = color.b;
_displayedOpacity = _realOpacity = color.a;
//四个顶点 初始化
for (size_t i = 0; i<sizeof(_squareVertices) / sizeof( _squareVertices[0]); i++ )
{
_squareVertices[i].x = 0.0f;
_squareVertices[i].y = 0.0f;
}
//四个顶点的颜色归一化,颜色是一样的
updateColor();
//w,h 为 设计分辨率,设置顶点的范围
setContentSize(Size(w,h));
/*
每个node拥有一个GLProgramState实例
查找这种类型的shader GLProgram SHADER_NAME_POSITION_COLOR_NO_MVP
*/
GLProgramState* state=GLProgramState::getOrCreateWithGLProgramName(GLProgram::SHADER_NAME_POSITION_COLOR_NO_MVP);
setGLProgramState(state);
return true;
}
return false;
}
/// override contentSize
void LayerColor::setContentSize(const Size & size)
{
//没有赋值的为0,也就是 0(0,0) 1(w,0) 2 (0,h) 3(w,h)
//绘制顺序为012 213
_squareVertices[1].x = size.width;
_squareVertices[2].y = size.height;
_squareVertices[3].x = size.width;
_squareVertices[3].y = size.height;
Layer::setContentSize(size);
}
void Node::setContentSize(const Size & size)
{
if ( ! size.equals(_contentSize))
{
_contentSize = size;
//得到锚点在本地坐标系下的坐标
_anchorPointInPoints = Vec2(_contentSize.width * _anchorPoint.x,_contentSize.height * _anchorPoint.y );
//告诉该更新了
_transformUpdated = _transformDirty = _inverseDirty = _contentSizeDirty = true;
}
}
void Director::drawScene()
{
//省略部分代码
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//兼容cocos2.0,暂时忽略
pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
// draw the scene
if (_runningScene)
{//正式访问
_runningScene->visit(_renderer,Mat4::IDENTITY,false);//第一次的矩阵是单位矩阵
_eventDispatcher->dispatchEvent(_eventAfterVisit);
}
//开始真正的opengl
_renderer->render();
popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
_totalFrames++;
// swap buffers
if (_openGLView)
{
_openGLView->swapBuffers();//这个之后再看
}
if (_displayStats)
{
calculateMPF();//不知道啥意思
}
}
void Node::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);
// 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
/*
为了便于迁移到v3.0,我们仍然支持Mat4堆栈,
但它已被弃用,您的代码不应该依赖它
*/
Director* director = Director::getInstance();
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
//把刚生产的模型视图矩阵加入到顶部的modeview【对scene来说,执行下面代码之前,里面已经有3个modelview】
//这个代码针对2.0的,对3.1没啥意义了
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,flags);
for(auto it=_children.cbegin()+i; it != _children.cend(); ++it)
(*it)->visit(renderer,flags);
}
else
{
this->draw(renderer,flags);
}
/*
画完了就退出战,是兼容2.0的时候,现在不需要这个了
矩阵的转换都在GPU的shader中了
*/
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
// FIX ME: Why need to set _orderOfArrival to 0??
// Please refer to https://github.com/cocos2d/cocos2d-x/pull/6920
// reset for next frame
// _orderOfArrival = 0;
}
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);//节点自己的转换矩阵,节点的本地坐标乘以这个矩阵就会得到世界坐标
//更新完毕,标记为false
_transformUpdated = false;
_contentSizeDirty = false;
return flags;
}
//transform为本地坐标转世界坐标的矩阵
void LayerColor::draw(Renderer *renderer,const Mat4 &transform,uint32_t flags)
{
_customCommand.init(_globalZOrder);
//回调函数
_customCommand.func = CC_CALLBACK_0(LayerColor::onDraw,this,transform,flags);
//把绘制命令的东西放到renderer里面
renderer->addCommand(&_customCommand);
for(int i = 0; i < 4; ++i)
{
Vec4 pos;
//四个顶点的设计分辨率坐标
pos.x = _squareVertices[i].x; pos.y = _squareVertices[i].y; pos.z = _positionZ;
pos.w = 1;//齐次坐标
//得出来的pos就是世界坐标下的pos了
_modelViewTransform.transformVector(&pos);
//pos.w 世界坐标的w始终为1
//这个世界坐标会在shader内乘以相机矩阵和裁剪矩阵,得出最后的视口需要的坐标
_noMVPVertices[i] = Vec3(pos.x,pos.y,pos.z)/pos.w;
}
}
void Renderer::render()
{
//Process render commands
//1. Sort render commands based on ID
//renderGroups包括若干rederqueue,默认使用第一个,
//renderquque包括若干个rendercommand
for (auto &renderqueue : _renderGroups)
{
renderqueue.sort();
}
visitRenderQueue(_renderGroups[0]);
flush();
clean();
}
void Renderer::visitRenderQueue(const RenderQueue& queue)
{
ssize_t size = queue.size();
for (ssize_t index = 0; index < size; ++index)
{
auto command = queue[index];
auto commandType = command->getType();
if(RenderCommand::Type::CUSTOM_COMMAND == commandType)//比如 LayerColor
{
flush();
auto cmd = static_cast<CustomCommand*>(command);
cmd->execute();//会调用LayerColor::onDraw,直接开始绘图
}
}
}
//通过自定义方法进行回调 transform为 本地坐标转世界坐标的旋转矩阵
void LayerColor::onDraw(const Mat4& transform,uint32_t flags)
{
getGLProgram()->use();//layercolor 的tansform为相机矩阵*裁剪矩阵
getGLProgram()->setUniformsForBuiltins(transform);//设置顶点着色器中全局变量的值,如MVP矩阵
//启用 顶点坐标和颜色
GL::enableVertexAttribs( GL::VERTEX_ATTRIB_FLAG_POSITION | GL::VERTEX_ATTRIB_FLAG_COLOR );
//
// Attributes
//
#ifdef EMSCRIPTEN
setGLBufferData(_noMVPVertices,4 * sizeof(Vec3),0);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION,3,GL_FLOAT,GL_FALSE,0);
setGLBufferData(_squareColors,4 * sizeof(Color4F),1);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR,4,0);
#else
//找到顶点的索引 _noMVPVertices为世界坐标中的四个顶点的值,存在了cpu中,没有存到显存
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION,3,0,_noMVPVertices);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR,_squareColors);
#endif // EMSCRIPTEN
//混合,源和目标 颜色的混合
GL::blendFunc( _blendFunc.src,_blendFunc.dst );
//画这四个点
glDrawArrays(GL_TRIANGLE_STRIP,4);
//这是记录图元和顶点吗
// CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,4);
auto __renderer__ = Director::getInstance()->getRenderer();
__renderer__->addDrawnBatches(1);
__renderer__->addDrawnVertices(4);
}