注册 登录
主题 : 西蒙iphone-OpenGL ES 教程-10
级别: 侠客

UID: 1030
精华: 1
发帖: 52
可可豆: 1420 CB
威望: 1420 点
在线时间: 476(时)
注册时间: 2008-10-14
最后登录: 2016-07-21
楼主 : 发表于: 2009-08-24 10:09    发自: Web Page
来源于 3D图形 分类

西蒙iphone-OpenGL ES 教程-10   

OpenGL ES 10 – 多重纹理,重复纹理,并结束书本时代

我的朋友昨晚留在我家,并且我们喝点啤酒一起聊天。这时候我告诉他我正在写一些教程。所有的时间都是我在说,他的脸上不断的出现这是什么什么的表情,我告诉他,所有人都在网上看到这些教程。他不赞成这个:把所有的东西都放在网上实在是太奇怪了。
我自己在想,现在已经不是书本的时代了,我们可以在网上看到许多好的教程,来帮助我们学习。是时候结束书本时代了。
(伟大的共享精神万岁!!!)

本教程需要使用的纹理在这里下载: Tutorial10Textures.zip

改变loadTexture[]
第一件需要做的是就是改变 loadTexture[]. 基本上,我们可以改变调用如下:

- (void)loadTexture:(NSString *)name intoLocation:(GLuint)location;

向前看。我们改变 loadTexture[] 函数让它知道加载纹理的名词和路径就可以加载纹理. 现在改变 loadTexture[] 函数如下:

- (void)loadTexture:(NSString *)name intoLocation:(GLuint)location {

    CGImageRef textureImage = [UIImage imageNamed:name].CGImage;

不要忘记删除 @”checkerplate.png” 取而带之的是我们的文件名. 删除 glGenTextures() 函数并且改变 glBindTexture() 函数如下:

glBindTexture(GL_TEXTURE_2D, location);

就是这样,现在这个方法更加的有用,我们将调用glGenTextures() 在我们的 initWithCoder[] 函数里。当我们要加载某个纹理的时候,我们就调用 loadTexture[] ,在本教程里,我们将加载6个纹理, 所以在 initWithCoder[] 里调用完 setupView, 我们增加如下的函数:

        [self setupView];
        glGenTextures(6, &textures[0]);
        [self loadTexture:@"bamboo.png" intoLocation:textures[0]];
        [self loadTexture:@"flowers.png" intoLocation:textures[1]];
        [self loadTexture:@"grass.png" intoLocation:textures[2]];
        [self loadTexture:@"lino.png" intoLocation:textures[3]];
        [self loadTexture:@"metal.png" intoLocation:textures[4]];
        [self loadTexture:@"schematic.png" intoLocation:textures[5]];

另外,切换到头文件,改变纹理如下:

GLuint textures[6];

获得渲染
好,回到drawView[]. 删除有关金字塔的所有东西。我们已经不需要再使用它了。删除我们使用的颜色。所以看起来就如下:

    // Our new drawing code goes here
    rota += 0.2;
    
    glPushMatrix();
    {
        glTranslatef(0.0, 0.0, -4.0);        // Change this line
        glRotatef(rota, 1.0, 1.0, 1.0);
        glVertexPointer(3, GL_FLOAT, 0, cubeVertices);
        glEnableClientState(GL_VERTEX_ARRAY);
        
        // Draw the front face
        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
        
        // Draw the top face
        glDrawArrays(GL_TRIANGLE_FAN, 4, 4);
        
        // Draw the rear face
        glDrawArrays(GL_TRIANGLE_FAN, 8, 4);
        
        // Draw the bottom face
        glDrawArrays(GL_TRIANGLE_FAN, 12, 4);
        
        // Draw the left face
        glDrawArrays(GL_TRIANGLE_FAN, 16, 4);
        
        // Draw the right face
        glDrawArrays(GL_TRIANGLE_FAN, 20, 4);
    }
    glPopMatrix();

你可以不需要使用 glPushMatrix() 和 glPopMatrix() .如果你想你的代码100%的优化,就可以删除它。

现在我们已经获得了一些改变,让我们第二次停下来,思考OpenGL的状态。

好了,记得刚才我们加载过纹理,我们可以使用 glBindTexture()来告诉OpenGL我们希望那个纹理工作。所以,再加载完6个纹理以后,OpenGL将默认使用最后一个加载的纹理,如果你点击 “Build and Go”, 你将看到一个只有单一纹理的立方体。

因为我们想每个面都有一个纹理,我们需要告诉OpenGL我们想使用那个纹理来绘制,在我们调用glDrawArrays()之前。所以,我们的纹理代码如下:

    glPushMatrix();
    {
        glTranslatef(0.0, 0.0, -4.0);
        glRotatef(rota, 1.0, 1.0, 1.0);
        glVertexPointer(3, GL_FLOAT, 0, cubeVertices);
        glEnableClientState(GL_VERTEX_ARRAY);
        
        // Draw the front face
        glBindTexture(GL_TEXTURE_2D, textures[0]);
        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
        
        // Draw the top face
        glBindTexture(GL_TEXTURE_2D, textures[1]);
        glDrawArrays(GL_TRIANGLE_FAN, 4, 4);
        
        // Draw the rear face
        glBindTexture(GL_TEXTURE_2D, textures[2]);
        glDrawArrays(GL_TRIANGLE_FAN, 8, 4);
        
        // Draw the bottom face
        glBindTexture(GL_TEXTURE_2D, textures[3]);
        glDrawArrays(GL_TRIANGLE_FAN, 12, 4);
        
        // Draw the left face
        glBindTexture(GL_TEXTURE_2D, textures[4]);
        glDrawArrays(GL_TRIANGLE_FAN, 16, 4);
        
        // Draw the right face
        glBindTexture(GL_TEXTURE_2D, textures[5]);
        glDrawArrays(GL_TRIANGLE_FAN, 20, 4);
    }
    glPopMatrix();

点击 “Build and Go”


回答一个问题,那些代码完成了如上的功能。

纹理包装
下一节就是我一直在说的重复和包装纹理。重复纹理只是简单的多次重复相同的纹理。这是非常有用的内容,用较小的纹理组成一面墙。(必须是要整齐的纹理)

我们要做的是绘制我们的立方体的一个面,使用一个纹理重复四次。我要用这个竹子纹理改变正面,你可以做你任意喜欢的一个面。

这非常容易,你还记得OpenGL是如何从图片中抽取像素去渲染对象的吗?它使用了纹理坐标数组,之前我都告诉你,使用0.0-1.0。如果我要使图像出现两次,我之要将1.0改变为2.0,重复的纹理就会出现了。


所以,在我们的纹理数组里,改变如下:

   const GLshort squareTextureCoords[] = {
        // Front face
        0, 2,       // top left
        0, 0,       // bottom left
        2, 0,       // bottom right
        2, 2,       // top right
        
        // Top face
        0, 1,       // top left
        0, 0,       // bottom left
        1, 0,       // bottom right
        1, 1,       // top right

点击 “Build and Go”:


我只是修改了前面,如果你喜欢,你可以把其他面都做修改。

这是OpenGL默认的纹理映射状态,当纹理坐标数组里的值大于1.0的时候。如果你想改变这个状态,你也可以调用 glTexParameterf().比如,你可以改变如下:

        // Draw the front face
    glBindTexture(GL_TEXTURE_2D, textures[0]);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

上面的代码,在加载纹理坐标中数组大于1以后,就会出现如下效果

  


纹理的边缘像素一直延伸到左上角。这就是GL_CLAMP_TO_EDGE.

让我快速解释这两行代码:

   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

我们调用了 glTexParameterf() 当我们加载纹理的时候设置纹理过滤。像一般的OpenGL函数,它具有“双重功能”。有三个参数,但是在OpenGL ES只有两个有效果。第一个参数一般使 GL_TEXTURE_2D ,OpenGL ES 只支持它。

第二个参数是告诉OpenGL什么“变量”是我们要改变的,一般来说,是 GL_TEXTURE_WRAP_x.

这第三个参数就是我们要设置的。

OpenGL通过设置 “变量” or “设置” GL_TEXTURE_WRAP_S t到GL_CLAMP_TO_EDGE, 我们告诉 OpenGL 不要重复纹理而是延伸s 坐标 (什么是 “s”, 后面会说). 我们也做了相同的t坐标,等下运行下模拟器,看看是什么样的。

这里设置的默认值是 GL_REPEAT.

s t 坐标?
不,不是玩笑。OpenGL在它的纹理中使用了s t 坐标系统。它确实存在,以避免混淆,因为你必须记住我们的纹理并不是真实存在于我们的3d世界,他们只是我们放置到3d世界的某些东西。所以,你可以认为s 是横向,t 是纵向.但你旋转它的时候,它是不是一样的使用?

原文的地址如下:

http://web.me.com/smaurice/AppleCoder/iPhone_OpenGL/Entries/2009/4/22_OpenGL_ES_10_-_Multiple_Textures%2C_Repeating_Textures%2C_and_The_End_of_the_Book_Era.html
清空我的评分动态本帖最近评分记录: 共可可豆条评分记录
gagaga 贡献值 +5 2008-09-19
隐藏评分记录
级别: 圣骑士

UID: 1168
精华: 0
发帖: 45
可可豆: 5710 CB
威望: 5710 点
在线时间: 5230(时)
注册时间: 2008-10-30
最后登录: 2016-10-18
沙发 : 发表于: 2009-08-24 10:16    发自: Web Page
开头的那段是原作者的,还是译者的感悟呢?
级别: 论坛版主

状态: 未签到 - [143天]
UID: 491
精华: 6
发帖: 1729
可可豆: 112154 CB
威望: 112802 点
在线时间: 8521(时)
注册时间: 2008-08-19
最后登录: 2017-06-11
板凳 : 发表于: 2009-08-24 10:18    发自: Web Page
没抢到沙发。。。。
CC8年生快 | I'm  Developer
------------------------------------------------------------
Η αγάπη ποτέ δεν αποτυγχάνει.
愛是永不止息。
Love never fails.

    --《圣经.新约》哥林多前书第13章
级别: 侠客

UID: 1030
精华: 1
发帖: 52
可可豆: 1420 CB
威望: 1420 点
在线时间: 476(时)
注册时间: 2008-10-14
最后登录: 2016-07-21
3 楼:  发表于: 2009-08-24 11:16    发自: Web Page
引用
引用第1楼青蛙小子于2009-08-24 10:16发表的  :
开头的那段是原作者的,还是译者的感悟呢?

是原作者的。。。()内是我的。。

这个教程的原作者的共享精神很强大啊,e文好的朋友帮我发个mail给他,表达我们来自中国的感谢。
级别: 侠客
UID: 5950
精华: 0
发帖: 10
可可豆: 1750 CB
威望: 1750 点
在线时间: 213(时)
注册时间: 2009-05-24
最后登录: 2016-03-25
4 楼:  发表于: 2009-08-24 16:05    发自: Web Page
这个不顶不成
级别: 侠客

UID: 1030
精华: 1
发帖: 52
可可豆: 1420 CB
威望: 1420 点
在线时间: 476(时)
注册时间: 2008-10-14
最后登录: 2016-07-21
5 楼:  发表于: 2009-08-25 14:48    发自: Web Page
为什么没有人跳出来给我加分啊。。
级别: 新手上路

UID: 9360
精华: 0
发帖: 16
可可豆: 160 CB
威望: 160 点
在线时间: 61(时)
注册时间: 2009-09-29
最后登录: 2014-01-23
6 楼:  发表于: 2010-03-25 11:52    发自: Web Page
这么好的教材这么辛苦的翻译  兄顶门 顶起来 非要gagaga送楼主ipad不可
级别: 侠客
UID: 16122
精华: 0
发帖: 80
可可豆: 900 CB
威望: 900 点
在线时间: 909(时)
注册时间: 2010-03-25
最后登录: 2015-01-27
7 楼:  发表于: 2010-03-25 11:57    发自: Web Page
蛋蛋 顶楼上的
级别: 圣骑士
UID: 13184
精华: 0
发帖: 577
可可豆: 2034 CB
威望: 2034 点
在线时间: 428(时)
注册时间: 2010-01-20
最后登录: 2014-08-03
8 楼:  发表于: 2010-04-16 15:33    发自: Web Page
This lesson is wonderful !
Never drop yourself in darkness.
级别: 新手上路
UID: 18962
精华: 0
发帖: 11
可可豆: 110 CB
威望: 110 点
在线时间: 25(时)
注册时间: 2010-05-05
最后登录: 2010-08-20
9 楼:  发表于: 2010-05-06 15:51    发自: Web Page
我顶,楼主太辛苦了。继续翻译,粉丝来瓜了
描述
快速回复

关注本帖(如果有新回复会站内信通知您)

验证问题:
苹果公司现任CEO是谁?2字 正确答案:库克

发帖、回帖都会得到可观的积分奖励。查看论坛积分规则

按"Ctrl+Enter"直接提交
    顶部