I am using OpenGL version string: 4.6 (Compatibility Profile) Mesa 21.3.5
. I load objects from an .obj file with matching textures, 51 textures to be exact. To be able to match various textures to various triangles and surfaces, I am adding texture coordinates along with an texture identifier in my vertex array buffer.
So now I use a stride looking like this:
x y z u v r g b id
which clarifies with: pos tex col id
.
The problem now is that I can generate textures and bind them to corresponding texture units, but I cannot select each texture in my shader in regards to the texture unit id I get from my texture array buffer. To clarify: I generate and bind textures like so:
void loadTextures(void) {
std::cout << "Size: " << this->materialLib.materials.size() << std::endl;
std::cout << "Loading textures" << std::endl;
for (long unsigned int i = 0; i < this->materialLib.materials.size(); i++) {
Material m = this->materialLib.materials[i];
// init
struct TEXTURE *t = (struct TEXTURE*)malloc(sizeof(struct TEXTURE));
t->data = NULL;
t->path = (char*)malloc(sizeof(char) * (m.ambient_map.length() + 1)); // add one to include \0 character
t->texture_int = 0;
strcpy(t->path, m.ambient_map.c_str());
t->data = stbi_load( t->path, &t->width, &t->height, &t->nrChannels, 0);
textures.push_back(t);
std::cout << '\r';
std::cout << i << "/" << this->materialLib.materials.size();
std::cout.flush(); // see wintermute's comment
}
}
void applyTextures(Shader ourShader) {
for (long unsigned int i = 0; i < textures.size(); i++) {
struct TEXTURE *t = textures[i];
glGenTextures( 1, &t->texture_int );
glBindTexture( GL_TEXTURE_2D, t->texture_int );
// set the texture wrapping parameters
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
// set texture filtering parameters
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
// load image, create texture and generate mipmap
//stbi_set_flip_vertically_on_load(true); // tell stb_image.h to flip loaded texture's on the y-axis.
if (t->data) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, t->width, t->height, 0, GL_RGB, GL_UNSIGNED_BYTE, t->data);
glGenerateMipmap(GL_TEXTURE_2D);
} else
std::cout << "ERROR::LOAD::TEXTURE " << t->path << " " << i << std::endl;
}
return;
/* This could be optimized by moving this to the above loop but we'll separate for simplicity for now */
GLint gl_textures[MAX_TEXTURES];
ourShader.use();
for (long unsigned int i = 0; i < textures.size() && i < MAX_TEXTURES; i++) {
gl_textures[i] = i;
// set texture unit as a uniform for the fragment shader, could be set by ourShader.setInt()
glUniform1i(glGetUniformLocation(ourShader.ID, "texture" + (1 + i)), i); // 'i' is our texture id, for another texture, use another id
}
// set texture units as a uniform for the fragment shader
glUniform1iv(glGetUniformLocation(ourShader.ID, "textures"), MAX_TEXTURES, gl_textures);
}
void bindTextures(void) {
for (long unsigned int i = 0; i < textures.size(); i++) {
glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, textures[i]->texture_int);
}
}
This gives me varius uniforms in my fragment shader that I can select like so:
uniform sampler2D texture1;
uniform sampler2D texture2;
...
FragColor = texture(texture2, TexCoord);
I want to be able to select a texture like this:
uniform sampler2D texures;
...
FragColor = texture(textures[id], TexCoord);
What I have tried is to pass the id as the first argument to "texture()" but that gave me an error, I also tried to cast my id as a sampler2D type but that didn't work either.
How can I fix this?