2015-08-09 54 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