我的代码有效,但我想知道为什么!
我有2个纹理:
uniform sampler2D uSampler0;
uniform sampler2D uSampler1;
void main() {
vec4 color0 = texture2D(uSampler0, vTexCoord);
vec4 color1 = texture2D(uSampler1, vTexCoord);
gl_FragColor = color0 * color1;
}
和我的js代码
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D,my_texture_ZERO);
gl.uniform1i(program.uSampler0,0);
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D,my_texture_ONE);
gl.uniform1i(program.uSampler1);
// uncomment one of the 3, it works.
// gl.bindTexture(gl.TEXTURE_2D, my_texture_ZERO);
// gl.bindTexture(gl.TEXTURE_2D, my_texture_ONE);
// gl.bindTexture(gl.TEXTURE_2D, texture_FOR_PURPOSE_ONLY);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
在gl.draw之前,我测试了3个绑定, 每个人都有效!
所以,我不明白真正的管道基础。
感谢您的一些解释
答案 0 :(得分:1)
它正常工作,因为在提供的代码中,您正在为采样器发送适当的制服。
通过调用glActiveTexture(GL_TEXTURE0)将第一个纹理设置为单位0,然后绑定。然后切换到unit1。
此时每个单元中有两个单独的绑定纹理。
最后,这些单位作为采样器的制服传递 - 这是如何指示采样器中应该采用哪种纹理:在这种情况下,将对应于GL_TEXTURE0单位的0传递给第一制服并将第二制服的类似物传递给第二制服。
甚至可能没有取消注释这些内容 - 事情应该有效。
答案 1 :(得分:1)
此行无效
gl.uniform1i(program.uSampler1);
您没有将值传递给采样器
WebGL纹理单元的工作方式是它们是WebGL中的全局状态
gl.activeTexture
设置纹理单元所有其他纹理命令的效果。对于每个纹理单元,有2个绑定点TEXTURE_2D
和TEXTURE_CUBE_MAP
。
你可以这样认为
gl = {
activeTextureUnit: 0,
textureUnits: [
{ TEXTURE_2D: null: TEXTURE_CUBE_MAP: null, },
{ TEXTURE_2D: null: TEXTURE_CUBE_MAP: null, },
{ TEXTURE_2D: null: TEXTURE_CUBE_MAP: null, },
...
],
};
gl.activeTexture
就是这样做
gl.activeTexture = function(unit) {
gl.activeTextureUnit = unit - gl.TEXTURE0;
};
gl.bindTexture
执行此操作
gl.bindTexture = function(bindPoint, texture) {
gl.textureUnits[gl.activeTextureUnit][bindPoint] = texture;
};
gl.texImage2D
和gl.texParamteri
查找要使用的纹理
gl.texImage2D = function(bindPoint, .....) {
var texture = gl.textureUnits[gl.activeTextureUnit][bindPoint];
// now do something with texture
换句话说,在WebGL内部有一个全局的纹理单元数组。 gl.activeTexture
和gl.bindTexture
操纵该数组。
gl.texXXX
操纵纹理本身,但它们通过该数组间接引用纹理。
gl.uniform1i(someSamplerLocation, unitNumber)
设置着色器的制服以查看该纹理单元数组中的特定索引。