注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

熊猫正正的博客

熊猫正正的天空

 
 
 

日志

 
 

Cocos2D-X研究之OpenGL ES 2.0教程:你的第一个三角形(1)  

2014-08-12 10:45:22|  分类: ios游戏开发 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

前言

在本系列教程中,我会以当下最流行的2D引擎Cocos2D-X为基础,介绍OpenGL ES 2.0的一些基本用法。本系列教程的宗旨是OpenGL扫盲,让大家在使用Cocos2D-X过程中,知其然,更知其所以然。因为我自己的图形学水平有限,所以这些教程不会涉及非常底层的数学原理,同时也不会过多地提及OpenGL本身的一些细节知识。但是我会在每篇文章的最后给出一些参考链接,大家可以顺藤摸瓜,一举Get OpenGL这个新技能。

我第一次学习OpenGL是在2008年,但是那时候学得很烂,被各种矩阵变换搞得云里雾里。我于今年年初彻底重新学习OpenGL,目前来讲,应该算是入门了,至少矩阵变换是理解了,同时也会自己写一些简单的shader,可以进行OpenGL调试了。但是,我的学习之路才刚刚开始,我希望在我自己学习的过程,把有用的一些知识记录下来,方便自己和他人查阅。我个人觉得,OpenGL真的没有那么难,只要你用心,就一定可以学会。当然,好的学习方法和好的学习资料肯定是会使之事半功倍的,希望接下来我的这些博文能为大家带来些许帮助。

在第一篇文章正式开始前,我谈下我自己的入门心得体会吧,而《如何学习OpenGL》这是个更大的话题,等我OpenGL水平精进之后,我再单独写一篇文章来谈谈我的看法。

目前来说,我的体会是“三要”和“三不要”。

  • 要理解OpenGL渲染管线
  • 要理解OpenGL是个状态机
  • 要多动手实践。

当然还有最重要的“三不要”:

  • 不要每天去群里问怎样最快能学好OpenGL
  • 不要每天去看各种资料而不动手写一点代码
  • 不要出了问题到处问,尝试先自己解决,实在解决不了再问

正文

准备工作

首先,是创建一个新的工程(注意我这里使用的版本是3.1)。打开命令行工具,然后输入下列命令:

1
cocos new -l cpp

如果对于上述命令不了解的用户,请猛戳这里.

编译并运行成功,然后把HelloWorldScene.cpp里面的init函数修改成下面的样子:

1
2
3
4
5
6
7
8
9
10
11
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函数,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
class HelloWorld : public cocos2d::Layer
{
public:
    //其它函数省略
    virtual void visit(Renderer *renderer, const Mat4 &transform, bool transformUpdated) override;
        
    void onDraw();
private:
    CustomCommand _command;
 
    
};

然后我们实现这个visit函数:

1
2
3
4
5
6
7
8
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函数,它是整个绘制三角形的核心。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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,所以下面的调用会失败:

1
2
3
  auto glProgram = getGLProgram();
    glProgram->use();
    glProgram->setUniformsForBuiltins();

接下来,让我们在HelloWorldScene.cpp的init方法中加入下列代码:

1
    this->setGLProgram(GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_COLOR));

这个调用的含义是从Cocos2D-X的shader缓存中取出一个带有position和color顶点属性的shader,然后传给HelloWorld这个Layer.如果你是第一次接触OpenGL ES,看到这句话肯定无法理解,不过没有关系,后面的文章我们逐步讲清楚。如果你等不及,也可以先看我在文章最后推荐的链接。

接下来,运行一下程序.恭喜你,你的第一个漂亮的三角形完成啦,还算简单吧:)

本教程源代码下载。 Git仓库地址: https://git.oschina.net/zilongshanren/Cocos2D-X-OpenGL-ES-2.0

转自:http://www.cgzhw.com/?p=168
  评论这张
 
阅读(311)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017