2016-07-20 12:12 2513人閱讀 評論(0) 收藏 舉報數組
分類:編程語言
OpenGL(10) ide
版權聲明:本文爲博主原創文章,未經博主容許不得轉載。函數
原文連接:http://blog.csdn.net/xufeng0991/article/details/47256583ui
shader即着色器,就是專門用來渲染3D圖形的一種技術。
經過shader,能夠本身編寫顯卡渲染畫面的算法,使畫面更漂亮、更逼真。this
shader又分兩種,一種是頂點shader(3D圖形是由三角形組成的,頂點shader就是計算頂點位置,併爲後期像素渲染作準備的),
另外一種是像素shader,就是以像素爲單位,計算光照、顏色的一系列算法。url
幾個不一樣的圖形API有各自的shader語言:
在DirectX中,頂點shader叫作vertex shader,像素shader叫作pixel shader;
在OpenGL中,頂點shader也叫作vertex shader,但像素shader叫作fragment shader。
此外顯卡芯片廠商NVIDIA還推出CG顯卡編程語言,也支持shader。
編寫vertex Shader和fragment shader源碼。
建立兩個shader 實例:GLuint glCreateShader(GLenum type); [gl.createShader]
給Shader實例指定源碼。 glShaderSource [gl.shaderSource]
編譯shaer源碼 void glCompileShader(GLuint shader) [gl.compileShader]
建立shader program – GLuint glCreateProgram(void) [gl.createProgram]
綁定shader到program 。 void glAttachShader(GLuint program, GLuint shader)。每一個program必須綁定一個vertex shader 和一個fragment shader。 [gl.attachShader]
連接program 。 void glLinkProgram(GLuint program) [gl.linkProgram]
使用porgram 。 void glUseProgram(GLuint program) [gl.useProgram]
對於使用獨立shader編譯器編譯的二進制shader代碼,可以使用glShaderBinary來加載到一個shader實例中。
glsl即OpenGL Shading Language(OpenGL着色語言),是用來在OpenGL中着色編程的語言。
// 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