博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS-----openGL--openGL ES iOS 入门篇3---> 纹理贴图(texture)
阅读量:6327 次
发布时间:2019-06-22

本文共 4139 字,大约阅读时间需要 13 分钟。

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

 

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

转载于:https://www.cnblogs.com/LifeTechnologySupporter/p/6604618.html

你可能感兴趣的文章
unable to load selinux policy. machine is in enforcing
查看>>
2015年10月23日作业
查看>>
MySQL5.7 加强了root用户登录安全性
查看>>
CentOS 6.3_Nagios安装配置与登录
查看>>
加强型的记录集权限(数据集权限、约束表达式设置功能)实现方法界面参考...
查看>>
Linux 内存机制
查看>>
linux下定时任务
查看>>
SharePoint 2013 部署 Part 1
查看>>
DWGSee看图纸dwg文件阅读器免费下载地址
查看>>
grep
查看>>
我的友情链接
查看>>
单例模式学习
查看>>
解决httpd: Could not reliably determine the server's fully qualified domain name
查看>>
名词学习
查看>>
centos7安装部署keepalived
查看>>
Citrx XenDesktop 7 实施九 创建交付组,策略.测试.(完结)
查看>>
存储过程实例
查看>>
[20180819]关于父子游标问题(11g).txt
查看>>
经纬度正则表达式
查看>>
Nutch成功添加中文分词
查看>>