OpenGL(ES)学习一:准备

学习代码地址
OpenGL(ES)学习一:准备
OpenGL(ES)学习二:绘制一个三角形

两年前看博客和OpenGL超级宝典开始入门,后来接触Unity开发,对3D图形有了比较直观的理解,特别感谢[Unity Shader入门精要
这本书,给了我很多明确的知识,像光照模型、法线贴图等都是在这才懂-_-。

然后就是到最近开始准备明确系统的学习下OpenGL的知识,主要跟随learnOpenGL学习。OpenGL的知识,要么很分散,要么是外国人写的看不懂的书,就像超级宝典,特别是刚开始的时候很多概念都没有建立。这个网站真的超级好,一步步开始。如果能跟着learnOpenGL是最好了,或者中文版learnOpenGL

准备写一系列的博客,把作为学习笔记,如果能帮助到其他学习者最好了。教学相长,当想着把有一个概念讲给别人是,会更加清晰、严谨的去确认这个概念。很多时候,一些知识在脑袋里就处于“是那么一回事”的状态,而写下来就是让这种理解更明确。

学习代码都在这个项目里,而且做了win/mac/iOS三个平台的测试。iOS上是测试OpenGL ES。

mac和win

1. 需要4个库:glfw, glew, soilglm.

  • glfw用来打开窗口、生成OpenGL context、接入键盘鼠标控制等。
  • glew提供对应各平台OpenGL统一的接口,不需要自己根据平台不同而再做处理
  • soil用来加载图片,用于纹理生成
  • glm提供了矩阵、向量等3D变量类型的定义和操作。glm只是头文件,和其他稍有不同。

安装:

1. 使用homebrew下载,除了soil,其他的都有,这个最方便。而soil可以用[stb_image.h](https://github.com/nothings/stb/blob/master/stb_image.h)代替。win上用chocolatey,只有glfw.
2. 到网站下载代码,除了glm,其他几个都要编译成静态库才能用,而且要用[cmake](https://cmake.org/download/),因为各个平台不一样。cmake使用官网下载桌面程序(glfw和glew),或者在终端使用cmake命令(soil)。cmake程序使用先点击Configure,然后点Generate,在目标目录生成对应的程序。mac上是xcode,win上是vs,然后运行项目,编译静态库。soil下载好后,进入soil根目录,运行make & make install得到静态库。
3. 或者使用我示例项目里编译好的包。
4. 把静态库和对应的头文件放到项目里。

2.初始配置

建好项目后,在main函数里开始编写。

  • 配置GLFW

    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE,     GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
    

    mac上加上:

    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

    然后创建窗口:

    GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", nullptr, nullptr);

    使用窗口构建当前的context:
    glfwMakeContextCurrent(window);

    设置OpenGL的视野大小,这个是渲染的内容的大小,这里选择和window一样大。

    int width,height;
    glfwGetFramebufferSize(window, &width, &height);
    glViewport(0, 0, width, height);
    
  • 初始化GLEW:

    glewExperimental = GLFW_TRUE;
    if (glewInit() != GLEW_OK) {
        std::cout<< "Failed to initilize GLEW" <<std::endl;
        return -1;
    }
    
  • 循环调用渲染命令

    while (!glfwWindowShouldClose(window)) {
            glfwPollEvents();
            
            //Here is render commands
            
            glfwSwapBuffers(window);
        }
    

    glfwPollEvents处理窗口事件,有了这句窗口才能响应用户才做。
    glfwSwapBuffers 是切换前后缓冲区,即有两个缓冲区存储图像,一个是当前显示的,另一个是当前写入的,所以写入后要切换,让刚写入的显示,然后在渲染另一个缓冲区。这样可以让显示和写入同时进行,加快速度。

3.简单测试

在渲染命令位置加上:

glClearColor(1.0f, 1.0f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);

glClearColor设置清除后的颜色,glClear对响应缓冲区进行清除,这里只清除颜色,使用GL_COLOR_BUFFER_BIT。

如果没问题,运行后,窗口填充为刚设置的颜色,即淡黄色。

iOS

iOS上和电脑上比较不同,不需要第三方库管理窗口,而且Apple本身也有一些OpenGL ES上的封装。主要依据Drawing to Other Rendering Destinations这一篇来处理。

  1. 首先iOS上可以使用GLKit,这个是对OpenGL ES封装后的工具库,而为了学习,就不使用这个,而是自己搭建环境。
  2. 根据上面的文档,主要就是建立自己的Framebuffer,它包含了一帧画面需要的颜色、深度和模板测试数据这些信息。我们使用绘制命令,把数据输出到Framebuffer里,然后framebuffer由一个和它贡献数据的CAEAGLLayer,由这个layer负责显示。
所以根据文档进行操作:
  1. 需要一个用来显示的view,新建一个UIView的子类用来封装我们的OpenGL ES绘制操作。@interface TFGLView : UIView,然后为了让它能呈现绘制的内容,把它的layer修改成CAEAGLLayer。

+(Class)layerClass{
return [CAEAGLLayer class];
}

2. 初始化EAGLContext

    `_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];`
这里使用OpenGL ES3,所以头文件导入为
`#import <OpenGLES/ES3/gl.h>`.

    然后把这个context设为当前context:
    `[EAGLContext setCurrentContext:_context]`
    
3. 初始化framebuffer
    
    ```
    glGenBuffers(1, &_frameBuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);
    ```
    `glGenxxx`类型的函数很多,都是用来生成某个东西的,而拿到的一半都是int类型,也就是一个标志而已。比如这里生成一个framebuffer,你不会拿到一个对象,甚至内存地址都没有。_frameBuffer是`GLuint`类型??梢园阉强醋鲆桓鰅d,我猜这样都是为了性能处理。写多了面向对象的程序,会对这样的状况稍有不适。
    
    `glBindxxx`也是常见类型,用来表示下面的操作都是针对绑定的对象的。比如这里,下面使用`GL_FRAMEBUFFER`的地方,都是对_frameBuffer的操作,知道你再次绑定了其他对象。

4. 构建colorbuffer,并把它附加到framebuffer上
 

glGenRenderbuffers(1, &_colorBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, _colorBuffer);
[_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:_renderLayer];
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _colorBuffer);

前两句和framebuffer一样,先生成,然后绑定。第三句,给colorbuffer生成存储空间,这里使用了`_context`的方法,就是通过这里实现colorbuffer 和 _renderLayer的内存共享,所以之后_renderLayer可以显示colorbuffer的内容。

   注意这里使用了GL_RENDERBUFFER,而不是 _colorBuffer,这就是glBindRenderbuffer绑定的作用.
   
5. 设置OpenGL ES视野大小位置,即渲染的图像在layer中的位置和大小

   ```
   GLint width,height;
   glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width);
   glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height);
   
   glViewport(0, 0, width, height);
   ```
   同样使用glViewport函数。
   
5. 检测一下framebuffer的状态,如果没问题就可以开始绘制了

   ```
       GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER) ;
   if(status != GL_FRAMEBUFFER_COMPLETE) {
       NSLog(@"failed to make complete framebuffer object %x", status);
   }
   ```

####简单绘制

glBindFramebuffer(GL_FRAMEBUFFER, self.frameBuffer);
glClearColor(1.0f, 1.0f, 0.5f, 1.0f);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

glBindFramebuffer,保证这次渲染的目表是我们构建的framebuffer.
glClearColor设置清除后颜色,glClear清除缓冲区,GL_DEPTH_BUFFER_BIT是深度缓冲区,GL_COLOR_BUFFER_BIT是颜色缓冲区。如果不清除,那么上一次绘制的内容会保留,导致和这次绘制的内容叠加在一起。

然后把渲染结果提交显示:

glBindRenderbuffer(GL_RENDERBUFFER, self.colorBuffer);
[self.context presentRenderbuffer:GL_RENDERBUFFER];

把自定义的view添加到界面上,查看结果,如果显示设置的颜色,就ok了。
最后编辑于
?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,172评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,346评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事?!?“怎么了?”我有些...
    开封第一讲书人阅读 159,788评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,299评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,409评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,467评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,476评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,262评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,699评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,994评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,167评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,827评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,499评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,149评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,387评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,028评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,055评论 2 352

推荐阅读更多精彩内容