cocos2D-X源碼分析之從cocos2D-X學習OpenGL(6)---cocos內置着色器

       上一篇我們介紹了cocos2d-x繪製基本圖形的基本流程,我們還留下了一個着色器的部分沒有講,本篇內容將從openGL的渲染流程講起,介紹cocos2d-x中的着色器,openGL的渲染流程如圖所示:

       

       openGL的繪製通常就是將頂點數據傳輸到openGL服務端。我們可以將一個頂點視爲一個需要統一處理的數據包,這個包中的數據可以是我們需要的任何數據,通常其中幾乎始終會包含位置數據。其他數據可能用來決定一個像素的最終顏色。

       頂點着色器:一個複雜的應用程序可能包含許多個頂點着色器,但是在同一時刻只能有一個頂點着色器起作用,它用來進行頂點的變換,可能會非常簡單,簡單到傳遞着色器,也可能包含大量的計算。

       幾何着色器:對幾何圖元做處理,可以創建新的圖元,這個階段是可選的

       細分着色器:頂點着色器存在一些限制,一個就是它們在執行的過程中無法創建額外的幾何圖形,它們僅僅更新與它們當前所處理的頂點相關數據,無法訪問當前圖元中其他頂點數據,它包含細分控制着色器和細分計算着色器。

       像素着色器(片元着色器):通過編程控制在屏幕上顯示顏色的階段,在這個階段中,我們使用着色器來計算片元的最終顏色和它的深度值。片元着色器非常強大,在這裏我們會使用紋理映射的方式,對頂點處理階段進行補充。可能還會丟棄不需要處理的片元

       簡而言之,頂點着色器決定一個圖元應該位於屏幕什麼位置,而片元着色器使用這些信息來決定摸個片元的顏色是什麼。這兩個着色器是必選的。另外因爲頂點着色器階段處理的頂點比較少,而在像素着色階段處理的像素會很多,所以有時會在頂點階段處理顏色和光照,其餘的像素進行插值處理,爲了節約效率,當然效果要差些了。

       下面來看cocos2d-x的着色器流程,回到上一篇講的DrawNode的init函數中

    //設置着色器
    setGLProgramState(GLProgramState::getOrCreateWithGLProgramName(GLProgram::SHADER_NAME_POSITION_LENGTH_TEXTURE_COLOR));
       這句話調用setGLProgramState設置着色器狀態,setGLProgramState函數代碼如下:

void Node::setGLProgramState(cocos2d::GLProgramState* glProgramState)
{
    if (glProgramState != _glProgramState)
    {
        CC_SAFE_RELEASE(_glProgramState);
        _glProgramState = glProgramState;
        CC_SAFE_RETAIN(_glProgramState);

        if (_glProgramState)
            _glProgramState->setNodeBinding(this);
    }
}
      這段代碼判斷設置的着色器是否與之前設置的相同,不同就重新設置,在onDraw函數中,會使用設置的着色器

auto glProgram = getGLProgram();
glProgram->use();
glProgram->setUniformsForBuiltins(transform);
       其中getGLProgram函數就是獲得着色器,代碼如下:

GLProgram * Node::getGLProgram() const
{
    return _glProgramState ? _glProgramState->getGLProgram() : nullptr;
}
      或者乾脆直接在使用時傳遞使用哪個着色器

auto glProgram = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_LENGTH_TEXTURE_COLOR);
glProgram->use();
glProgram->setUniformsForBuiltins(transform);
       無論哪種方式,我們這裏都使用的是cocos2d-x的內置的着色器代碼,它們在“cocos目錄/cocos/renderer”目錄中    
       具體的詳細加載可以看GLProgramCache類的loadDefaultGLProgram函數,這是一個單例類,在初始化的時候就會加載所有的內置着色器,然後這些着色器的代碼文本以鍵值對的方式存儲程序中,當使用的時候就通過getGLProgram調用,我們看一下這裏使用的GLProgram::SHADER_NAME_POSITION_LENGTH_TEXTURE_COLOR:

        頂點着色器:ccShader_PositionColorLengthTexture.vert

        像素着色器:ccShader_PositionColorLengthTexture.frag


const char* ccPositionColorLengthTexture_vert = STRINGIFY(

\n#ifdef GL_ES\n
attribute mediump vec4 a_position;
attribute mediump vec2 a_texcoord;
attribute mediump vec4 a_color;

varying mediump vec4 v_color;
varying mediump vec2 v_texcoord;

\n#else\n

attribute vec4 a_position;
attribute vec2 a_texcoord;
attribute vec4 a_color;

varying vec4 v_color;
varying vec2 v_texcoord;

\n#endif\n

void main()
{
    v_color = vec4(a_color.rgb * a_color.a, a_color.a);
    v_texcoord = a_texcoord;

    gl_Position = CC_MVPMatrix * a_position;
}
);

       cocos2d-x的內置着色器採用字符串的方式存儲,可讀性上會差一些,忽略掉“\n”之類的應該還好,着色器使用GLSL,在下一篇中會詳細介紹,它類似於C語言,main函數是入口,這裏處理了輸入進來的顏色,貼圖和位置信息,並做相應處理,位置進行了MVP的轉換。

       下一篇會介紹GLSL

       

       能力不足,水平有限,如有錯誤,歡迎指出。







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章