opengl纹理部分全面解析

一.纹理映射

简单说纹理映射就是将一张或者多张纹理粘贴在mesh的表面,为mesh进行着色的过程,就是纹理映射。
我们在使用opengl进行纹理映射的时候,通常的步骤是:
1.创建纹理对象,加载纹素数据。
2.为mesh上的每个点增加一个uv坐标也就是纹理坐标。
3.将纹理对象与纹理单元进行绑定,即将纹理对象与着色器中纹理采样器相关联。
4.在着色器中直接使用纹理采样器来得到特定纹理坐标出的颜色值。

二.各种纹理类型

经常用到的纹理类型包括1D,2D,3D,还有各种array类型,以及立方体纹理等,这些类型可以很容易
的在opengl的宏定义中查到,这里不再详细说了。

三.创建和初始化纹理

void glGenTextures(GLsizei n, GLuint *textures);
这个函数产生n个纹理对象的名称,说白了就是在系统中查找n个未被使用的整数,来作为n个对象的保
留值,可以用这个保留值来操作这个对象。
void glBindTexture(GLenum target, GLuint texture);
后面这个texture参数,就是上面那个函数产生的保保留值,这里就是真正创建一个纹理对象,然后将
这个纹理对象与这个保留值进行关联,这之后就可以真正通过这个GLuint值来处理该对象。
当然如果texture之前已经绑定过一个纹理对象的话,这个函数的意思就是激活已绑定的纹理对象。
glActiveTexture(GLenum texture);
这个函数是激活纹理单元,我们可以通过此函数激活shader中的某个纹理单元,然后调用
glBindTexture函数,这个样就可以将纹理对象与一个纹理单元进行绑定。
纹理单元其实是应用程序中的纹理对象与shader中的纹理采样器进行关联的媒介,我们接下来可以通过
glUniform1i(GLuint location, int val);
函数来将shader中的纹理采样器与纹理单元进行绑定,这样其实是完成了纹理对象与shader中纹理采样
器的绑定,一般的代码如下:

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, _texture);
GLuint textLoc = glGetUniformLocation(prog, “texture”);
glUniform1i(textLoc, 0);

这样_texture纹理对象中的数据就可以在shader中通名字为texture的sampler得到,并在shader中检索纹素值。

四.代理纹理

代理纹理主要用来测试一些限制是否被当前opengl支持时使用。
例如,现在我们有2G的纹理数据,想知道当前opengl是否支持这么大的纹理数据规模,可以使用代理纹
来进行测试。对于有些opengl版本中可用纹理空间只有1G,那么这个测试就会失败,也就是说当前opengl
不支持这么大的纹理空间,我们就要想别的办法来实现该功能了。
使用代理纹理,通常就是在代理纹理对象上请求这样的纹理分配,OpenGL设备实现可以告诉你在对应的纹
理目标上请求能否成功,或者是否注定会失败。

五.设置纹理数据

设置纹理数据的方法主要包括三种大方法:
glTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei border, GLenum format, GLenum type, const void *data);
1.将内存中的数据赋给纹理对象
这种方法最长用,比如我们将一涨纹理读入内存,然后将这块内存中的纹理数据赋给纹理对象
glTexImage2D、glTexStorage2D+glTexSubImage2D 等类函数就可以将将内存中的数据绑定到纹理对象中
并在shader中进行使用。
2.在Pixel Unpack缓存中读取数据
我们可以先将纹理数据绑定到GL_PIXEL_UNPACK_BUFFER,然后使用glTexImage2D、glTexStorage2D+glTexSubImage2D
等类函数来从缓存中读取数据,这两种方式的主要差别就是最后一个参数data表示的意义,在方法1中,最后一个
参数表示内存中的实际地址,而在方法2中最后一个参数表示的是数据在Pixel Unpack缓存中的偏移。
3.从帧缓存拷贝数据
我们可以将帧缓存的福分或者全部数据读进纹理对象,并在随后用在渲染中。
glCopyTexImage2D(GLenum target, GLint level, GLint internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
该函数可以从当前的缓存中拷贝数据并绑定到激活的纹理单元target的纹理像素。

这里解释下上面这些函数中internalFormat和format以及type的含义。
internalFormat指出opengl内部存储纹理数据的格式。
format指出未绑定的本地纹理数据的格式,然后type指定了数据类型,也就是format和type共同指定了未绑定数据的
格式和数据类型。

六.纹理数据布局

设置纹理数据的时候我们可以决定读入的数据如何进行布局,而这与从内存中还是存Pixel Unpack缓存中读取没有关系,
个可以使用glPixelStorei函数来实现。
比如想实现字节反转,可以将GL_UNPACK_SWAP_BYTES设置为GL_TRUE,即glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
这样在读取数据到纹理对象的时候,字节会进行反转,如下
原本数据为byte0 | byte1 然后读入到纹理对象中就会变成 byte1 | byte0,这里的详细例子可以查看红宝书第八版217页。

本文遵从CC3.0协议转载请注明:转自凌风技术站

本文标题:opengl纹理部分全面解析

本文链接地址:http://www.iaccepted.net/graphics/13.html

相关文章



发表评论

电子邮件地址不会被公开。 必填项已用*标注