iOS-----openGL--openGL ES iOS 入门篇2--->绘制一个多边形

上一篇我们学习了如何搭建IOS下openGL的开发环境,接下来我们来学习如何绘制一个多边形。

在2.0之前,es的渲染采用的是固定管线,何为固定管线,就是一套固定的模板流程,局部坐标变换 -> 世界坐标变换 ->观察坐标变换->背面消除->光照->裁剪->投影->视口计算->光栅化,程序员只需要调用固定的api修改一些配置参数就可以完成整个渲染流程了。而到了2.0,固定管线改成了可编程管线,我们对整个渲染流程可以再编程,没有固定的api给你调用,一切都依靠shader来完成。那么什么是shader呢:

Shader分为顶点着色器(Vertex Shader)和片段着色器(Fragment Shader)。其中Vertex Shader主要负责顶点的几何关系等的运算,Pixel Shader主要负责片源颜色等的计算。

我们使用的是openGLES2.0。因此必然会用到shader,shader使用OpenGL着色语言(GLSL―OpenGL Shading Language)编写,在这里就不仔细介绍。

首先,设置好缓存

 GLuint _renderBuffer;
 GLuint _frameBuffer;

  glGenRenderbuffers(1, &_renderBuffer);
  glBindRenderbuffer(GL_RENDERBUFFER, _renderBuffer);
  [_eaglContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:  (id<EAGLDrawable>)self.layer];

  glGenFramebuffers(1, &_frameBuffer);
  glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);
  glFramebufferRenderbuffer(GL_FRAMEBUFFER,
                              GL_COLOR_ATTACHMENT0,
                              GL_RENDERBUFFER,
                              _renderBuffer);
    

在设置缓存之前,最好先清理一次,避免重复设置

if (_frameBuffer) {
        glDeleteFramebuffers(1, &_frameBuffer);
        _frameBuffer = 0;
    }

    if (_renderBuffer) {
        glDeleteRenderbuffers(1, &_renderBuffer);
        _renderBuffer = 0;
    }

设置好缓存之后开始编译着色器,基本上编译着色器的步骤都是固定,图像处理,滤镜实现基本都是通过着色器来完成。以下是编译着色器的代码。

GLuint _program;
GLunit _positionSlot;
_program = [MTShaderOperations compileShaders:@"Vertex"
                                   shaderFragment:@"Fragment"];
 glUseProgram(_program);
  _positionSlot = glGetAttribLocation(_program, "Position");

glUseProgram(_program);

//绑定着色器中的参数

_positionSlot = glGetAttribLocation(_program, "Position");

+ (GLuint)compileShaders:(NSString *)shaderVertex shaderFragment:(NSString *)shaderFragment {
    // 1 vertex和fragment两个shader都要编译
    GLuint vertexShader = [MTShaderOperations compileShader:shaderVertex withType:GL_VERTEX_SHADER];
    GLuint fragmentShader = [MTShaderOperations compileShader:shaderFragment withType:GL_FRAGMENT_SHADER];

    // 2 连接vertex和fragment shader成一个完整的program
    GLuint _glProgram = glCreateProgram();
    glAttachShader(_glProgram, vertexShader);
    glAttachShader(_glProgram, fragmentShader);

    // link program
    glLinkProgram(_glProgram);

    // 3 check link status
    GLint linkSuccess;
    glGetProgramiv(_glProgram, GL_LINK_STATUS, &linkSuccess);
    if (linkSuccess == GL_FALSE) {
        GLchar messages[256];
        glGetProgramInfoLog(_glProgram, sizeof(messages), 0, &messages[0]);
        NSString *messageString = [NSString stringWithUTF8String:messages];
        NSLog(@"%@", messageString);
        exit(1);
    }
    return _glProgram;
}

+ (GLuint)compileShader:(NSString*)shaderName withType:(GLenum)shaderType {
    // 1 查找shader文件
    NSString* shaderPath = [[NSBundle mainBundle] pathForResource:shaderName ofType:@"glsl"];
    NSError* error;
    NSString* shaderString = [NSString stringWithContentsOfFile:shaderPath encoding:NSUTF8StringEncoding error:&error];
    if (!shaderString) {
        NSLog(@"Error loading shader: %@", error.localizedDescription);
        exit(1);
    }

    // 2 创建一个代表shader的OpenGL对象, 指定vertex或fragment shader
    GLuint shaderHandle = glCreateShader(shaderType);

    // 3 获取shader的source
    const char* shaderStringUTF8 = [shaderString UTF8String];
    int shaderStringLength = (int)[shaderString length];
    glShaderSource(shaderHandle, 1, &shaderStringUTF8, &shaderStringLength);

    // 4 编译shader
    glCompileShader(shaderHandle);

    // 5 查询shader对象的信息
    GLint compileSuccess;
    glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &compileSuccess);
    if (compileSuccess == GL_FALSE) {
        GLchar messages[256];
        glGetShaderInfoLog(shaderHandle, sizeof(messages), 0, &messages[0]);
        NSString *messageString = [NSString stringWithUTF8String:messages];
        NSLog(@"%@", messageString);
        exit(1);
    }

    return shaderHandle;
}

当然,要编译着色器,首先我们要写好着色器代码。绘制多边形的着色器代码十分简单,如果有不懂得童鞋可以参考OpenGL着色语言(GLSL―OpenGL Shading Language)

新建一个empty文件,然后将后缀改成glsh就可以开始写着色器代码了。

Vertex Shader代码如下:

attribute vec4 Position;

void main(void)
{
    gl_Position = Position;

}

Fragment Shader代码如下

void main(void)
{

    gl_FragColor = vec4(0,1,1, 1.0);
}

编译好着色器之后,我们就可以开始绘制图形了,在这里要注意的是在openGLES中只能画三角形,所有的图形都是由三角形组成的。

还有,在定义顶点时要注意openGL中的坐标系不同于UIKit。

首先定义顶点数组

 const GLfloat vertices[] = {
        -1, -1, 0,   //左下
        1,  -1, 0,   //右下
        -1, 1,  0,   //左上
        1,  1,  0 }; //右上

绘制图形

//传入顶点参数

glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, 0, vertices);

glEnableVertexAttribArray(_positionSlot);

//绘制多边形

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

在上面我们画出了多边形,这个多边形是顶点数组按照顺序画出所有的三角形,在不少情况下,并不能符合我们的要求。我们可以试着将上面最后一句改成

glDrawArrays(GL_TRIANGLE_STRIP, 1, 4);

得到的图像如下

由于openGL只能画三角形,因此在顶点数组中,顶点按照怎样的顺序链接十分重要。因此在openGLES中提供了另一个方法。

//定义索引数组 const GLubyte indices[] = {
        0,1,2,
        1,2,3
    };

//根据索引数组的顺序画出多边形

glDrawElements(GL_TRIANGLES, sizeof(indices)/sizeof(indices[0]), GL_UNSIGNED_BYTE, indices);


这样我们就画出了一个四边形,其他多边形也是一样的步骤。

下一篇章我们会讲如何传入一个纹理,敬请期待。

时间: 2024-10-10 00:28:30

iOS-----openGL--openGL ES iOS 入门篇2--->绘制一个多边形的相关文章

Three.js 第一篇:绘制一个静态的3D球体

第一篇就画一个球体吧 首先我们知道Three.js其实是一个3D的JS引擎,其中的强大之处就在于这个JS框架并不是依托于JQUERY来写的.那么,我们在写这一篇绘制3D球体的文章的时候,应该注意哪些地方呢?下面我就来一一列举 1.场景. 场景是什么,说得简单一点,场景就是一个canvas ,我们就是要在Canvas上面实现3D效果的画面而已.场景和容器,相机是息息相关的,我们就拿拍戏来说,假如我们需要演一个古装剧的撕逼场景,那么,我们需要的道具其中之一就是一个相机. 2.容器 就是承载球体的DI

iOS-----openGL--openGL ES iOS 入门篇3---&gt; 纹理贴图(texture)

在这篇文章中,我们将学习如何在openGL中使用纹理贴图. penGL中纹理可以分为1D,2D和3D纹理,我们在绑定纹理对象的时候需要指定纹理的种类.由于本文将以一张图片为例,因此我们为我们的纹理对象绑定一个GL_TEXTURE_2D的纹理. 本文将分为两个部分,一部分是如何通过图片获取一个2D的纹理,另一部分是如何使用一个纹理. 在上一篇中,我们介绍了如何使用shader来绘制一个多边形,本文是基于上一篇的提高,我们也将继续使用shader,对于shader使用不熟的童鞋可以看上一篇. 首先我

[WebGL入门]六,顶点和多边形

注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中如果有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,如果翻译有误,欢迎大家指正. 可以在三维空间中描画的东西 要说在WebGL的世界里能够描画什么,其实任何东西都可以描画.而描画的最基本的东西就是下面几种. ?点 ?线段 ?三角形 虽然在OpenGL中提供了矩形的绘制,但是WebGL中基本上只能绘制上面的三种类型.和二维世界不同,比如像HTML中的img标签那样,简单的在画

iOS-----openGL--openGL ES iOS 入门篇---&gt;搭建openGL环境

OpenGL版本 iOS系统默认支持OpenGl ES1.0.ES2.0以及ES3.0 3个版本,三者之间并不是简单的版本升级,设计理念甚至完全不同,在开发OpenGL项目前,需要根据业务需求选择合适的版本.这方面的介绍不少,不再展开.在学习OpenGL代码的时候也需要知道它对应着哪个版本,在ES1中执行ES2代码是看不到任何效果的,你可以在初始化EAGLContext时指定ES版本号 _eaglContext = [[EAGLContext alloc] initWithAPI:kEAGLRe

iOS下OpenGL ES 3.0编程入门(一):构建Hello World环境

OpenGL ES简介: OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL三维图形 API 的子集,针对手机.PDA和游戏主机等嵌入式设备而设计.该API由Khronos集团定义推广,Khronos是一个图形软硬件行业协会,该协会主要关注图形和多媒体方面的开放标准. OpenGL ES 3.0主要新功能有: 1.渲染管线多重增强,实现先进视觉效果的加速,包括遮挡查询(Occlusion Query).变缓反馈(Transform Feedback)

iOS开发-OpenGL ES入门教程1

http://www.jianshu.com/p/750fde1d8b6a 这里是一篇新手教程,环境是Xcode7+OpenGL ES 2.0,目标写一个OpenGL ES的hello world.OpenGL ES系列教程在这里.OpenGL ES系列教程的代码地址 你的star和fork是我的源动力,你的意见能让我走得更远. 核心思路 通过GLKit,尽量简单地实现把一张图片绘制到屏幕. 效果展示 具体细节 1.新建OpenGL ES上下文 - (void)setupConfig { //新

[转载]ios入门篇 -hello Word(1)

温馨提示:,如果您使用移动终端阅读本篇文章,请连接wifi的情况下阅读,里面有大量图片,以免造成您不必要的损失. 潜水博客园很多年,闲来无事,聊一下自己的经历,语文不好(如有什么错别字,请您在下评论)望您谅解,没有上过什么学的. 博主介绍 2010 入园博客园学习.net,只是为后面做.net开发做铺垫. 2011-2012年 2年一直做.net开发(一直处于打杂状态),由于一直打杂状态,萌发转行做ios的状态. 2013-至今 做过4-5个ios方面的app(现阶段处于打杂状态).一直想做转行

ios入门篇 -hello Word(1)

温馨提示:,如果您使用移动终端阅读本篇文章,请连接wifi的情况下阅读,里面有大量图片,以免造成您不必要的损失. 潜水博客园很多年,闲来无事,聊一下自己的经历,语文不好(如有什么错别字,请您在下评论)望您谅解,没有上过什么学的. 博主介绍   2010 入园博客园学习.net,只是为后面做.net开发做铺垫.   2011-2012年 2年一直做.net开发(一直处于打杂状态),由于一直打杂状态,萌发转行做ios的状态.   2013-至今 做过4-5个ios方面的app(现阶段处于打杂状态).

Android学习笔记&mdash;&mdash;OpenGL ES的基本用法、绘制流程与着色器编译

首先声明下,本文为笔者学习<OpenGL ES应用开发实践指南(Android卷)>的笔记,涉及的代码均出自原书,如有需要,请到原书指定源码地址下载. 在Android.iOS等移动平台上,开发者可以使用跨平台应用编程接口创建二维或者三维图形,或进行图像处理和计算机视觉应用,结合两者将能构建丰富有趣的交互体验.前者称为OpenGL,后者称为OpenCV,不过本文主要介绍前者,OpenCV在后续文章中涉及.OpenGL应用于桌面系统的历史已经很长了,但考虑到移动平台的特点(计算能力.性能等),将