本文为L_Ares个人写作,包括图片皆为个人亲自操作,如需转载请表明原文出处。
一、关于纹理采样器Sampler
关于对纹理单元的理解,首先就要知道什么是sampler
纹理采样器。在GLSL中,我们经常会在.fsh
也即是片元着色器源码文件中使用sampler
这个修饰符,它会和一个texture
一一对应,从而获取到我们需要的纹理。
他的功能就是辅助texture()
函数获取纹理的纹素,而texture()
函数有两个参数,一个是纹理坐标,另外一个就是sampler
修饰的纹理,由此可见,sampler是通过某些方法获取纹理的修饰符。
sampler
之前,会有uniform
通道来修饰,也即是说明,纹理采样器对应的采样或者说获取的纹理是不经常发生改变的量。
二、关于纹理单元
首先来明确一个概念,通常情况下,一个纹理的位置,我们通常称其为纹理单元,一个纹理的默认纹理单元是0,通常情况下,这个默认的纹理单元0是激活的。
纹理单元的主要目的是让我们可以在着色器中可以使用多于1个的纹理。
在激活了相应的纹理单元位置以后,我们可以通过把纹理单元赋值给纹理采样器,从而将纹理采样器获取到的纹理赋值到纹理单元上。激活纹理单元的方式是:
glActiveTexture(GL_TEXTURE0)
;
参数传入我们需要激活的纹理单元。
GL_TEXTURE0
默认就是激活状态的。
上面也说了,纹理采样器和纹理是一一对应的,那么纹理和纹理单元也就要一一对应,就需要进行绑定。绑定纹理到对应激活的纹理单元的方法是:
glBindTexture(GL_TEXTURE_2D,texure)
;
参数第一个是纹理的维度,第二个就是纹理。
OpenGL保证了16个纹理单元供我们选择使用,超过16个的话,就自己想办法吧,即GL_TEXTURE0
~GL_TEXTURE15
。纹理单元是有顺序定义的,所以在使用连续的纹理单元的时候,可以使用循环的方式,例如:想要获取纹理单元6,可以直接写GL_TEXTURE + 6
三、关于多纹理的混合
如果我们需要使用多个纹理,那么在设置gl_FragColor
这个内建变量的时候,可以选择使用mix()
这个GLSL的内建函数来达到混合的目的。
如:(提示,不要在.fsh
里面写注释,这里是没有办法)
//纹理坐标
varying vec2 varyTextCoord;
//纹理单元1
uniform sampler2D textureUnit1;
//纹理单元2
uniform sampler2D textureUnit2;
void main()
{
gl_FragColor = mix(texture(textureUnit1,varyTextCoord),texture(textureUnit2,varyTextCoord),0.6);
}
mix
函数参数解析:
(1). 第一个参数是获取纹理单元1的纹理采样值
(2). 第二个参数是获取纹理单元2的纹理采样值
(3). 第三个参数是混合比例,按照比例进行线性插值。
比如,如果第三个参数设置的是0.6,那么就会按照纹理单元1的40%和纹理单元2的60%进行线性插值。
如果第三个参数设置为0,则全部使用第一个纹理单元的颜色,如果第三个参数为1,那么全部使用第二个纹理单元的颜色。
另外,因为有两个纹理单元,所以除了第一个默认开启的纹理单元0以外,我们要激活第二个纹理单元,并且绑定纹理和纹理单元。
glBindTexture(GL_TEXTURE2D,0);
glUniform1i(glGetUniformLocation(self.program, "textureUnit1"), 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE2D,1);
glUniform1i(glGetUniformLocation(self.program, "textureUnit2"),1);
glUniform1i
函数则是保证纹理单元和uniform sampler2D
互相一一对应。即:
纹理单元0对应着纹理采样器textureUnit1采样的纹理。
纹理单元1对应着纹理采样器textureUnit2采样的纹理。
网友评论