在本系列教程中,我会以当下最流行的2D引擎Cocos2D-X为基础,介绍OpenGL ES 2.0的一些基本用法。本系列教程的宗旨是OpenGL扫盲,让你们在使用Cocos2D-X过程当中,知其然,更知其因此然。由于我本身的图形学水平有限,因此这些教程不会涉及很是底层的数学原理,同时也不会过多地说起OpenGL自己的一些细节知识。可是我会在每篇文章的最后给出一些参考连接,你们能够顺藤摸瓜,一举Get OpenGL这个新技能。html
我第一次学习OpenGL是在2008年,可是那时候学得很烂,被各类矩阵变换搞得云里雾里。我于今年年初完全从新学习OpenGL,目前来说,应该算是入门了,至少矩阵变换是理解了,同时也会本身写一些简单的shader,能够进行OpenGL调试了。可是,个人学习之路才刚刚开始,我但愿在我本身学习的过程,把有用的一些知识记录下来,方便本身和他人查阅。通过此次从新学习,我我的以为,OpenGL真的没有那么难,只要你用心,就必定能够学会。固然,好的学习方法和好的学习资料确定是会使之事半功倍的,但愿接下来个人这些博文能为你们带来些许帮助。node
在第一篇文章正式开始前,我谈下我本身的入门心得体会吧,而《如何学习OpenGL》这是个更大的话题,等我OpenGL水平精进以后,我再单独写一篇文章来谈谈个人见解。git
目前来讲,个人体会是“三要”和“三不要”。api
要理解OpenGL渲染管线缓存
要理解OpenGL是个状态机ide
要多动手实践。函数
固然还有最重要的“三不要”:工具
不要天天去群里问怎样最快能学好OpenGL学习
不要天天去看各类资料而不动手写一点代码网站
不要出了问题处处问,尝试先本身解决,实在解决不了再问
首先,是建立一个新的工程(注意我这里使用的版本是3.7. Update: Tuesday, June 16, 2015)。打开命令行工具,而后输入下列命令:
1 |
cocos new -l cpp |
若是对于上述命令不了解的用户,请猛戳这里.
编译并运行成功,而后把HelloWorldScene.cpp里面的init函数修改为下面的样子:
12345678910 |
bool HelloWorld::init(){ ////////////////////////////// // 1. super init first if ( !Layer::init() ) { return false; } return true; } |
此时,再编译运行之。你将会获得如下界面。
因为Cocos2D-X 从3.0开始引入了一种新的渲染机制,全部的OpenGL渲染代码再也不放到每个node的draw函数里面,而是经过各类RenderCommand封装起来,而后添加到一个渲染队列里面去,最后在每一帧结束时把全部的这些命令都渲染出来。具体细节,你们能够参考这个文档.
首先,打开HelloWorldScene.h,添加一个onDraw函数,一个CustomCommand成员变量,而且重载Layer的visit函数,代码以下:
12345678910 |
class HelloWorld : public cocos2d::Layer{public: //其它函数省略 virtual void visit(Renderer *renderer, const Mat4& parentTransform, uint32_t parentFlags) override; void onDraw();private: CustomCommand _command;}; |
而后咱们实现这个visit函数:
1234567 |
void HelloWorld::visit(cocos2d::Renderer *renderer, const Mat4 &transform,uint32_t parentFlags){ Layer::visit(renderer, transform, parentFlags); _command.init(_globalZOrder); _command.func = CC_CALLBACK_0(HelloWorld::onDraw, this); Director::getInstance()->getRenderer()->addCommand(&_command);} |
这里要稍微解释一下。因为此函数是个重载的虚函数,因此咱们在函数的最开始调用了父类的visit函数。若是你不调用父类的visit函数,那么当你往HelloWorldScene里面添加节点的时候,它们是不会被渲染出来的。(这个留给读者本身去完成)
而后,咱们使用_globalZOrder和一个std::function来初始化CustomCommand。_globalZOrder会影响渲染的顺序,这个在后面的博文中再详细探讨。而std::function会在CustomCommand被render队列处理的时候被调用。最后咱们把该CustomCommand添加到renderer里面去。
最后,让咱们看看onDraw函数,它是整个绘制三角形的核心。
123456789101112131415161718192021222324252627282930 |
void HelloWorld::onDraw(){ //得到当前HelloWorld的shader auto glProgram = getGLProgram(); //使用此shader glProgram->use(); //设置该shader的一些内置uniform,主要是MVP,即model-view-project矩阵 glProgram->setUniformsForBuiltins(); auto size = Director::getInstance()->getWinSize(); //指定将要绘制的三角形的三个顶点,分别位到屏幕左下角,右下角和正中间的顶端 float vertercies[] = { 0,0, //第一个点的坐标 size.width, 0, //第二个点的坐标 size.width / 2, size.height}; //第三个点的坐标 //指定每个顶点的颜色,颜色值是RGBA格式的,取值范围是0-1 float color[] = { 0, 1,0, 1, //第一个点的颜色,绿色 1,0,0, 1, //第二个点的颜色, 红色 0, 0, 1, 1}; //第三个点的颜色, 蓝色 //激活名字为position和color的vertex attribute GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POSITION | GL::VERTEX_ATTRIB_FLAG_COLOR); //分别给position和color指定数据源 glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertercies); glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_FLOAT, GL_FALSE, 0, color); //绘制三角形,所谓的draw call就是指这个函数调用 glDrawArrays(GL_TRIANGLES, 0, 3); //通知cocos2d-x 的renderer,让它在合适的时候调用这些OpenGL命令 CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, 3); //若是出错了,可使用这个函数来获取出错信息 CHECK_GL_ERROR_DEBUG();} |
若是你如今直接运行程序,会crash。这是由于咱们尚未指定Shader,因此下面的调用会失败:
123456789 |
auto glProgram = getGLProgram();glProgram->use();glProgram->setUniformsForBuiltins();``` 接下来,让咱们在HelloWorldScene.cpp的init方法中加入下列代码:```cppthis->setGLProgram(GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_COLOR)); |
这个调用的含义是从Cocos2D-X的shader缓存中取出一个带有position和color顶点属性的shader,而后传给HelloWorld这个Layer.若是你是第一次接触OpenGL ES,看到这句话确定没法理解,不过没有关系,后面的文章咱们逐步讲清楚。若是你等不及,也能够先看我在文章最后推荐的连接。
接下来,运行一下程序.恭喜你,你的第一个漂亮的三角形完成啦,还算简单吧:)
本教程源代码下载,请认准tutorial1分支。
Git仓库地址: https://git.oschina.net/zilongshanren/Cocos2D-X-OpenGL-ES-2.0
为了保持第一篇文章的简单性,我只在画三角形的代码里面给了一些注释,由于我并不想一开始就涉及到OpenGL底层的一些细节,并且有些内容我一时半会儿也很难说清楚。因此,我会在文章的最后给出一些参考连接,强烈推荐你们在看完本文后,有时间就多看一看这些连接,相信对理解上面的代码有帮助。下一篇文章中,我将给你们介绍如何编写本身的shader,包括vertex attribute, uniform,vertex shader, fragment shader等内容。若是您对本文有什么建议或者意义,欢迎在下方评论。
关于参考连接:全部的推荐阅读都是我精心挑选的,部份内容我本身看过,另一些我也正在计划看。若是你们有好的资料,欢迎推荐给我。
关于评论:请不要找我要电子书,全部的电子书均可以经过google找到。
另外,我推荐的资料大部分都是英文版,若是对英文不是很感冒的同窗,能够看翻译的版本。
网站:
http://http.developer.nvidia.com/CgTutorial/cg_tutorial_chapter01.html
http://duriansoftware.com/joe/An-intro-to-modern-OpenGL.-Chapter-1:-The-Graphics-Pipeline.html
视频:
https://www.youtube.com/watch?v=-tonZsbHty8&index=26&list=PLRwVmtr-pp06qT6ckboaOhnm9FxmzHpbY
书籍: