簡體   English   中英

帶有多個着色器程序的OpenGL多重紋理

[英]OpenGL multiple texture with multiple shader programs

我正在嘗試在OpenGL中創建一個場景以模擬太空中的地球。 我現在有兩個球體,一個是地球,另一個是大雲。 地球和雲球對象具有自己的着色器程序,以使其簡單。 Earth shader程序采用4種紋理(白天,黑夜,specmap和Normalmap),而Cloud Shader程序采用2種紋理(cloudmap和Normalmap)。 我有一個具有render函數的對象類,在該函數中,我使用以下邏輯:

//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個紋理綁定到從GL_TEXTURE0開始的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);
}

當我這樣做時,第一個球體(地球)中的所有紋理都成功加載,但是在第二個球體中,我沒有紋理,而我只得到了一個黑色球體。 我的查詢是,如果我為每個對象使用不同的着色器程序,應該如何管理多個紋理和采樣器?

從我看到的內容來看,您正在將所有紋理綁定為單獨的紋理單元

  • 那是錯的
  • 如果您有100個對象並且每個對象有4個紋理怎么辦...
  • 我強烈懷疑您是否可以使用400個紋理單位
  • 紋理ID(名稱)不是紋理單位...

我渲染這樣的空間物體:

  1. 第一遍渲染astro人體幾何

    • 我有用於特定任務的特定紋理單元

       // 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 
    • 請參閱該鏈接中的着色器(它也是為太陽系可視化編寫的)...

    • 您可以在每次渲染前僅綁定單個主體的紋理
    • (綁定着色器之后)
    • 不要更改紋理單位的含義(如果進行着色,着色器將如何知道哪種紋理是?)
  2. 第二次渲染過程增加了氣氛

    • 沒有使用紋理
    • 它只是覆蓋整個屏幕的單個透明四邊形
  3. 這里對您的任務有一些見解

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM