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

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并与当前绑定的纹理关联。

到此运行程序,界面效果如下:


你可能感兴趣的:(IOS,Opengl)