cocos2dx(3.X)中使用shader

 cocos2dx(3.X)中使用shader 算法

標籤: cocos2d-xshader編程

 2513人閱讀 評論(0) 收藏 舉報數組

category_icon.jpg 分類:編程語言

OpenGL(10) arrow_triangle%20_down.jpgide

目錄(?)[+]post

原文連接:http://blog.csdn.net/xufeng0991/article/details/47256583ui

一 shader的基本概念

1 什麼是shader

shader即着色器,就是專門用來渲染3D圖形的一種技術。 
經過shader,能夠本身編寫顯卡渲染畫面的算法,使畫面更漂亮、更逼真。this

2 shader分類

shader又分兩種,一種是頂點shader(3D圖形是由三角形組成的,頂點shader就是計算頂點位置,併爲後期像素渲染作準備的), 
另外一種是像素shader,就是以像素爲單位,計算光照、顏色的一系列算法。url

3 shader語言

幾個不一樣的圖形API有各自的shader語言: 
在DirectX中,頂點shader叫作vertex shader,像素shader叫作pixel shader; 
在OpenGL中,頂點shader也叫作vertex shader,但像素shader叫作fragment shader。 
此外顯卡芯片廠商NVIDIA還推出CG顯卡編程語言,也支持shader。

二 shader開發流程

這裏寫圖片描述

  1. 編寫vertex Shader和fragment shader源碼。

  2. 建立兩個shader 實例:GLuint glCreateShader(GLenum type); [gl.createShader]

  3. 給Shader實例指定源碼。 glShaderSource [gl.shaderSource]

  4. 編譯shaer源碼 void glCompileShader(GLuint shader) [gl.compileShader]

  5. 建立shader program – GLuint glCreateProgram(void) [gl.createProgram] 

  6. 綁定shader到program 。 void glAttachShader(GLuint program, GLuint shader)。每一個program必須綁定一個vertex shader 和一個fragment shader。 [gl.attachShader] 

  7. 連接program 。 void glLinkProgram(GLuint program) [gl.linkProgram]

  8. 使用porgram 。 void glUseProgram(GLuint program) [gl.useProgram]

對於使用獨立shader編譯器編譯的二進制shader代碼,可以使用glShaderBinary來加載到一個shader實例中。

三 shader程序

1 語言glsl

glsl即OpenGL Shading Language(OpenGL着色語言),是用來在OpenGL中着色編程的語言。

2 頂點着色器

// vert.vsh// 頂點着色器,VBO/VAO提供的每一個頂點都執行一遍頂點着色器,輸出一個varying和gl_Position等// 變量修飾:// attribute: 只讀,隨不一樣頂點變化的全局變量,應用程序傳入,只能用在頂點着色器中// uniform: 只讀,隨不一樣圖元變化的全局變量,應用程序傳入,// varying: 在頂點shader中可寫,在片段shader中只讀,用於在頂點着色器和片斷着色器之間傳遞數據// 輸入: attribute, 輸出:varying+gl_positon + gl_Position + gl_PointSizeattribute vec4 a_position;attribute vec4 a_color;varying vec4 v_fragmentColor;// 每個Shader程序都有一個main函數void main()
{    // gl開頭的變量名是系統內置的變量
    gl_Position = CC_MVPMatrix * a_position;// 每一個點固有的Varying,表示點的空間位置。
    v_fragmentColor = a_color;
}12345678910111213141516171819202122

3 片斷着色器

// frag.fsh// 片元着色器,光柵化輸出的每一個片元都執行一遍片斷着色器,生成一個或多個(多重渲染)顏色值做爲輸出// 輸入: varying, 輸出: gl_FragColor + gl_FragDepth//用於在頂點着色器和片斷着色器之間傳遞數據,所以類型必須徹底一直varying vec4 v_fragmentColor;// 每個Shader程序都有一個main函數void main()
{    // gl開頭的變量名是系統內置的變量
    gl_FragColor = v_fragmentColor;// gl_FragColor 定義最終畫在屏幕上面的像素點的顏色}12345678910111213

三 程序調用

新建cocos工程,將上面兩個文件放到Resource/shaders文件夾下,修改代碼以下:

// .h#ifndef __HELLOWORLD_SCENE_H__#define __HELLOWORLD_SCENE_H__#include "cocos2d.h"USING_NS_CC;class HelloWorld : public cocos2d::Layer
{public:    static cocos2d::Scene* createScene();    virtual bool init();

    CREATE_FUNC(HelloWorld);    virtual void visit(Renderer *renderer, const Mat4& parentTransform, uint32_t parentFlags);    void onDraw();private:
    CustomCommand _customCommand;

    GLuint _vao;
    GLuint _vertVBO;
    GLuint _colorVBO;
};#endif // __HELLOWORLD_SCENE_H__1234567891011121314151617181920212223242526272829
// .cpp#include "HelloWorldScene.h"USING_NS_CC;

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 instancebool HelloWorld::init()
{    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() )
    {        return false;
    }    /*
    在OpenGL中,GLSL的shader使用的流程與C語言類似,每一個shader相似一個C模塊,首先須要單獨編譯(compile),
    而後一組編譯好的shader鏈接(link)成一個完整程序。
    */
    auto program = CCGLProgram::createWithFilenames("shader/vert.vsh", "shader/frag.fsh");
    program->link();
    program->updateUniforms();    this->setGLProgram(program);    /*
    使用VBO和VAO的步驟都差很少,步驟以下:
    1 glGenXXX
    2 glBindXXX
    */

    // 建立和綁定vao
    glGenVertexArrays(1, &_vao); 
    glBindVertexArray(_vao);    // 建立和綁定vbo
    glGenBuffers(1, &_vertVBO);// 生成VBO
    glBindBuffer(GL_ARRAY_BUFFER, _vertVBO); // 關聯到當前的VAO

    auto size = Director::getInstance()->getVisibleSize();    float vertercies[] = {// 三角形頂點位置
        0, 0, // 第1個點座標
        size.width, 0, // 第2個點座標
        size.width / 2, size.height // 第3個點座標
    };    // 給VBO設置數據
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertercies), vertercies, GL_STATIC_DRAW);    // 得到變量a_position在內存中的位置
    GLuint positionLocation = glGetAttribLocation(program->getProgram(), "a_position");
    glEnableVertexAttribArray(positionLocation);    // 提交包含數據的數組指針
    glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);    // 設置顏色
    float color[] = {// 三角形頂點顏色RGBA
        0, 1, 0, 1,        1, 0, 0, 1,        0, 0, 1, 1
    };
    glGenBuffers(1, &_colorVBO);
    glBindBuffer(GL_ARRAY_BUFFER, _colorVBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(color), color, GL_STATIC_DRAW);    // 得到變量a_color在內存中的位置
    GLuint colorLocation = glGetAttribLocation(program->getProgram(), "a_color");
    glEnableVertexAttribArray(colorLocation);
    glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);

    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);    return true;
}void HelloWorld::visit(cocos2d::Renderer *renderer, const Mat4 &transform, uint32_t parentFlags)
{
    Layer::draw(renderer, transform, parentFlags);

    _customCommand.init(_globalZOrder);
    _customCommand.func = CC_CALLBACK_0(HelloWorld::onDraw, this);
    renderer->addCommand(&_customCommand);
}void HelloWorld::onDraw()
{    auto glProgram = getGLProgram();
    glProgram->use();
    glProgram->setUniformsForBuiltins();    /*
    VAO裏的VBOs都設置好了之後,在繪製的地方只須要設置當前綁定的VAO是哪一個,
    就能按照初始化的VAO來繪製,即調用glDrawArrays
    */

    // 設置當前綁定的VAO
    glBindVertexArray(_vao);    // 繪製三角形
    glDrawArrays(GL_TRIANGLES, 0, 3);    // 解綁當前VAO,但並不釋放
    glBindVertexArray(0);

    CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, 3);
    CHECK_GL_ERROR_DEBUG();
}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122

效果以下:

這裏寫圖片描述

win7默認關閉VAO,須要手動開啓:libcocos2d工程-》屬性-》C/C++-》預處理器,在預處理器定義中添加CC_TEXTURE_ATLAS_USE_VAO=1

相關文章
相關標籤/搜索