OpenGL纹理

1.创建n个纹理id

void glGenTexture(GLsizei n, GLuint* ids);

2.把指定纹理对象与当前启用的纹理单元以target的形式进行绑定

void glBindTexture(GLenum target, GLuint id);

targe t为 GL_TEXTURE_1D、GL_TEXTURE_2D、GL_TEXTURE_3D。。。
例如要把当前的 GL_TEXTURE_1D 设为1号纹理,则:

glBindTexture(GL_TEXTURE_1D, 1);

注意:一个纹理对象可以绑定到多个纹理单元,也就是说同样的纹理数据可以使用不同的采样器采样。

3.选择当前启用的纹理单元

void glActiveTexture(GLenum texture);

texture为GL_TEXTURE0,GL_TEXTURE1,GL_TEXTURE2。。。
默认为GL_TEXTURE0
当一个着色器需要使用多个纹理时(多重纹理)需要指定当前启动的纹理单元,然后进行绑定操作glBindTexture时就是把纹理对象绑定到当前纹理单元上。
《OpenGL编程指南(第8版)》p227–6.7.3使用多重纹理

相同的纹理可以绑定到不同的纹理单元,通过不同的采样器读取
一个纹理单元在同一时刻只能绑定一个纹理,Shader中一个Sampler也只能对应一个纹理单元

4.删除纹理对象,纹理id可以被重新使用

void glDeleteTexture(GLsizei n, const GLuint* textures);

5.接下来将纹理数据放入显存,有两种方法

(1) glTexStorage() + glTexSubImage()*************不可改变的存储

void glTexStorage1D (
GLenum  target, 
GLsizei levels,
GLenum  internalFormat, 
GLsizei width
);

先设置纹理在显存中的储存格式 internalFormat(内部格式)

void glTexSubImage1D (
GLenm target,
GLint   levels,
GLint   xoffset,
GLsizei width,
GLenum  format, 
GLenum  type, 
const void* data
);

然后用data中的数据去替换纹理存储位置的某一个区域
这里的format和type(外部格式)是data的格式,改格式是根据读进来的数据决定的

(2)glTexImage()*************可改变的纹理分配函数(缩放、格式变化等)

void glTexImage1D (   
GLenum target, 
GLint   levels, 
GLint   internalFormat, 
GLsizei width, 
GLsizei border, 
GLenum  format, 
GLenum  type, 
const void* data
);

注意:内部格式是纹理在显存中的格式,由我们自己指定;外部格式是数据本身的格式(内存中的格式),由数据决定。一般用无符号归一化的方式存储纹理,这是内存中存的是整数,传进Shader时归一化到[0.0,1.0]。浮点内部格式是真浮点格式,这种情况下,纹理可以储存-1.0到1.0以外的值哦!!
《OpenGL编程指南(第8版)》p202–6.3.1纹理格式
《OpenGL编程指南(第8版)》p202–6.5.1显式设置纹理数据

6.此外,还可以使用PixelUnpack缓存读入数据

《OpenGL编程指南(第8版)》p210–6.5.2使用Pixel Unpack缓存

7.或者从帧缓存中拷贝数据

《OpenGL编程指南(第8版)》p211–6.5.3从帧缓存中拷贝数据

8.设置采样方式,也有两种方法

(1)对采样器设置采样方式

glSamplerParameter(GLuint sampler,GLenum pname, Type param);

(2)直接对当前激活的纹理单元设置(其实是对纹理的默认的采样器设置)

glTexParameter(GLuint texture, GLenum pname, Type param);

大多时候我们并没有设置采样器,而直接使用默认的采样器,这个时候就对纹理单元进行设置。
pname可以选择为GL_TEXTURE_WRAP_S(横)、GL_TEXTURE_WRAP_T(竖)、GL_TEXTURE_WRAP_R(深度)

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);//边缘
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//插值方法
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

glTexParameter 的结尾是 i 时(glTexParameteri),后面的Type param就是整数
结尾是iv时,Type param就是个整数向量
结尾是fv时,Type param就是个浮点向量
例如,如果我们选择GL_CLAMP_TO_BORDER选项,我们还需要指定一个边缘的颜色:

float borderColor[] = { 1.0f, 1.0f, 0.0f, 1.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);

注意:
纹理坐标左下角是(0.0,0.0)。
“OpenGL要求y轴0.0坐标是在图片的底部的,但是图片的y轴0.0坐标通常在顶部。”
三维纹理看存放顺序。纹理是个数组,存放的第一个数深度纹理坐标为0.0。
例如,读三维纹理的时候我们按深度从小到大读到数组中去,那么纹理z坐标的0.0就是深度最小的值,1.0是深度最大的值

8.将纹理单元与Shader中的采样器绑定

glUseProgram(prog);

将纹理对象tex1绑定到纹理单元GL_TEXTURE0上

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex1);

获取Shader中采样器“tex1”的位置,并把它和纹理单元GL_TEXTURE0绑定

GLint tex1_uniform_loc = glGetUniformLocation(prog,"tex1");
glUnifom1i(tex1_uniform_loc , 0);

你可能感兴趣的:(OpenGL)