OpenGL ES基础理论 (二) —— 几个重要函数及纹理

版本记录

版本号 时间
V1.0 2018.01.11

前言

OpenGL ES这种图形库的使用,由于底层C函数比较多,理论也更偏向于底层和硬件GPU,所以使用起来代码可能你都见过,顺序也知道改怎么做,但是还是多少会有点感觉不知道为什么这么做?具体有什么含义?接下来这几篇我们就一起来看一下OpenGL ES基础理论,一起学习一下相关的基础理论。感兴趣的可以看上面几篇文章。
1. OpenGL ES基础理论 (一) —— 缓存、帧缓存、上下文与坐标系等

OpenGL ES 在Cocoa Touch中的位置

下面我们就看一下OpenGL ES 在Cocoa Touch中的位置,如下图所示。

这里面简单的说下GLKView,它是 Cocoa Touch UIView 类的内建子类。GLKView 简化了通过用 Core Animation 层来自动创建并管理帧缓存和渲染缓存共享内存所需要做的工作。GLKView 相关的 GLKViewController实例是视图的委托并接收当视图需要重绘时的消息。


几个重要函数详细说明

1. GL_API void GL_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers);

glGenBuffers()函数的第一个参数用于指定要生成的缓存标识符的数量,第二个参数是一个指针,指向生成的标识符的内存保存位置。

2. GL_API void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);

glBindBuffer()的第一个参数是一个常量,用于指定要绑定哪一种类型的缓存。 OpenGL ES 对于glBindBuffer()的实现只支持两种类型的缓存,GL_ARRAY_ BUFFERGL_ELEMENT_ARRAY_BUFFER。GL_ARRAY_BUFFER 类型用于指定一个顶点属性数组,glBindBuffer() 的第二个参数是要绑定的缓存的标识符。

3. GL_API void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);

glBufferData()的第一个参数用于指定要更新当前上下文中所绑定的是哪一个缓 存。第二个参数指定要复制进这个缓存的字节的数量。第三个参数是要复制的字节的地 址。最后,第 4 个参数提示了缓存在未来的运算中可能将会被怎样使用。GL_STATIC_ DRAW 提示会告诉上下文,缓存中的内容适合复制到 GPU 控制的内存,因为很少对其 进行修改。这个信息可以帮助 OpenGL ES 优化内存使用。使用 GL_DYNAMIC_DRAW 作为提示会告诉上下文,缓存内的数据会频繁改变,同时提示 OpenGL ES 以不同的方 式来处理缓存的存储。

4. GL_API void GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);

glVertextAttribPointer()函数会告诉 OpenGL ES 顶点数据在哪里,以 及怎么解释为每个顶点保存的数据。在这个例子中,glVertexAttribPointer() 的第一个参数指示当前绑定的缓存包含每个顶点的位置信息。第二个参数指示每个位置有几个部 分。第三个参数告诉 OpenGL ES 每个部分都保存为一个浮点类型的值。第四个参数告诉 OpenGL ES 小数点固定数据是否可以被改变。第五个参数叫做“步幅”,它指定了每个顶点的保存需要多少个字节。换句话说, 步幅指定了 GPU 从一个顶点的内存开始位置转到下一个顶点的内存开始位置需要跳过 多少字节。sizeof(GLKVector3)指示在缓存中没有额外的字节,即顶点位置数据是密封的。在一个顶点缓存中保存除了每个顶点位置的 X、Y、Z 坐标之外的其他数据也是可能的。最后一个参数是 NULL,这告诉 OpenGL ES 可以从当前 绑定的顶点缓存的开始位置访问顶点数据。

在顶点数组缓存内存中的顶点数据的可能排列方式

5. GL_API void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);

通过调用 glDrawArrays() 来执行绘图。glDrawArrays() 的第一个参数 会告诉 GPU 怎么处理在绑定的顶点缓存内的顶点数据。glDrawArrays() 的第二个参数和第三个参数分别指定缓存内的需要渲染的第一个顶点的位置和需要渲染的顶点的数量。

6. GL_API void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params) __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_3_0);

获取和返回当前上下 文的帧缓存的像素颜色渲染缓存的尺寸。


纹理

纹理是一个用来保存图像的颜色元素值的 OpenGL ES 缓存。

在纹理的缓存中保存的颜色值可能要耗费很多的内 存。所有的嵌入式系统都为纹理设定了内存的最大尺寸 限制。所有的 iPhone 和 iPad Touch 版本都可以支持由 1024×1024像素的图像生成的纹理。iPad 和最新一代 iPhone、iPod Touch 所支持的尺寸甚至更大。

当用一个图像初始化一个纹理缓存之后,在这个图像中的每个像素变成了纹理中 的一个纹素(texel)。与像素类似,纹素保存颜色数据。像素和纹素之间的差别很微妙 : 像素通常表示计算机屏幕上的一个实际的颜色点,因此,像素通常被用来作为一个测量单位。与此相反,纹素存在于一个虚拟的没有尺寸的数学坐标系中。如下所示, 显示了 OpenGL ES 纹理坐标系中的一个纹理。

纹理坐标系有一个命名为 S 和 T 的 2D 轴。在一个纹理中无论有多少个纹素,纹理的尺寸永 远 是 在 S 轴 上 从 0.0 到 1.0, 在 T 轴 上 从 0.0 到 1.0。从一个 1 像素高 64 像素宽的图像初始化来的纹 理会沿着整个 T 轴有 1 纹素,沿着 S 轴有 64 纹素。

在每个顶点的 X、Y、Z 坐标被转换成视口坐标后,GPU 会设置转换生成的三角形 内的每个像素的颜色。转换几何形状数据为帧缓存中的颜色像素的渲染步骤叫做点阵化(rasterizing),每个颜色像素叫做片元(fragment)。当 OpenGL ES 没有使用纹理时, GPU 会根据包含该片元的对象的顶点的颜色来计算每个片元的颜色。当设置了使用纹理后,GPU 会根据在当前绑定的纹理缓存中的纹素来计算每个片元的颜色。

纹理映射到转换后的顶点

1. 纹理的取样模式

每个顶点的 U 和 V 坐标会附加到每个顶点在视口坐标中的最终位置。然后 GPU 会 根据计算出来的每个片元的 U、V 位置从绑定的纹理中选择纹素。这个选择过程叫做取样(Sampling)。取样会把纹理的 S 和 T 坐标系与每个渲染的三角形的顶点的 U、V 坐标匹配起来。具体如上图所示。在 S 和 T 坐标系中与 {0,0} 位置最近的纹素会被映射到 拥有 {0,0} 的 U、V 坐标的顶点所对应的片元上。每个随后的片元位置对应于一个沿着 S 和 T 轴的与该片元在 U、V 坐标中的位置等比例的位置。例如,一个 U、V 坐标为{0.5,0,5} 的片元会被当前绑定的纹理中最接近中间位置的纹素所着色。

渲染过程中的取样可能会导致纹理被拉伸、压缩,甚至翻转。

2. MIP贴图

MIP 贴图是与取样密切相关的。根据维基百科,MIP 代表拉丁短语 Multum In Parvo,意思是“放置很多东西的小空间”。回忆一下,内存存取是现代图形处理的薄弱 环节。当有多个纹素对应一个片元时,线性取样会导致 GPU 仅仅为了计算一个片元的 最终颜色而读取多个纹素的颜色值。MIP 贴图是一个为纹理存储多个细节级别的技术。 高细节的纹理会沿着 S 轴和 T 轴存储很多的纹素。低细节的纹理沿着每个轴存储很少的 纹素。最低细节的纹理只保存一个纹素。多个细节级别增加了在 S、T 轴上的纹素和每 个片元的 U、V 坐标之间有紧密的对应关系的可能性。当存在一个紧密的对应关系时, GPU 会减少取样纹素的数量,进而会减少内存访问的次数。

后记

未完,待续~~~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容