在这篇文章中,我们将学习如何在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(, , width, height);

  //绘制图片
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
void *imageData = malloc(width * height * );
CGContextRef context = CGBitmapContextCreate(imageData, width, height, , width * , colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmap    ByteOrder32Big);
CGContextTranslateCTM(context, , 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(, &textureID);
  glBindTexture(GL_TEXTURE_2D, textureID);  
  glTexImage2D(GL_TEXTURE_2D, , GL_RGBA, width, height, , GL_RGBA, GL_UNSIGNED_BYTE, imageData);
  //绑定纹理位置 
glBindTexture(GL_TEXTURE_2D, );
  //释放内存
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, );

在指定区域绘制纹理。

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

//纹理使用范围顶点
const GLfloat texCoords[] = {
, ,//左下
, ,//右下
, ,//左上
, ,//右上
};
glVertexAttribPointer(_textureCoordsSlot, , GL_FLOAT, GL_FALSE, , texCoords);
glEnableVertexAttribArray(_textureCoordsSlot); //绘图区域顶点
const GLfloat vertices[] = {
-, -, , //左下
, -, , //右下
-, , , //左上
, , }; //右上 glVertexAttribPointer(_positionSlot, , GL_FLOAT, GL_FALSE, , vertices);
glEnableVertexAttribArray(_positionSlot); const GLubyte indices[] = {
,,,
,,
}; glDrawElements(GL_TRIANGLES, sizeof(indices)/sizeof(indices[]), GL_UNSIGNED_BYTE, indices); [_context presentRenderbuffer:GL_RENDERBUFFER];

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

IOS 中openGL使用教程3(openGL ES 入门篇 | 纹理贴图(texture)使用)的更多相关文章

  1. android ndk调用OpenGL 实现纹理贴图Texture

    android ndk调用OpenGL 实现纹理贴图Texture 时间 2014-06-25 05:24:39  CSDN博客 原文  http://blog.csdn.net/chrisfxs/a ...

  2. IOS 中openGL使用教程2(openGL ES 入门篇 | 绘制一个多边形)

    在上一篇我们学习了如何搭建IOS下openGL的开发环境,接下来我们来学习如何绘制一个多边形. 在2.0之前,es的渲染采用的是固定管线,何为固定管线,就是一套固定的模板流程,局部坐标变换 -> ...

  3. (转)使用OpenGL显示图像(七)Android OpenGLES2.0——纹理贴图之显示图片

    转:http://blog.csdn.net/junzia/article/details/52842816 前面几篇博客,我们将了Android中利用OpenGL ES 2.0绘制各种形体,并在上一 ...

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

    在这篇文章中,我们将学习如何在openGL中使用纹理贴图. penGL中纹理可以分为1D,2D和3D纹理,我们在绑定纹理对象的时候需要指定纹理的种类.由于本文将以一张图片为例,因此我们为我们的纹理对象 ...

  5. OpenGL入门1.4:纹理/贴图Texture

    每一个小步骤的源码都放在了Github 的内容为插入注释,可以先跳过 前言 游戏玩家对Texture这个词应该不陌生,我们已经知道了怎么为每个顶点添加颜色来增加图形的细节,但,如果想让图形看起来更真实 ...

  6. animation-play-state 在 ios 中不生效的解决办法(JS篇)

    我们要实现动画的播放和暂停,animation-play-state 在安卓端可以使用,但是在 ios 中不起作用,这时可以使用 js 来实现相同效果. 原理 通过 js 获取当前元素的 transf ...

  7. IOS 中openGL使用教程1(openGL ES 入门篇 | 搭建openGL环境)

    OpenGL版本 iOS系统默认支持OpenGl ES1.0.ES2.0以及ES3.0 3个版本,三者之间并不是简单的版本升级,设计理念甚至完全不同,在开发OpenGL项目前,需要根据业务需求选择合适 ...

  8. IOS 中openGL使用教程4(openGL ES 入门篇 | 离屏渲染)

    通常情况下,我们使用openGL将渲染好的图片绘制到屏幕上,但有时候我们不想显示处理结果,这时候就需要使用离屏渲染了. 正常情况下,我们将屏幕,也就是一个CAEAGLLayer对象作为渲染目标,离屏渲 ...

  9. sql语句中出现笛卡尔乘积 SQL查询入门篇

    2014-12-29  凡尘工作室   阅 34985  转 95 本篇文章中,主要说明SQL中的各种连接以及使用范围,以及更进一步的解释关系代数法和关系演算法对在同一条查询的不同思路. 多表连接简介 ...

随机推荐

  1. 设置jdk的编码

    在环境变量中:  AVA_TOOL_OPTIONS-Dfile.encoding=utf-8 -Duser.language=en -Duser.country=US

  2. Eclipse动态web工程(Dynamic Web Project)添加jar文件的正确方法

    Eclipse中,创建了动态web工程之后,如果需要添加新的jar文件,有两种方法.第一种是配置工程的“build path”,第二种则是将jar文件放在工程目录下的“/WebContent/WEB- ...

  3. xmlstreaml xml过滤 格式化 报文的发送接收 struct2

    有时候把东西想的过于复杂了,还是思路不清晰啊. seervlet struct2配置过程

  4. string.join(iterable)

    str.join(iterable) Return a string which is concatenation the  of the strings in the iterable iterab ...

  5. 一般处理程序上传文件(html表单上传、aspx页面上传)

    html 表单上传文件        一般处理程序由于没有 apsx 页面的整个模型和控件的创建周期,而比较有效率.这里写一个用 html 表单进行文件上传的示例.        1. 表单元素选用 ...

  6. Window memcache 使用

    一.memcache配置 1. 下载memcache 32位系统 1.2.5版本:http://static.runoob.com/download/memcached-1.2.5-win32-bin ...

  7. Javascript模式(第二章基本技巧)------读书笔记

    本章主要帮助大家写出高质量的JS代码的方法,模式和习惯,例如:避免使用全局变量,使用单个的var变量声明,缓存for循环的长度变量length等 一.尽量避免使用全局变量 1 每一个js环境都有一个全 ...

  8. linux下重置mysql的root密码

    # /etc/init.d/mysql stop # mysqld_safe --user=mysql --skip-grant-tables --skip-networking & # my ...

  9. 【sql】之查询昨天的记录

    http://blog.csdn.net/cangchen/article/details/44978531

  10. mysql5.5 物理删除binlog文件导致的故障

    故障现象: 中午12点多,一套主从集群的主库因为没有配置大页内存,发布时导致OOM,MYSQL实例重启了,然后MHA发生了切换.切换过程正常.切换后需要把原master配置成新master的slave ...