Reputation: 317
I am trying to do a scene in OpenGL to simulate earth from space. I have two spheres right now, one for earth, and another slightly big for clouds. The earth and the cloud sphere objects have their own shader programs to keep it simple. The earth shader program takes 4 textures (day, night, specmap and normalmap) and the cloud shader program takes 2 textures (cloudmap and normalmap). I have an object class which has a render function, and in that function I use this logic:
//bind the current object's texture
for (GLuint i = 0; i < texIDs.size(); i++){
glActiveTexture(GL_TEXTURE0 + i);
if (cubemap)
glBindTexture(GL_TEXTURE_CUBE_MAP, texIDs[i]);
else
glBindTexture(GL_TEXTURE_2D, texIDs[i]);
}
if (samplers.size()){
for (GLuint i = 0; i < samplers.size(); i++){
glUniform1i(glGetUniformLocation(program, samplers[i]), i);
}
}
It starts from the 0th texture unit, and binds N number of textures to N number of texture units starting from GL_TEXTURE0. Then it binds the the samplers starting from 0 to N in the shader program. The samplers are provided by me while loading the textures:
void Object::loadTexture(const char* filename, const GLchar* sampler){
int texID;
texID = SOIL_load_OGL_texture(filename, SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS);
if(texID == 0){
cerr << "SOIL error: " << SOIL_last_result();
}
cout << filename << " Tex ID: " << texID << endl;
texIDs.push_back(texID);
samplers.push_back(sampler);
//glBindTexture(GL_TEXTURE_2D, texID);
}
When I do this, all the textures in the first sphere (earth) gets loaded successfully, but in the seconds sphere I get no textures and I just get a black sphere. My query is, how should I manage multiple textures and samplers if I'm using different shader programs for each object?
Upvotes: 1
Views: 1952
Reputation: 51835
From what I see You are binding all textures as separate texture unit
I render space bodies like this:
First pass renders the astro body geometry
I have specific texture units for specific tasks
// texture units:
// 0 - texture0 map 2D rgba (surface)
// 1 - texture1 map 2D rgba (clouds blend)
// 2 - normal map 2D xyz (normal/bump mapping)
// 3 - specular map 2D i (reflection shininess)
// 4 - light map 2D rgb rgb (night lights)
// 5 - enviroment/skybox cube map 3D rgb
see the shader in that link (it was written for the solar system visualization too)...
Second render pass adds atmospheres
[edit1] example of multitexturing
// init shader once per render all geometries
GLint prog_id; // shader program ID;
GLint txrskybox; // global skybox environment cube map
GLint id;
glUseProgram(prog_id);
id=glGetUniformLocation(prog_id,"txr_texture0"); glUniform1i(id,0); //uniform sampler2D txr_texture0;
id=glGetUniformLocation(prog_id,"txr_texture1"); glUniform1i(id,1); //uniform sampler2D txr_texture1;
id=glGetUniformLocation(prog_id,"txr_normal"); glUniform1i(id,2); //uniform sampler2D txr_normal;
id=glGetUniformLocation(prog_id,"txr_specular"); glUniform1i(id,3); //uniform sampler2D txr_specular;
id=glGetUniformLocation(prog_id,"txr_light"); glUniform1i(id,4); //uniform sampler2D txr_light;
id=glGetUniformLocation(prog_id,"txr_skybox"); glUniform1i(id,5); //uniform samplerCube txr_skybox;
// add here all uniforms you need ...
glActiveTexture(GL_TEXTURE0+5); glEnable(GL_TEXTURE_CUBE_MAP); glBindTexture(GL_TEXTURE_CUBE_MAP,txrskybox);
for (i=0;i<all_objects;i++)
{
// add here all uniforms you need ...
// pass textures once per any object render
// obj::(GLint) txr0,txr1,txrnor,txrspec,txrlight; // object local textures
glActiveTexture(GL_TEXTURE0+0); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,obj[i].txr0);
glActiveTexture(GL_TEXTURE0+1); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,obj[i].txr1);
glActiveTexture(GL_TEXTURE0+2); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,obj[i].txrnor);
glActiveTexture(GL_TEXTURE0+3); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,obj[i].txrspec);
glActiveTexture(GL_TEXTURE0+4); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,obj[i].txrlight);
// here render the geometry of obj[i]
}
// unbind textures and shaders
glActiveTexture(GL_TEXTURE0+5); glBindTexture(GL_TEXTURE_CUBE_MAP,0); glDisable(GL_TEXTURE_CUBE_MAP);
glActiveTexture(GL_TEXTURE0+4); glBindTexture(GL_TEXTURE_2D,0); glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0+3); glBindTexture(GL_TEXTURE_2D,0); glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0+2); glBindTexture(GL_TEXTURE_2D,0); glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0+1); glBindTexture(GL_TEXTURE_2D,0); glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0+0); glBindTexture(GL_TEXTURE_2D,0); glDisable(GL_TEXTURE_2D); // unit0 at last so it stays active ...
glUseProgram(0);
Upvotes: 2