问题:在实现镜面光贴图时,在渲染循环外按照代码1激活并绑定纹理,发现无法显示0层的纹理(即木质纹理),只能看到1层的纹理(铁框)。
代码1:
unsigned texture = genTexture(tpath);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
unsigned stexture = genTexture(spath);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, stexture);
scape_shader.setUniform1i("material.diffuse", 0);
scape_shader.setUniform1i("material.specular", 1);
效果:
希望的效果是:
开始以为是图像透明度的问题,将铁框中间的黑色部分挖空设为透明并重新保存为png,发现仍然无法显示出0层的纹理。
首先看genTexture的实现:
unsigned genTexture(const string &path) {
unsigned char *data;
int width, height, nrChannels;
stbi_set_flip_vertically_on_load(true);
data = stbi_load(path.c_str(), &width, &height, &nrChannels, 0);
unsigned texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
GLenum format;
if (nrChannels == 1) format = GL_RED;
if (nrChannels == 3) format = GL_RGB;
if (nrChannels == 4) format = GL_RGBA;
//重复填充效果
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, format, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
stbi_image_free(data);
return texture;
}
其中有一句话:glBindTexture(GL_TEXTURE_2D, texture);
发现这句话前面没有写glActiveTexture(...)
,即这句话默认是将当前生成的texture绑定到GL_TEXTURE0
上,问题就出在这。
在代码1中我是创建纹理就立即绑定他了,对于第一个木质纹理(tpath对应的纹理),在生成texture之后,就将其绑定在GL_TEXTURE0
上了,而在第二个纹理(铁框纹理)产生的时候,由于当前活跃的纹理目标是GL_TEXTURE0
(默认也是他),所以会将铁框纹理绑定在GL_TEXTURE0
,此时原本绑定在GL_TEXTURE0
上的木质纹理就失效了,所以代码1其实实现的是在GL_TEXTURE0
和GL_TEXTURE1
上均绑定了铁框纹理,所以木质纹理自然就看不见了。
如何修改?
应该先将所有texture生成(因为生成的texture不会消失,在内存中存在,并且一个texture(unsigned整数)对应唯一一个内存区域),再挨个绑定。
unsigned texture = genTexture(tpath);
unsigned stexture = genTexture(spath);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, stexture);
scape_shader.setUniform1i("material.diffuse", 0);
scape_shader.setUniform1i("material.specular", 1);