您的位置:首页 > 运维架构

OpenGLES 1.1教程(四)-纹理映射

2012-10-12 10:40 375 查看
http://www.helmsmansoft.com/index.php/archives/1536

继续哈,从前面的几篇文章里,可以在三维空间里绘制出一个z轴为0的平面图形,这样绘制出来的东西看起来没什么意思,所以本课来介绍下“纹理映射”,这是一个将图像(纹理)应用到原始图像或图形的过程。它的基本概念:对每个定义多边形中的一个顶点,还得提供一个顶点来定义纹理中的一个点。然后将此信息提供给OpenGL ES ,OpenGL ES执行一系列复杂的工作以使纹理和多边形匹配,并在多边形内将纹理渲染出来。
纹理坐标:用于在纹理内部确定位置。范围为0到1.
本课继续使用前面课程所建立的模板,如果您还没有下载此模板,可以在本站查看前几篇文章并下载模板。
言归正传,继续我们的课程风格,用代码说事,在RenderView.h里添加属性

GLuint textures[1];


在RenderView.m文件里添加如下代码:

//添加下面的方法
//载入纹理
- (void)loadTexture
{
CGImageRef textureImage = [UIImage imageNamed:@"texture.png"].CGImage;//通过CGImage获取被UIImage加载的底层位图图数据,存储在CGImageRef结构体中
if(!textureImage){  //判断是否加载成功
NSLog(@"Load the Image failed!");
return;
}
 
NSInteger textImageWidth = CGImageGetWidth(textureImage); //获取图片数据 宽度
NSInteger textImageHeight = CGImageGetHeight(textureImage);  //获取图片数据 高度
 
GLubyte *imageData = (GLubyte *)malloc(textImageWidth*textImageHeight*4); //分配textImageWidth*textImageHeight*4字节空间,并返回指向这块内存的指针,存储在GLubyte中
 
CGContextRef textureContext = CGBitmapContextCreate(imageData, textImageWidth, textImageHeight, 8, textImageWidth*4, CGImageGetColorSpace(textureImage), kCGImageAlphaPremultipliedLast);  //创建位图语境,
 
CGContextDrawImage(textureContext, CGRectMake(0.0, 0.0, (float)textImageWidth, (float)textImageHeight), textureImage); ///* Draw `image' in the rectangular area specified by `rect' in the context`c'. The image is scaled, if necessary, to fit into `rect'. */
CGContextRelease(textureContext);  //释放创建的语境
 
glGenTextures(1, &textures[0]); //创建文理名称,这里是创建一个文理,也可以创建多个,第一个参数为文理个数
glBindTexture(GL_TEXTURE_2D, textures[0]); //绑定纹理,第一个参数为作用目标,在O盆GLES里必须使用GL_TEXTURE_2D,因为OpenGLES只支持这个,第二个为需要绑定的纹理名称,即上面创建的
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textImageWidth, textImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);//将图像数据加载到纹理中
free(imageData);//释放内存
 
/*下面两行为设置纹理相关参数,GL_LINEAR参数能呈现一个平滑的、消除了锯齿的外观*/
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);  //图像被缩小时GL_TEXTURE_MIN_FILTER,
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);  //图像被放大时GL_TEXTURE_MAG_FILTER
glEnable(GL_TEXTURE_2D); //开启2D纹理贴图功能
 
}


render方法修改如下:

//渲染方法
- (void)render
{
static GLfloat rotation = 0.0; //角度
static CGFloat spinnySquareVertices[12] = {
-0.5f, -0.5f, -1,
0.5f,  -0.5f, -1,
-0.5f,  0.5f, -1,
0.5f,   0.5f, -1,
};
 
//    static CGFloat spinnSquareColor[] = {
//
//        255,255,0,255,
//        0,255,255,255,
//        0,0,0,0,
//        255,0,255,255,
//
//    };
 
const GLshort square[] = {
0,0,
1,0,
0,1,
1,1
};
 
glClearColor(0.1f, 0.8f, 1.0f, 1.0f); //设置清屏颜色
glClear(GL_COLOR_BUFFER_BIT);  //清屏
glViewport(0, 0, backingWidth, backingHeight);  //设置视口
 
glLoadIdentity();  //清空当前矩阵,还原默认矩阵
glOrthof(-1.0f, 1.0f, -1.5f, 1.5f, -1.0f, 1.0f);  //正交模式下可视区域
glColor4f(1.0, 1.0, 1.0, 1.0);  //绘制的颜色
glVertexPointer(3, GL_FLOAT, 0, spinnySquareVertices); //确定使用的顶点坐标数列的位置和尺寸
glEnableClientState(GL_VERTEX_ARRAY);  //启动独立的客户端功能,告诉OpenGL将会使用一个由glVertexPointer定义的定点数组
//    glColorPointer(4, GL_FLOAT, 0, spinnSquareColor);
//    glEnableClientState(GL_COLOR_ARRAY);
 
glTexCoordPointer(2, GL_SHORT, 0, square); //new //纹理坐标.参数含义跟以上的方法大相迳庭
glEnableClientState(GL_TEXTURE_COORD_ARRAY); //new
//    glShadeModel(GL_FLOAT);
glRotatef(rotation, 0.0, 0.0, 1.0);  //旋转
 
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); //进行连续不间断的渲染,在渲染缓冲区有了一个准备好的要渲染的图像
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
rotation += 0.5;
[_context presentRenderbuffer:GL_RENDERBUFFER_OES]; //将渲染缓冲区的内容呈现到屏幕上
 
}


render内的注释为new的是新添加的代码。
下面来具体解释下上面所用到的方法:
上面很多都加了详细的注释,这里说下关于OpenGL ES纹理映射的一些相关内容:
图像大小:在OpenGL ES中所有纹理大小必须为2的幂,也就是说,图像的高度和宽度应该等于以下的值之一
2 4 8 16 32 64 128 256 512 1024
高度和宽度不必相同。PS:iPhone3G,iPhone 4和iPad都支持2048*2048的纹理尺寸
如果需要的图片不是以上的大小,需要使用程序进行处理,使其符合以上尺寸。
glTexImage2D这个方法的几个参数:
第一个参数:目标纹理,必须为GL_TEXTURE_2D

第二个参数:细节程度。0是基本图像水平。 n级为mipma中的第n个缩小的图像。必须大于等于0.

第三个参数:纹理中的颜色组件,必须和之后的颜色参数相同。

第四个参数:纹理图像的宽度

第五个参数:纹理图像的高度

第六个参数:边框的宽度,必须为0

第七个参数:像素数据的格式

第八个参数:像素数据中使用的数据类型

第九个参数:内存中指向图像数据的指针
此命令发出后,imageData实力变量中的图像数据将被加载到OpenGL ES并与当前绑定的纹理关联。
到此运行程序,界面效果如下:


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息