2015-08-09 86 views
1

我想在OpenGL中做一个场景来模拟来自太空的地球。我现在有两个球体,一个用于地球,另一个用于云层。地球和云球对象有自己的着色器程序来保持简单。地球着色器程序需要4个纹理(日,夜,specmap和normalmap),云着色器程序需要2个纹理(云图和法线贴图)。我有具有呈现功能的对象类,并在该功能的我使用这个逻辑:从GL_TEXTURE0开始带有多个着色器程序的OpenGL多纹理

//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); 
    } 
} 

它从第0纹理单元开始,并结合纹理的N个以N个纹理单元。然后在着色器程序中将采样器从0开始绑定到N.采样器是由我公司提供,同时加载纹理:

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); 
} 

当我做到这一点,在第一球(地球)所有的纹理被加载成功,但在秒球我没有得到任何纹理和我刚刚得到一个黑色的球体。我的查询是,如果我为每个对象使用不同的着色器程序,我应该如何管理多个纹理和采样器?

回答

2

从我看到你有约束力的所有纹理作为独立的纹理单元

  • ,这是错误
  • 如果你有100个对象,每个人都有4个纹理...
  • 我强烈怀疑你有400个纹理单位在您的处置
  • 纹理ID(名称)不是纹理单元...

我使空间机构是这样的:

  1. First pass renders the astro body geometry

    • 我有特殊的纹理单元为特定任务

      // 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 
      
    • 见日在该路段e着色器(它是太阳系可视化太书面)...

    • 绑定仅在每个前的单机身纹理渲染它
    • (绑定着色器后)
    • 做不会改变纹理单元的含义(如果着色器知道哪个纹理是如何做的话?)
  2. Second render pass adds atmospheres

    • 使用
    • 没有纹理它仅仅是单透明的四覆盖整个屏幕
  3. here some insights to your tasks

[EDIT1]多纹理

// 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); 
+0

的例子可以告诉你你怎么绑定纹理着色器上使用glActiveTexture和glBindTexture调用C++的一面呢? – pslayer89

+0

@ pslayer89增加了一个例子 – Spektre

+0

谢谢,我今天晚些时候会尝试一下结果。 – pslayer89