OpenGL3.3纹理(更新)

什么纹理

纹理贴图是将指定的部分纹理图象映射到每个图元上
纹理由纹素组成 包含颜色数据信息
取样:在片段着色器中将纹理坐标和纹理进行匹配就是取样 取样的结果 也就是取样取到的就是纹素
纹素:纹理中的一个像素 纹素通常包含一个颜色值 用于画屏幕上对应的一个像素
纹理坐标:(u,v)(0,1)
纹理存储空间:存储给定纹理中的所有纹素
纹理存储空间的属性:用来存储给定纹理中的所有纹素(以及所有mipmap层次中的纹素)的内存总量,他需要根据选定的内部格式和对应的分辨率来决定 那这么说应该就是存储空间的内存总量

怎么计算每个像素的坐标

假设我们要将三个像素的图片贴在三个像素的物体上
请添加图片描述

这样就完美契合
纹理是在光栅化之后 也就是此时我们的图形变成了一个个的格子 然后我们将图形转换到纹理空间 也就是由纹理坐标决定的 相应的纹理坐标空间中有很多纹素(纹理像素) 然后每一个像素会在纹理空间中获取到坐标值 例如上面图片

纹理对象:

管理着一片纹理空间 代表了一种可以构成完整纹理的图片形式 也可以看作一组图片的集合 每一张图片都可以独立访问 然后所有图片一起进行操作 每一张图片都是由一维,二维或三维纹素的数组构成 多张图片可以进行堆叠 就是将一张图片螺再另一张上面 因此构成了一个被称作mipmap的金字塔形式
数组纹理:由一维或二维图片切片组成的数组 数组中的每一个元素都称为一张切片

立方体映射:

是一种特殊形式的数组纹理 他只有6的倍数个切片 一张立方体映射纹理总是由6个面 立方体映射数组中总有多个立方体映射纹理组成

多重采样:

反锯齿的实现方案 要求每个纹素都记录多个独立的颜色数据 然后再渲染过程当中将这些颜色进行合并得到最终的输出结果 一张多重采样纹理的每个纹素都会有多个采样值 一般2~8个

纹理单元:

作用:将纹理绑定到OpenGL环境中
将纹理绑定到环境中 我们就可以在着色器中 通过采样器变量的方式去访问它
纹理单元应该是每个OpenGL环境都有的 属于环境而不属于纹理

代理纹理

作用:测试OpenGL具体实现的能力 检查是否存在一些特定的限制
在这里插入图片描述

使用纹理的步骤

创建一个纹理对象 glGenTextures
绑定纹理对象 glBindTexture
加载纹素数据
为顶点数据增加纹理坐标
如果要在着色器中使用纹理采样器 将他关联到纹理贴图
在着色器中通过纹理采样器获取纹素数据

纹理类型

在这里插入图片描述
简述几个书上提到的 :
GL_TEXTURE_RECTANGLE(二维长方形纹理)特殊的二维纹理类型 可以表达简单的长方形区域中的纹素集合 但是他不能有mipmap 也不能不够成数组类型 也不支持某些纹理封装的模式
GL_TEXTURE_BUFFER(缓存纹理) 表示任意一位的纹素数组 也没有mipmao且无法构成数组 缓存纹理的存在使得我们可以在任意着色器阶段访问诸如顶点数据这样的内容 而不需要将数据在重新复制到纹理图片中 缓存纹理的存储区域(通常是通过缓存对象来表达)

采样器

1.每个纹理对象都有内置的采样器 该采样器如果不绑定在采样单元上 就是对该纹理对象采样
2.带有纹理单元的采样器才能对纹理采样
3.采样对象需要绑定采样单元
4.
带有纹理单元信息的采样器变量可以读取纹理 纹理单元就是TEXTURE1这种
每个纹理对象中包含了一个默认内置的采样器对象 如果没有把采样器对象绑定到专门的采样器单元 那么该采样器对象将用来从相对应的纹理对象中读取数据

函数

(创建纹理对象)glCreateTextures(GLenum target, GLsizei n, GLuint *textures)

纹理对象在创建时就会指定纹理维度和纹理类型
返回n各当前没有使用的纹理对象名称 保存到textures数组中 textures中返回的名称不一定是一组连续的整数值 0是一个默认保留的纹理名称 永远不会由glCreateTextures返回

(删除纹理对象)glDeleteTextures(GLsizei n,const GLuint *textures)

删除n个纹理对象 他们的名字被保存在textures数组中 也就是删除textures中的纹理对象 释放后的纹理名称可以再次被使用来创建 例如由glCreateTextures再次分配
如果一个当前绑定到环境的纹理被删除 那么这个绑定点也会被删除(也就是他绑定的纹理单元就可以绑定给别人了) 相当于调用glBindTextureUnit()并且texture参数为0 如果试图删除不存在的纹理名称 或者为0的纹理名称 则命令会被忽略不产生错误

(判断该名称是否属于一个纹理对象)gllsTexture(GLuint texture)

如果texture是一个已经被创建的纹理的名称 且没有被删除 返回GL_TURE 如果texture是0 或者 非0但并不是纹理的名称 返回GL_FALSE

(一维)glTextureStorage1D(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width)

(分配二维纹理数据)glTextureStorage2D(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)

(三维)glTextureStorage3D(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)

这三个函数创建永久的纹理存储空间并且初始化(为什么是永久?)
一旦使用glTextureStorage分配了空间 这个空间是无法再次被定义的,但是纹理内容可以通过glTextureSubImage2D()来改变
纹理存储空间的属性:用来存储给定纹理中的所有纹素(以及所有mipmap层次中的纹素)的内存总量,他需要根据选定的内部格式和对应的分辨率来决定
一般一维数组纹理的分配需要使用glTextureStorage2D 以此类推 要上升一个维度 多出来的这个维度是用来存储设置数组大小的
立方体映射纹理可以被认为是二维数组纹理等价
texture是准备分配存储空间的纹理对象的名称
levels是分配给纹理的mipmap的层数 第0层是基础层 后续金字塔的每层都比之前的层数据要更少(没懂)
width, height, depth表示纹理基础层的宽度 高度 深度值
internalformat 指定纹理中的颜色组件。可选的值有GL_ALPHA,GL_RGB,GL_RGBA,GL_LUMINANCE, GL_LUMINANCE_ALPHA 等几种。
因为提高了一个维度 所以在一维数组纹理时 使用的是glTextureStorage2D 所以height就相当于一维数组纹理的纹理切片的数量 depth就是二维的切片数量 对于立方体映射数组 使用glTextureStorage3D 且设置depth为立方体映射表面的数量 在这里 depth应该设置为6的整数倍(为什么?)
一旦为纹理分配了存储空间 那么他就无法被重新分配或者释放 只有纹理自己被删除的时候也才会删除对应的存储空间 一旦使用该函数分配了空间 这个空间是无法再次被定义的 对于纹理的不变性而言 上述分配的存储空间属性是永久不变的 但是可以改变存储空间的内容 简单来说 存储空间的大小无法改变 内容可以改变

glBindTextureUnit(GLuint unit,GLuint texture)

如果绑定了一个已经创建的纹理对象 那么这个纹理对象在给定纹理单元unit上会被激活
如果设置绑定名称texture为0 那么OpenGL会删除当前激活的纹理单元上所有已经绑定的对象 也就是不绑定的纹理的状态

(多重采样型2D)glTextureStorage2DMultisample(GLuint texture,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height,GLboolean fixedsamplelocations)

(多重采样型3D)glTextureStorage3DMultisample(GLuint texture,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth ,GLboolean fixedsamplelocations)

glTextureSubImage1D(GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type,const boid *pixels)

glTextureSubImage2D(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type,const boid *pixels)

glTextureSubImage3D(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei hight, GLsizei depth, GLenum format, GLenum type,const boid *pixels)

使用pixels会替换texture纹理对象所指定纹理缓存中的部分或全部数据
leble设置了需要更新mipmap的那一层
format指定了像素数据的颜色格式 可选的值有GL_ALPHA,GL_RGB,GL_RGBA,GL_LUMINANCE, GL_LUMINANCE_ALPHA 等几种。
type 指定像素数据的数据类型
width,height,depth是poxels中数据区域的大小 如果width填的是1 然后type指定的是GL_FLOAT 则表示宽度是1float
xoffset,yoffset,zoffset 是偏移量
如果target表示一维的数组纹理 则 yoffset 和 hight分别表示更新后数组的第一层切片和总的切片数

pixels参数有两种情况
第一种情况:
第一种情况 没有绑定GL_PIXEL_UNPACK_BUFFER pixels是一块指向数据地址的指针
第一种的好处:数据在应用程序本地内存中 那么glTextureSubImage2D需要先对数据进行拷贝 然后函数才会返回 不能进行并行完成 好处在于 应用程序在函数返回之后依然可以进行自由修改之前传输的pixels数据

unsigned int texture;
glCreateTextures(GL_TEXTURE_2D,1,&texture);
GLfloat data[]
{
	1.0,1.0,1.0,1.0,   1.0,1.0,1.0,1.0, 
	1.0,1.0,1.0,1.0,   1.0,1.0,1.0,1.0
}
glTextureStorage2D(texture,2,GL_RGBA32F,2,2);
glTextureSubImage2D(texture,//目标纹理
					0,//mipmap第0层
					0,0,//x和y偏移
					2,2//宽度
					GL_RGBA.//格式
					GL_FLOAT,//数据类型
					data);//数据

第二种情况 绑定了GL_PIXEL_UNPACK_BUFFER目标的缓存对象来完成 作为对象的偏移位置 就是将数据绑定到一个缓存对象 再将该绑定给GL_PIXEL_UNPACK_BUFFER
第二种的好处:数据不是立即从缓存对象向纹理进程传输的 而是在着色器请求数据的时候才会执行这一操作 应用程序的运行和数据的传输操作可以并行进行

unsigned int buffer;
glGenbuffer(1,&buffer);
glBindbuffer(GL_PIXEL_UNPACK_BUFFER,buffer);
glBufferData(GL_PIXEL_UNPACK_BUFFER,sizeof(data),data,GL_STATIC_DRAW);
unsigned int texture;
glCreateTextures(GL_TEXTURE_2D,1,&texture);
GLfloat data[]
{
	1.0,1.0,1.0,1.0,   1.0,1.0,1.0,1.0, 
	1.0,1.0,1.0,1.0,   1.0,1.0,1.0,1.0
}
glTextureStorage2D(texture,2,GL_RGBA32F,2,2);
glTextureSubImage2D(texture,//目标纹理
					0,//mipmap第0层
					0,0,//x和y偏移
					2,2//宽度
					GL_RGBA.//格式
					GL_FLOAT,//数据类型
					NULL);//偏移量

(创建采样对象)glCreateSamples(GLsizei n,Gluint *samplers);

返回n个保存在数组samplers中的采样器对象的名称

(将采样对象绑定给采样单元)glBindSampler(GLuint unit, GLuint sampler)

glBindSamplers(GLuint first,GLsizei count, const GLuint *samplers)

第一个是将一个采样器对象sample绑定到unit所设置的采样器单元
第二个是 将多个采样器对象绑定到连续的采样纹理单元
first表示第一个纹理单元
count是采样器单元的数量
sample是指向采样器对象名称的数组 如果samplers中某个元素为0 则代表解绑

(设置采样器对象参数)glSamplerParameter{fi}(GLuint sample, GLenum pname, Type param)

glSamplerParameter{fi}v(GLuint sample, GLenum pname, const Type* param)

glSamplerParameter{i ui}(GLuint sample, GLenum pname, const Type* param)

sample为要设置的采样器对象
设置参数pname的数值为param给定的值
glTextureParameteri()中的param是一个整数值
glTextureParameterf()中的param是一个浮点数值
gTextureParameteriv()中的param是一个正数值数组的地址
glTextureParameterfv()中的param是一个浮点数值数组的地址
在这里插入图片描述
GL_CLAMP_EDGE 如果纹理了坐标超出0.0-1.0的范围 纹理边缘的纹素将作为结果值直接返回给着色器

(设置纹理对象参数)glTextureParameter{fi}(GLuint texture, GLenum pname, Type param)

glTextureParameter{fi}v(GLuint texture, GLenum pname, const Type* param)

glTextureParameter{i ui}(GLuint texture, GLenum pname, const Type* param)

texture为要设置的纹理对象
设置参数pname的数值为param给定的值
glTextureParameteri()中的param是一个整数值
glTextureParameterf()中的param是一个浮点数值
glTextureParameteriv()中的param是一个正数值数组的地址
glTextureParameterfv()中的param是一个浮点数值数组的地址

(绑定纹理对象)glBindTexture

glBindTexture(GL_TEXTURE_2D, texture);绑定纹理对象 也就是绑定给GL_TEXTURE_2D 在调用glDrawElements之前绑定纹理了,它会自动把纹理赋值给片段着色器的采样器

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值