学习是一件开心的额事情
学习目标
- 理解纹理图像的概念
- 掌握纹理采样器的类型和作用
- 在GLSL 中如何使用纹理
- 纹理缓冲区
纹理图像
玩过游戏的同学们,都知道在游戏人物身上穿的那个叫皮肤,专业点将那个就叫做纹理图像。GLSL 支持在顶点和片段着色器使用纹理图像。
纹理采样器的类型和作用
下面的这个表解释了每种采样器的作用,不需要记忆,使用时,进行查阅即可!
采样器名称 |
描述 |
---|---|
sampler1D |
访问1D 纹理图像 |
isampler1D |
访问1D 纹理图像 |
usampler1D |
访问1D 纹理图像 |
sampler2D |
访问2D 纹理图像 |
isampler2D |
访问2D 纹理图像 |
usampler2D |
访问2D 纹理图像 |
sampler3D |
访问3D 纹理图像 |
isampler3D |
访问3D 纹理图像 |
usampler3D |
访问3D 纹理图像 |
samplerCube |
访问立体纹理图像 |
isamplerCube |
访问立体纹理图像 |
sampler1DArray |
访问1D 纹理图像数组 |
isampler1DArray |
访问1D 纹理图像像数组 |
usampler1DArray |
访问1D 纹理图像像数组 |
sampler2DArray |
访问2D 纹理图像数组 |
isampler2DArray |
访问2D 纹理图像像数组 |
usampler2DArray |
访问2D 纹理图像像数组 |
sampler2DRect |
访问2D 纹理矩形 |
isampler2DRect |
访问2D 纹理矩形 |
usampler2DRect |
访问2D 纹理矩形 |
sampler1DShadow |
访问1D 阴影纹理 |
isampler1DShadow |
访问1D 阴影纹理 |
usampler1DShadow |
访问1D 阴影纹理 |
samplerCubeShadow |
访问立体纹理 |
samler1DArrayShadow |
访问1D阴影纹理的一个数组 |
samler2DArrayShadow |
访问2D阴影纹理的一个数组 |
samler2DRectShadow |
访问2D阴影纹理矩阵 |
samplerBuffer |
访问纹理缓冲区 |
isamplerBuffer |
访问纹理缓冲区 |
usamplerBuffer |
访问纹理缓冲区 |
如何使用
第一步.采样器必须在着色器中声明为uniform,切记他们的赋值必须来自应用程序中,采样器也可以作为函数的参数,但必须是类型匹配的采样器 第二步.采样器在着色器中使用之前必须分配一个纹理单元,并且只能通过glUniformli()、glUniformliv() 进行初始化(把采样器应该使用的纹理单元的索引作为参数)
Glint texsampler; texSampler = glGetUniformLocation(program,"tex "); glUniformli(texSampler,2);
第三步 .在着色器内部对一副问题图片进行采样时,需要使用已经声明且与一个纹理单元相关联的采样器变量。举个例子: 我们对一个与Sampler 2D 变量tex 相关联的二维纹理图像进行采样,并把采样结果和片段颜色进行组合,提供与在纹理环境下使用GL_MODULATE 模式相同的结果:
uniform sampler2D tex; void main(){ gl_fragColor = gl_color *texture2D(tex,gl_texCoord[0].st) }
- 依赖性纹理读取 先解释一下,在一个使用纹理贴图的着色器执行过程中,需要使用纹理坐标在纹理图像中指定位置,并提取相应的纹理单元的值。 我们看看代码怎么写:
uniform sampler1D coords; uniform sampler3D volume; void main() { vec3 texCoords = texture1D(coords,gl_TexCoord[0].s); vec3 volumeColor = texture3D(volume,texCoords); }
纹理缓冲区
有个问题先说一下:尽管GLSL 使得数组可用,不管是在着色器中使用静态初始值,还是作为值得集合呈现为uniform变量中的一个数组,在这两个情况下,都有可能出现超出可用大小限制的数组.我们可能把这样一个值得表存储在一个纹理图像中,然后,在纹理中操作纹理坐标来访问想要访问的值。对于这个问题,更加直接的解决方案是纹理缓冲区,为什么这样说呢?纹理缓冲区是缓冲对象的一种特定的类型,类似于一维纹理,可以在说色器中使用一个整数值来索引,但是,它提供了较为昂贵的纹理内存的资源,因此支持较大的数据集合。 创建纹理缓冲区的步骤: 1.初始化数据 glBufferData() 2.把该缓冲区绑定到一个纹理缓冲区中 glTexBuffer()
void glTexBuffer(GLenum target,GLenum internalFormat,GLuint buffer)
把缓冲区对象buffer 和target 关联起来,这导致buffer 中的数据格式被解释为拥有internalFormat 的格式. target:必须为GL_TEXTURE_BUFFER interalFormat 纹理格式: GL_R8,GL_R16,GL_R16F,GL_R32F,GL_R81,GL_R16I,GL_R32I,GL_R81UI,GL_R16UI,GL_R32UI,GL_RG8,GL_RG16,GL_RG16F,GL_RG32F,GL_RG81,GL_RG16I,GL_RG32I,GL_RG8UI,GL_RG16UI,GL_RG32UI,GL_RGBA8,GL_RGBA16,GL_RGBA16F,GL_RGBA32F,GL_RGBA8I,GL_RGBA16I,GL_RGBA32I,GL_RGBA8UI,GL_RGBA16UI,GL_RGBA32UI 通过调用glActiveTexture() 来指定那个纹理单元和纹理缓冲区相关联。
总结
纹理的使用在OpenGL 中是比较重要的一块内容,必须要掌握!