基于Cocos2d-x学习OpenGL ES 2.0系列——你的第一个三角形(1)
前言
在本系列教程中,我会以当下最流行的2D引擎Cocos2d-x为基础,介绍OpenGL ES 2.0的一些基本用法。本系列教程的宗旨是OpenGL扫盲,让大家在使用Cocos2d-x过程中,知其然,更知其所以然。本系列教程不会涉及非常底层的数学原理,同时也不会过多地提及OpenGL本身的一些细节知识。但是我会在每篇文章的最后给出一些参考链接,大家可以顺藤摸瓜,一举Get OpenGL这个新技能。
准备工作
首先,是创建一个新的工程, 编译并运行成功,然后把HelloWorldScene.cpp里面的init函数修改成下面的样子:
bool HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if ( !Layer::init() )
{
return false;
} return true;
}
此时,再编译运行之。你将会得到以下界面。
发送CustomCommand
由于Cocos2d-x 从3.0开始引入了一种新的渲染机制,所有的OpenGL渲染代码不再放到每一个node的draw函数里面,而是通过各种RenderCommand封装起来,然后添加到一个渲染队列里面去,最后在每一帧结束时把所有的这些命令都渲染出来。
首先,打开HelloWorldScene.h,添加一个onDraw函数,一个CustomCommand成员变量,并且重载Layer的visit函数,代码如下:
class HelloWorld : public cocos2d::Layer
{
public:
//其它函数省略
virtual void visit(Renderer *renderer, const Mat4 &transform, bool transformUpdated) override; void onDraw();
private:
CustomCommand _command; .........
.........
};
然后我们实现这个visit函数:
void HelloWorld::visit(Renderer *renderer, const Mat4 &transform, bool transformUpdated)
{
Layer::visit(renderer, transform, transformUpdated); _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函数,它是整个绘制三角形的核心。
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[] = { ,, //第一个点的坐标
size.width, , //第二个点的坐标
size.width / , size.height}; //第三个点的坐标
//指定每一个顶点的颜色,颜色值是RGBA格式的,取值范围是0-1
float color[] = { , ,, , //第一个点的颜色,绿色
,,, , //第二个点的颜色, 红色
, , , }; //第三个点的颜色, 蓝色
//激活名字为position和color的vertex attribute
GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POSITION | GL::VERTEX_ATTRIB_FLAG_COLOR);
//分别给position和color指定数据源
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, , GL_FLOAT, GL_FALSE, , vertercies);
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, , GL_FLOAT, GL_FALSE, , color);
//绘制三角形,所谓的draw call就是指这个函数调用
glDrawArrays(GL_TRIANGLES, , );
//通知cocos2d-x 的renderer,让它在合适的时候调用这些OpenGL命令
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(, );
//如果出错了,可以使用这个函数来获取出错信息
CHECK_GL_ERROR_DEBUG();
}
如果你现在直接运行程序,会crash。这是因为我们还没有指定Shader,所以下面的调用会失败:
auto glProgram = getGLProgram();
glProgram->use();
glProgram->setUniformsForBuiltins();
接下来,让我们在HelloWorldScene.cpp的init方法中加入下列代码:
this->setGLProgram(GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_COLOR));
这个调用的含义是从Cocos2d-x的shader缓存中取出一个带有position和color顶点属性的shader,然后传给HelloWorld这个Layer.如果你是第一次接触OpenGL ES,看到这句话肯定无法理解,不过没有关系,后面的文章我们逐步讲清楚。如果你等不及,也可以先看我在文章最后推荐的链接。
接下来,运行一下程序。恭喜你,你的第一个漂亮的三角形完成啦,还算简单吧。
结束语
为了保持第一篇文章的简单性,我只在画三角形的代码里面给了一些注释,因为我并不想一开始就涉及到OpenGL底层的一些细节,而且有些内容我一时半会儿也很难说清楚。所以,我会在文章的最后给出一些参考链接,强烈推荐大家在看完本文后,有时间就多看一看这些链接,相信对理解上面的代码有帮助。下一篇文章中,我将给大家介绍如何编写自己的shader,包括vertex attribute, uniform,vertex shader, fragment shader等内容。
【本系列转自】http://cn.cocos2d-x.org/tutorial/lists?id=79
推荐阅读
网站:
http://http.developer.nvidia.com/CgTutorial/cg_tutorial_chapter01.html
http://www.opengl-tutorial.org/
http://antongerdelan.net/opengl/index.html
http://www.arcsynthesis.org/gltut/
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
书籍:
OpenGL ES 2.0 Programming Guide
Real-Time Rendering, Third Edition
基于Cocos2d-x学习OpenGL ES 2.0系列——你的第一个三角形(1)的更多相关文章
- 基于Cocos2d-x学习OpenGL ES 2.0系列——你的第一个立方体(5)
在上篇文章中,我们介绍了VBO索引的使用,使用VBO索引可以有效地减少顶点个数,优化内存,提高程序效率. 本教程将带领大家一起走进3D--绘制一个立方体.其实画立方体本质上和画三角形没什么区别,所有的 ...
- 基于Cocos2d-x学习OpenGL ES 2.0系列——纹理贴图(6)
在上一篇文章中,我们介绍了如何绘制一个立方体,里面涉及的知识点有VBO(Vertex Buffer Object).IBO(Index Buffer Object)和MVP(Modile-View-P ...
- 基于Cocos2d-x学习OpenGL ES 2.0系列——使用VBO索引(4)
在上一篇文章中,我们介绍了uniform和模型-视图-投影变换,相信大家对于OpenGL ES 2.0应该有一点感觉了.在这篇文章中,我们不再画三角形了,改为画四边形.下篇教程,我们就可以画立方体了, ...
- 基于Cocos2d-x学习OpenGL ES 2.0系列——OpenGL ES渲染之Shader准备(7)
Cocos2d-x底层图形绘制是使用OpenGL ES协议的.OpenGL ES是什么呢? OpenGL ES(OpenGl for Embedded System)是OpenGL三维图形API的子集 ...
- 基于Cocos2d-x学习OpenGL ES 2.0系列——编写自己的shader(2)
在上篇文章中,我给大家介绍了如何在Cocos2d-x里面绘制一个三角形,当时我们使用的是Cocos2d-x引擎自带的shader和一些辅助函数.在本文中,我将演示一下如何编写自己的shader,同时, ...
- 基于Cocos2d-x学习OpenGL ES 2.0系列——OpenGL ES渲染之LayerColor(8)
在前面文章中讲述了Cocos2d-x引擎OpenGL渲染准备Shader方面,本文主要讲解使用LayerColor来讲述OpenGL的渲染过程. 1.LayerColor对象创建 添加LayerCol ...
- 基于Cocos2d-x学习OpenGL ES 2.0系列——初识MVP(3)
在上一篇文章中,我在介绍vertex shader的时候挖了一个坑:CC_MVPMatrix.它其实是一个uniform,每一个Cocos2d-x预定义的shader都包含有这个uniform,但是如 ...
- 基于Cocos2d-x学习OpenGL ES 2.0之多纹理
没想到原文出了那么多错别字,实在对不起观众了.介绍opengl es 2.0的不多.相信介绍基于Cocos2d-x学习OpenGL ES 2.0之多纹理的,我是独此一家吧.~~ 子龙山人出了一个系列: ...
- OpenGL ES 2.0 渲染管线 学习笔记
图中展示整个OpenGL ES 2.0可编程管线 图中Vertex Shader和Fragment Shader 是可编程管线: Vertex Array/Buffer objects 顶点数据来源, ...
随机推荐
- mybatis中如果存在参数不再实体中的是如何处理
<select id="queryMapByType" parameterType="int" resultType="my.geomap.VO ...
- Android——TextView属性XML详解
Android_TextView属性XML详解 博客分类: android 属性名称 描述 android:autoLink 设置是否当文本为URL链接/email/电话号码/map时 ...
- EMC现场测试-EFT、ESD、Surge和场辐射
EMC测试主要进行了4项: 1. ESD 采用静电枪测试,接触电压±6KV,检测了整个箱体和内部可见金属部分: 空气放电正负8KV,检测了箱体及内部金属部分(如板卡壳体),特别检测了220V电源插头及 ...
- nginx日志分析利器GoAccess(转)
面试的时候一定会被面到的问题是:给出web服务器的访问日志,请写一个脚本来统计访问前10的IP有哪些?访问前10的请求有哪些?当你领略过goaccess之后,你就明白,这些问题,除了考验你的脚本背诵记 ...
- MySQL下查询锁信息
SHOW PROCESSLIST;SHOW OPEN TABLES WHERE In_use > 0; #运行线程 SHOW GLOBAL STATUS LIKE 'Threads_runn ...
- EcmaScript对象克隆之谜
先谈谈深拷贝 如何在js中获得一个克隆对象,可以说是喜闻乐见的话题了.相信大家都了解引用类型与基本类型,也都知道有种叫做深拷贝的东西,传说深拷贝可以获得一个克隆对象!那么像我这样的萌新自然就去学习了一 ...
- Javascript 你不知道的事,好吧,是我不知道的事
NaN表示一个不能产生正常结果的运算结果.它不等于任何值,包括它自己.可以用isNaN(number)来检测. 同Java中的字符串一样,JS中的字符串是不可变的.也就是说一旦字符串被创建,就无法改变 ...
- 20个优秀的JavaScript 键盘事件处理库
键盘事件是 Web 开发中最常用的事件之一,通过对键盘事件的捕获和处理可以提高网站的易用性和交互体验.下面,我们向大家介绍收集的20款优秀的 JavaScript 键盘事件处理库,帮助开发人员轻松处理 ...
- thinkphp 自动跟新时间
看了很多文章和资料了,明白何为真传一句话了... 模板里: <input type="text" name="time" value="{:da ...
- 【转】Hibernate系列学习之(二) 多对一、一对一、一对多、多对多的配置方法
hihernate一对多关联映射(单向Classes----->Student) 一对多关联映射利用了多对一关联映射原理 多对一关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是多指向 ...