iOS-----openGL--openGL ES iOS 入门篇3---> 纹理贴图(texture)

在这篇文章中,我们将学习如何在openGL中使用纹理贴图。

penGL中纹理可以分为1D,2D和3D纹理,我们在绑定纹理对象的时候需要指定纹理的种类。由于本文将以一张图片为例,因此我们为我们的纹理对象绑定一个GL_TEXTURE_2D的纹理。

本文将分为两个部分,一部分是如何通过图片获取一个2D的纹理,另一部分是如何使用一个纹理。

上一篇中,我们介绍了如何使用shader来绘制一个多边形,本文是基于上一篇的提高,我们也将继续使用shader,对于shader使用不熟的童鞋可以看上一篇

首先我们来看看如何通过图片获取一张2D的纹理。

+ (GLuint)createTextureWithImage:(UIImage *)image{
  //转换为CGImage,获取图片基本参数
    CGImageRef cgImageRef = [image CGImage];
    GLuint width = (GLuint)CGImageGetWidth(cgImageRef);
    GLuint height = (GLuint)CGImageGetHeight(cgImageRef);
    CGRect rect = CGRectMake(0, 0, width, height);
  //绘制图片
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    void *imageData = malloc(width * height * 4);
    CGContextRef context = CGBitmapContextCreate(imageData, width, height, 8, width * 4, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmap    ByteOrder32Big);
    CGContextTranslateCTM(context, 0, height);
    CGContextScaleCTM(context, 1.0f, -1.0f);
    CGColorSpaceRelease(colorSpace);
    CGContextClearRect(context, rect);
    CGContextDrawImage(context, rect, cgImageRef);
 //纹理一些设置,可有可无
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
     //生成纹理   glEnable(GL_TEXTURE_2D);   GLuint textureID;   glGenTextures(1, &textureID);   glBindTexture(GL_TEXTURE_2D, textureID);     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
  //绑定纹理位置 
    glBindTexture(GL_TEXTURE_2D, 0);  //释放内存
    CGContextRelease(context);
    free(imageData);

    return textureID;
}

获取纹理之后,我们就要开始使用纹理了。

和之前绘制多边形的过程一样,我们要先把参数传入shader中。在绘制多边形时我们只需要传入各个顶点的位置,但为了使用纹理,我们需要把纹理传入shader,

此外,还要传入所使用的纹理的范围(使用纹理的哪一部分来映射)。

Vertex Shader代码如下:

attribute vec4 Position;
attribute vec2 TextureCoords;
varying vec2 TextureCoordsOut;

void main(void)
{//用来展现纹理的多边形顶点
    gl_Position = Position;//表示使用的纹理的范围的顶点,因为是2D纹理,所以用vec2类型
    TextureCoordsOut = TextureCoords;
}

Fragment Shader代码如下:

precision mediump float;

uniform sampler2D Texture;
varying vec2 TextureCoordsOut;

void main(void)
{//获取纹理的像素
    vec4 mask = texture2D(Texture, TextureCoordsOut);
    gl_FragColor = vec4(mask.rgb, 1.0);
}

注意:

attribute属性只能通过Vertex Shader传入,再传给Fragment Shader,而uniform属性可以直接传入Fragment Shader。

同理的,与绘制多边形的过程一样,我们要编译shader,生成一个glProgram。不同的是,这次我们要传入着色器程序的参数有三个

  GLuint fragmentShader = [self compileShader:@"MTShaderFragment"
                                       withType:GL_FRAGMENT_SHADER];
    _glProgram = glCreateProgram();
    glAttachShader(_glProgram, vertexShader);
    glAttachShader(_glProgram, fragmentShader);
    glLinkProgram(_glProgram);
    glUseProgram(_glProgram);

    _positionSlot = glGetAttribLocation(_glProgram, "Position");  //uniform类型的参数获取方式不同
    _textureSlot = glGetUniformLocation(_glProgram, "Texture");
    _textureCoordsSlot = glGetAttribLocation(_glProgram, "TextureCoords");

接下来就到了最后一步,将纹理“贴”到多边形上。

首先将纹理传入,激活索引为1的纹理。表示接下来的操作都是针对纹理1

glActiveTexture(GL_TEXTURE1);//载入纹理
glBindTexture(GL_TEXTURE_2D, _textureID);//为当前程序对象指定Uniform变量的值,参数1代表使用的新值(GL_TEXTURE1)
glUniform1i(_textureSlot, 1);

在指定区域绘制纹理。

注意:用于表示纹理范围时的坐标表示方式与UIKit和openGL的坐标都不同,范围从(0,0)左下到(1,1)右上。

//纹理使用范围顶点 const GLfloat texCoords[] = {
        0, 0,//左下
        1, 0,//右下
        0, 1,//左上
        1, 1,//右上
    };
    glVertexAttribPointer(_textureCoordsSlot, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
    glEnableVertexAttribArray(_textureCoordsSlot);

  //绘图区域顶点
    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);

    const GLubyte indices[] = {
        0,1,2,
        1,2,3
    };

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

    [_context presentRenderbuffer:GL_RENDERBUFFER];

下一篇我们会讲解如何进行一些动态的操作和简单滤镜,让手指划过的区域变成灰色。

时间: 2024-11-09 02:20:20

iOS-----openGL--openGL ES iOS 入门篇3---> 纹理贴图(texture)的相关文章

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-----openGL--openGL ES iOS 入门篇2--->绘制一个多边形

在上一篇我们学习了如何搭建IOS下openGL的开发环境,接下来我们来学习如何绘制一个多边形. 在2.0之前,es的渲染采用的是固定管线,何为固定管线,就是一套固定的模板流程,局部坐标变换 -> 世界坐标变换 ->观察坐标变换->背面消除->光照->裁剪->投影->视口计算->光栅化,程序员只需要调用固定的api修改一些配置参数就可以完成整个渲染流程了.而到了2.0,固定管线改成了可编程管线,我们对整个渲染流程可以再编程,没有固定的api给你调用,一切都依靠

[转载]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(现阶段处于打杂状态).

Opengl ES 1.x NDK实例开发之六:纹理贴图

开发框架介绍请參见:Opengl ES NDK实例开发之中的一个:搭建开发框架 本章在第三章(Opengl ES 1.x NDK实例开发之三:多边形的旋转)的基础上演示怎样使用纹理贴图,分别实现了三角形纹理贴图和正方形纹理贴图. [实例解说] OpenglES要求生成纹理的图片长宽为2的n次方.支持各种格式(BMP, GIF, JPEG, PNG...) 本例中使用的图片为png格式,尺寸为128*128 本例中,在上层GLJNIView.java中生成纹理.将纹理句柄传递给Native层进行绘

iOS 即时通讯,从入门到 “放弃”?

原文链接:http://www.jianshu.com/p/2dbb360886a8 本文会用实例的方式,将 iOS 各种 IM 的方案都简单的实现一遍.并且提供一些选型.实现细节以及优化的建议. —— 由宇朋Look分享 前言 本文会用实例的方式,将iOS各种IM的方案都简单的实现一遍.并且提供一些选型.实现细节以及优化的建议. 注:文中的所有的代码示例,在github中都有demo:iOS即时通讯,从入门到“放弃”?(demo)可以打开项目先预览效果,对照着进行阅读. 言归正传,首先我们来总

iOS开发之多线程技术——GCD篇

本篇将从四个方面对iOS开发中GCD的使用进行详尽的讲解: 一.什么是GCD 二.我们为什么要用GCD技术 三.在实际开发中如何使用GCD更好的实现我们的需求 一.Synchronous & Asynchronous 同步 & 异步 二.Serial Queues & Concurrent Queues 串行 & 并发 三.Global Queues全局队列 四.Main Queue主队列 五.同步的作用 六.dispatch_time延迟操作 七.线程安全(单例dispa

iOS开发之Auto Layout入门

随着iPhone6与iOS8的临近,适配的问题讲更加复杂,最近学习了一下Auto Layout的使用,与大家分享.  什么是Auto Layout? Auto Layout是iOS6发布后引入的一个全新的布局特性,其目的是弥补以往Autoresizing在布局方面的不足之处,以及未来面对更多尺寸适配时界面布局可以更好的适应. 为什么要用Auto Layout? Autolayout能解决不同屏幕(iPhone4,iPhone5,iPad...)之间的适配问题. 在iPhone4时代开发者只需要适

iOS开发——完整项目实战OC篇&百思不得姐第四天

iOS开发——完整项目实战OC篇&百思不得姐第四天 上午 一:自定义按钮使用九宫格布局 二:控件不能点击 三:获取用户点击了那个按钮 四:调整按钮内部控件的位置:主流->上下 五:不能直接使用self.navigationController中或者View中获取导航控制器 方法一: 方法二: 六:布局取整 1 // 总行数 2 3 // NSUInteger rows = sqaures.count / maxCols; 4 5 // if (sqaures.count % maxCols)