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

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

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

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

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

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

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

  3. OpenGL——OpenCV与SOIL读取图片进行纹理贴图

    使用OpenCV读取图片代码如下 img = imread(m_fileName); if (img.empty()) { fprintf(stderr, "Can not load ima ...

  4. opengl学习笔记(三):经过纹理贴图的棋盘

    opengl纹理贴图的步骤: 1:创建纹理对象,并为它指定一个纹理 2:确定纹理如何应用到每个像素上 3:启用纹理贴图功能 4:绘制场景,提供纹理坐标和几何图形坐标 注意:纹理坐标必须在RGBA模式下 ...

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

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

  6. IOS 中openGL使用教程3(openGL ES 入门篇 | 纹理贴图(texture)使用)

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

  7. iOS开发-OpenGL ES入门教程1

    http://www.jianshu.com/p/750fde1d8b6a 这里是一篇新手教程,环境是Xcode7+OpenGL ES 2.0,目标写一个OpenGL ES的hello world.O ...

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

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

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

    温馨提示:,如果您使用移动终端阅读本篇文章,请连接wifi的情况下阅读,里面有大量图片,以免造成您不必要的损失.   潜水博客园很多年,闲来无事,聊一下自己的经历,语文不好(如有什么错别字,请您在下评 ...

随机推荐

  1. UWP开发:存储容器设置&复合设置数据

    有时候为了将应用设置进行分类,需要创建新的容器进行存储应用设置的信息. 1,容器的创建:在一个根容器里嵌套一个新容器 1)首先获取根容器. 2)调用ApplicationDataContainer.C ...

  2. [机器视觉] SIFT特征-尺度不变特征理解

    SIFT特征-尺度不变特征理解 简介 SIFT,即尺度不变特征变换(Scale-invariant feature transform,SIFT),是用于图像处理领域的一种描述.这种描述具有尺度不变性 ...

  3. PSNR

    PSNR,峰值信噪比,通常用来评价一幅图像压缩后和原图像相比质量的好坏,当然,压缩后图像一定会比原图像质量差的,所以就用这样一个评价指标来规定标准了.PSNR越高,压缩后失真越小.这里主要定义了两个值 ...

  4. js判断是否为app

    var ua = navigator.userAgent; var isapp = ua.match("lenovomallapp") == null ? 0 : 1;

  5. Python -- 函数之推导式

    5.12 推导式 l = [] for i in range(1,11): l.append(i) print(l) # 用列表推导式 (一行搞定) l = [i for i in range(1,1 ...

  6. tcp 高性能服务, netty,mqtt

    1. io 线程不要有比较长的服务. 全部异步化. [1] netty 权威指南上只是说业务复杂时派发到业务线程池种. 共用的线程池最好都轻量. 多层线程池后, 下层的可以进行隔离. 这个是 mqtt ...

  7. ssh整合思想 Spring与Hibernate和Struts2的action整合 调用action添加数据库 使用HibernateTemplate的save(entity)方法 update delete get 等方法crud操作

    UserAction类代码: package com.swift.action; import com.opensymphony.xwork2.ActionSupport; import com.sw ...

  8. iOS开发遇到的坑之六--使用cocopods管理第三方库时,编译出现Library not found for -lPods问题的解决办法

    在项目中有时候会遇到Library not found for -lPods(这里的IPods指的是你具体的第三方库)的问题 出现这个错误的原因是:xcode在编译的时候找不到这个库,从而导致项目无法 ...

  9. java 会话跟踪技术

    1.session用来表示用户会话,session对象在服务端维护,一般tomcat设定session生命周期为30分钟,超时将失效,也可以主动设置无效: 2.cookie存放在客户端,可以分为内存c ...

  10. 洛谷 P3328 【[SDOI2015]音质检测】

    这题我做的好麻烦啊... 一开始想分块来着,后来发现可以直接线段树 首先考虑一个性质,我们如果有数列的相邻两项f[i]和 f[i+1]那么用这两项向后推k项其线性表示系数一定(表示为f[i+k]=a∗ ...