原文链接:http://blog.csdn.net/xufeng0991/article/details/47256583
一 shader的基本概念
1 什么是shadershader即着色器,就是专门用来渲染3D图形的一种技术。
通过shader,可以自己编写显卡渲染画面的算法,使画面更漂亮、更逼真。
2 shader分类
shader又分两种,一种是顶点shader(3D图形是由三角形组成的,顶点shader就是计算顶点位置,并为后期像素渲染做准备的),
另一种是像素shader,就是以像素为单位,计算光照、颜色的一系列算法。
3 shader语言
几个不同的图形API有各自的shader语言:
在DirectX中,顶点shader叫做vertex shader,像素shader叫做pixel shader;
在OpenGL中,顶点shader也叫做vertex shader,但像素shader叫做fragment shader。
此外显卡芯片厂商nVidia还推出CG显卡编程语言,也支持shader。
二 shader程序
1 语言glslglsl即OpenGL Shading Language(OpenGL着色语言),是用来在OpenGL中着色编程的语言。
2 顶点着色器
// vert.vsh
attribute vec4 a_position; attribute vec4 a_color; varying vec4 v_fragmentColor; void main() { gl_Position = CC_MVPMatrix * a_position; v_fragmentColor = a_color; }
(1) 每一个Shader程序都有一个main函数;
(2) 有两种类型的变量:
attribute是从外部传进来的;
varying类型的变量是在vertex shader和fragment shader之间传递数据用的;
每一个顶点都会有attribute和varying属性,定点着色器作用于每个定点,有多少个点就会执行多少次。
3 片段着色器
// frag.fsh
varying vec4 v_fragmentColor; void main() { gl_FragColor = v_fragmentColor; }
(1) main函数;
(2) varying类型的变量是在vertex shader和fragment shader之间传递数据用的;
(3) gl_FragColor系统内置变量,定义最终画在屏幕上面的像素点的颜色;
三 程序调用
新建cocos工程,将上面两个文件放到Resource/shaders文件夹下,修改代码如下:// .h
#ifndef __HELLOWORLD_SCENE_H__ #define __HELLOWORLD_SCENE_H__ #include "cocos2d.h" USING_NS_CC; class HelloWorld : public cocos2d::Layer { public: // there's no 'id' in cpp,so we recommend returning the class instance pointer static cocos2d::Scene* createScene(); // Here's a difference. Method 'init' in cocos2d-x returns bool,instead of returning 'id' in cocos2d-iphone virtual bool init(); // implement the "static create()" method manually CREATE_FUNC(HelloWorld); virtual void visit(Renderer *renderer,const Mat4 &transform,uint32_t parentFlags) override; void onDraw(); private: CustomCommand _customCommand; GLuint VAO; GLuint vertexVBO; GLuint colorVBO; }; #endif // __HELLOWORLD_SCENE_H__
// .cpp
#include "HelloWorldScene.h" 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; } auto program = CCGLProgram::createWithFilenames("shaders/vert.vsh","shaders/frag.fsh"); program->link(); program->updateUniforms(); this->setGLProgram(program); glGenVertexArrays(1,&VAO); glBindVertexArray(VAO); glGenBuffers(1,&vertexVBO); glBindBuffer(GL_ARRAY_BUFFER,vertexVBO); auto size = Director::getInstance()->getVisibleSize(); float vertercies[] = { 0,size.width,size.width / 2,size.height }; float color[] = { 0,1,1 }; glBufferData(GL_ARRAY_BUFFER,sizeof(vertercies),vertercies,GL_STATIC_DRAW); GLuint positionLocation = glGetAttribLocation(program->getProgram(),"a_position"); glEnableVertexAttribArray(positionLocation); glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION,2,GL_FLOAT,GL_FALSE,(GLvoid*)0); glGenBuffers(1,&colorVBO); glBindBuffer(GL_ARRAY_BUFFER,colorVBO); glBufferData(GL_ARRAY_BUFFER,sizeof(color),color,GL_STATIC_DRAW); GLuint colorLocation = glGetAttribLocation(program->getProgram(),"a_color"); glEnableVertexAttribArray(colorLocation); glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR,4,(GLvoid*)0); return true; } void HelloWorld::visit(cocos2d::Renderer *renderer,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(); glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLES,3); CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1,3); CHECK_GL_ERROR_DEBUG(); }
效果如下:
win7默认关闭VAO,需要手动开启:libcocos2d工程-》属性-》C/C++-》预处理器,在预处理器定义中添加CC_TEXTURE_ATLAS_USE_VAO=1 参考:http://zilongshanren.com/blog/2014/06/07/write-your-own-shader/