1、cocos主線程以及Auto-batching
AppDelegate app;//封裝用於智能分化,完成初始化,載入資源、構造場景、生成精靈
Application::getInstance()->run();//啓動主線程
director->mainLoop();//分爲場景渲染,和清理緩存池
glview->pollEvents();
drawScene:
1)優先處理輸入事件(空實現,留接口)
2)默認定時器(負優先級,0,正優先級)。自定義計時器
3)visit主渲染樹(autobatcch)是使用group
4)visit通知窗口
5)渲染,切換緩存區
visit:中序遍歷二叉樹,添加RenderCommand。
遍歷結束後執行Render():
排序RenderCommand爲三組:負、0、正;
RenderCommand中爲QUAD_COMMAND的將會進行autoBatch處理:
_batchedQuadCommands緩存池不斷添加單個QuadCommand,
當前的繪製命令繪製quad單元數加上現存的繪製單元數超過緩存池容量,則執行現存的繪製操作,並清理緩存池,之後添加命令至緩衝池中。
其餘繪製類型如custom、batchNode則是直接執行,不執行autoBatch。
而GroupCommand類型是又是一組繪製隊列,將遞歸地執行上訴過程。
1、shader繪製灰度紋理
在helloworld中增加變量:
cocos2d::CustomCommand m_customCommand;
void onDraw(const cocos2d::Mat4 &transform, uint32_t flags);
cocos2d::Sprite* m_pSprite;
cocos2d::V3F_C4B_T2F_Quad m_sQuad;
//cpp中代碼
#include "HelloWorldScene.h"
USING_NS_CC;
static Texture2D * texture2d;
//--------------------------------------------------------
static const GLchar* s_szColorSpriteVSH =
" \n\
attribute vec4 a_position; \n\
attribute vec2 a_texCoord; \n\
attribute vec4 a_color; \n\
\n\
#ifdef GL_ES \n\
varying lowp vec4 v_fragmentColor; \n\
varying mediump vec2 v_texCoord; \n\
#else \n\
varying vec4 v_fragmentColor; \n\
varying vec2 v_texCoord; \n\
#endif \n\
\n\
void main() \n\
{ \n\
gl_Position = CC_MVPMatrix * a_position; \n\
v_fragmentColor = a_color; \n\
v_texCoord = a_texCoord; \n\
}";
//--------------------------------------------------------
static const GLchar* s_szColorSpriteFSH =
" \n\
#ifdef GL_ES \n\
precision mediump float; \n\
#endif \n\
\n\
uniform sampler2D u_texture; \n\
varying vec2 v_texCoord; \n\
varying vec4 v_fragmentColor; \n\
\n\
void main(void) \n\
{ \n\
// vec3( 0.299, 0.587, 0.114 ) 是RGB轉YUV的參數值,生成灰色圖 \n\
float MixColor = dot(texture2D(u_texture, v_texCoord).rgb, vec3(0.299, 0.587, 0.114)); \n\
// 使用灰色圖進行顏色混合 \n\
vec4 blendColor = vec4( 1.0, 1.0, 1.0, 1.0 ); // 調整這個值以修改最終混合色值 \n\
gl_FragColor = vec4(MixColor * blendColor.r, MixColor * blendColor.g, MixColor * blendColor.b, blendColor.a); \n\
}";
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;
}
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
texture2d = TextureCache::sharedTextureCache()->addImage("HelloWorld.png");
texture2d->getGLProgram()->initWithVertexShaderByteArray( s_szColorSpriteVSH, s_szColorSpriteFSH );
texture2d->getGLProgram()->link();
CHECK_GL_ERROR_DEBUG();
texture2d->getGLProgram()->updateUniforms();
CHECK_GL_ERROR_DEBUG();
return true;
}
void HelloWorld::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
m_customCommand.init(_globalZOrder);
m_customCommand.func = CC_CALLBACK_0(HelloWorld::onDraw, this, transform, flags);
renderer->addCommand(&m_customCommand);
}
void HelloWorld::onDraw(const Mat4 &transform, uint32_t flags)
{
//ccGLBlendFunc( m_sBlendFunc.src, m_sBlendFunc.dst );
static GLfloat vertext[] = {
0.0f,0.0f,0.0f,
480.0f,0.0f,0.0f,
0.0f,320.0f,0.0f,
480.0f,320.0f,0.0f
};
//但是紋理的讀取也是逆時針,只是EG是用三角形作爲基礎圖形去繪製其他圖形,方向先繪製下三角,再繪製上三角!!!之前這裏搞錯了。希望大家別被我誤導了
static GLfloat coord[] = {
0.0f,1.0f,
1.0f,1.0f,
0.0f,0.0f,
1.0f,0.0f
};
static GLfloat colors[] = {
1.0f,1.0f,1.0f,1.0f,
1.0f,1.0f,1.0f,1.0f,
1.0f,1.0f,1.0f,1.0f,
1.0f,1.0f,1.0f,1.0f,
};
//初始化紋理,即將紋理映射至openGL ES的世界座標系中
coord[2] = coord[6] = texture2d->getMaxS();
coord[1] = coord[3] = texture2d->getMaxT();
//開啓着色器,座標、顏色、紋理
GL::enableVertexAttribs( GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX);
//設置着色器
texture2d->getGLProgram()->use();
//設置統一屬性,即M模型、V視圖、P投影,完成從Opengl的世界座標到屏幕座標的映射
texture2d->getGLProgram()->setUniformsForBuiltins();
//綁定紋理,texture2d->getName() 紋理在內存或顯存中存儲的下標(應該是下標,我沒看紋理加載,還不瞭解GPU和CPU的通信)
glBindTexture(GL_TEXTURE_2D,texture2d->getName());
//設置頂點,每個頂點向量維數爲3,數據類型爲GL_FLOAT,不歸一化(真實物理座標不能歸一化),兩個個頂點間的偏移量爲0,
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, 0, vertext);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, 0, coord);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR,4,GL_FLOAT,GL_FALSE,0,colors);
//繪圖,從下標0開始,有4個頂點
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
}
2、cocos2d-x中,添加C++和luaScript的橋接函數,比如:
int lua_cocos2dx_3d_Skeleton3D_getBoneByName(lua_State* tolua_S)
{
int argc = 0;
cocos2d::Skeleton3D* cobj = nullptr;
bool ok = true;
#if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
#endif
#if COCOS2D_DEBUG >= 1
if (!tolua_isusertype(tolua_S,1,"cc.Skeleton3D",0,&tolua_err)) goto tolua_lerror;
#endif
cobj = (cocos2d::Skeleton3D*)tolua_tousertype(tolua_S,1,0);
#if COCOS2D_DEBUG >= 1
if (!cobj)
{
tolua_error(tolua_S,"invalid 'cobj' in function 'lua_cocos2dx_3d_Skeleton3D_getBoneByName'", nullptr);
return 0;
}
#endif
argc = lua_gettop(tolua_S)-1;
if (argc == 1)
{
std::string arg0;
ok &= luaval_to_std_string(tolua_S, 2,&arg0, "cc.Skeleton3D:getBoneByName");
if(!ok)
{
tolua_error(tolua_S,"invalid arguments in function 'lua_cocos2dx_3d_Skeleton3D_getBoneByName'", nullptr);
return 0;
}
cocos2d::Bone3D* ret = cobj->getBoneByName(arg0);
object_to_luaval<cocos2d::Bone3D>(tolua_S, "cc.Bone3D",(cocos2d::Bone3D*)ret);
return 1;
}
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "cc.Skeleton3D:getBoneByName",argc, 1);
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'lua_cocos2dx_3d_Skeleton3D_getBoneByName'.",&tolua_err);
#endif
return 0;
}
3、面試遺留:
1)lua的table本身是由兩塊內存組成,一塊是連續的array,另外一塊則是hashTable實現的。因爲沒看過源碼不確認數組這塊的存儲,就沒有提及
2)lua的調用棧從1到N爲棧增加,即從棧底向棧頂進發。-1爲棧頂,-N爲棧底。具體的內存結構還沒看
3)QuickSort和HeapSort的確切代碼,主要在於QuickSort的非遞歸實現。
4)認真考究cocos2d的主線線程流程,有利於以後做架構優化
4、lua腳本調用C++,則是先壓函數地址爲0下標位;C++、lua入棧從左參數開始入棧。C++若調用lua的函數則需要使用lua_call;Lua只能調用使用特定格式的函數:
定義一個C/C++函數:
代碼:typedef int (*lua_CFunction) (lua_State *L); //要求參數和返回值必須和這個一直,即可以賦值函數指針給lua_CFunction的都可以被調用
函數必須以Lua解釋器作爲參數,並且返回值爲int類型。既然Lua解釋器作爲函數的參數,那麼實際上函數可以從棧中取得任意多個參數。下面我 們將看到,返回的整數值代表入棧的值的數目。如果有一個C/C++函數,你想在Lua中調用他,很容易封裝一下就可以滿足上述要求。
5、上面一條成爲C++粘合層,cocos2d-lua的分支就是增加了粘合層來建立lua虛擬機和C++庫的連接,同時刪減沒必要了模塊。這個粘合層在設計模式中叫做代理,早前雲風曾經提到是否使用類似的設計,如果真要提供庫,必須減少粘合層的厚度才能保證健壯性
lua這邊的庫也要實現Lua的粘合層,才能使得腳本開發時使用的是和C++類似的API。
cocos的粘合層需要重新編寫一邊,這也是爲什麼自定義庫需要使用luabinding等工具方便。而維護引擎必須也要熟悉cocos接口設計思想,如第3條,都會根據參數個數去實現粘合調用的是哪個接口,quick引擎組要做的事情大部分是這個吧。
6、以前實現的QuicklySort:在github上面有Cpp文件夾中有
void swap(int *x,int *y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
int participation(int a[],int l,int r)
{
int p = a[l];
int i = l;
int j = r+1;
while(i<j)
{
do{
i++;
}while(a[i]<=p);
do{
j--;
}while (a[j]>p);
swap(&a[i],&a[j]);
}
swap(&a[i],&a[j]);
swap(&a[l],&a[j]);
return j;
}
void QuicklySort(int a[],int l,int r)
{
int s = 0;
if(l<r)
{
s = participation(a,l,r);
QuicklySort(a,l,s-1);
QuicklySort(a,s+1,r);
}
}
7、
1、先記錄幾篇博客,供以後查看:
http://cn.cocos2d-x.org/tutorial/show?id=1474http://blog.csdn.net/ym012/article/details/7209637
http://www.cnblogs.com/sifenkesi/p/3876745.html
http://my.oschina.net/xlplbo/blog/314956
http://blog.csdn.net/dongdongdongjl/article/details/8629704
2、本人的環境文檔:鏈接:http://pan.baidu.com/s/1o6FROMY 密碼:o7vt
直接使用源碼配置。luac.c和lua.c相關說明參照:
http://blog.csdn.net/dongdongdongjl/article/details/8629704