2012-01-22 40 views
1

我的程序一直運行良好,但事實證明我很幸運。我開始做着色器的一些清理工作,因爲它充滿了實驗性的東西,我在片段着色器的結尾以下行:紋理顯示爲純黑色,除非我將無效值傳遞到紋理統一位置

gl_FragColor = final_color * (texture2D(tex, gl_TexCoord[0].st)*1.0 + texture2D(tex2, gl_TexCoord[0].st)*1.0); 

我試圖把它清理乾淨,我有以下聲明在頂部:

uniform sampler2D tex, tex2; 

這些行改爲:

gl_FragColor = final_color * texture2D(tex, gl_TexCoord[0].st; 

uniform sampler2D tex; 

實際上打破了計劃(黑屏),即使我在我的主代碼做

GLuint tex_loc = glGetUniformLocation(shader_prog_id_, "tex"); 
glUniform1i(tex_loc, texture_id_); 

。我確定這是一個紋理問題,而不是glsl編譯器錯誤,因爲我可以將1.0添加到輸出中,並以網格的白色輪廓結束。

gl_FragColor = final_color * texture2D(tex2, gl_TexCoord[0].st; 

uniform sampler2D tex2; 

但仍檢索位置tex

陌生感當我改變了線我着色器開始。儘管在調試器中檢查tex_loc的值表明存在錯誤,但程序仍然像以往一樣工作。我不喜歡這樣做,現在我正試圖加載多個紋理,它會導致更大的麻煩。

我使用交織格式的VBO來渲染幾何。我以這種方式傳遞頂點位置,正常和texcoord。

「黑色紋理」問題還有其他問題,但他們使用即時模式調用並設置錯誤的紋理狀態。我在提供數組之前嘗試更改紋理單元,但沒有成功。

這裏是主程序儘可能多的相關代碼可能:

void MeshWidget::draw() { 

    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 
    glTranslatef(0.0f, 0.0f, -4.0f + zoom_factor_); 
    glRotatef(rotX, 1.0f, 0.0f, 0.0f); 
    glRotatef(rotY, 0.0f, 1.0f, 0.0f); 
    glRotatef(rotZ, 0.0f, 0.0f, 1.0f); 

    // Auto centre mesh based on vertex bounds. 
    glTranslatef(-x_mid_, -y_mid_, -z_mid_); 

    glDrawElements(GL_TRIANGLES, mesh_.num_indices, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0)); //The starting point of the IBO 
} 


void MeshWidget::openMesh(const string& filename) { 

    if (mesh_filename_ != filename) { 

     clearMeshData(mesh_); 

     glDeleteBuffersARB(1, &VertexVBOID); 
     glDeleteBuffersARB(1, &IndexVBOID); 

     ReadMsh(mesh_, filename); 

     // Create buffer objects here. 
     glGenBuffersARB(1, &VertexVBOID); 
     glBindBufferARB(GL_ARRAY_BUFFER, VertexVBOID); 
     glBufferDataARB(GL_ARRAY_BUFFER, sizeof(VertexAttributes)*mesh_.num_vertices, &mesh_.vertices[0], GL_STATIC_DRAW); 

     glGenBuffersARB(1, &IndexVBOID); 
     glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, IndexVBOID); 
     glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint16_t)*mesh_.num_indices, &mesh_.indices[0], GL_STATIC_DRAW); 

     glBindBuffer(GL_ARRAY_BUFFER, VertexVBOID); 
     glEnableClientState(GL_VERTEX_ARRAY); 
     glVertexPointer(3, GL_FLOAT, sizeof(VertexAttributes), BUFFER_OFFSET(0)); //The starting point of the VBO, for the vertices 
     glEnableClientState(GL_NORMAL_ARRAY); 
     glNormalPointer(GL_FLOAT, sizeof(VertexAttributes), BUFFER_OFFSET(12)); //The starting point of normals, 12 bytes away 
     glClientActiveTexture(GL_TEXTURE0); 
     glEnableClientState(GL_TEXTURE_COORD_ARRAY); 
     glTexCoordPointer(2, GL_FLOAT, sizeof(VertexAttributes), BUFFER_OFFSET(24)); //The starting point of texcoords, 24 bytes away 

     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexVBOID); 

     if (startup_done_) updateGL(); 
    } 
} 

void MeshWidget::openTexture(const string& filename) { 

    size_t dot = filename.find_last_of('.'); 
    string ext(filename, dot, filename.size()); // 3rd parameter should be length of new string, but is internally clipped to end. 

    glActiveTexture(GL_TEXTURE0); 
    glClientActiveTexture(GL_TEXTURE0); 
    glDeleteTextures(1, &texture_id_); 
    glGenTextures(1, &texture_id_); 
    glBindTexture(GL_TEXTURE_2D, texture_id_); 

    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 

    if (ext == ".dds") { 
     if (GLEE_EXT_texture_compression_s3tc) { 

      texture_id_ = SOIL_load_OGL_texture(filename.c_str(), SOIL_LOAD_AUTO, texture_id_, SOIL_FLAG_DDS_LOAD_DIRECT); 
      // SOIL takes care of calling glTexParams, glTexImage2D, etc. 
      yflip_texture_ = true; 

      } else { 
       //std::cout << "S3TC not supported on this graphics hardware." << std::endl; 
       // TODO: Error message in status bar? 
      } 

    } else { 

     QImage tex(filename.c_str()); 
     tex = QGLWidget::convertToGLFormat(tex); 

     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tex.bits()); 

     yflip_texture_ = false; 

    } 

    updateUniforms(); 

    if (startup_done_) updateGL(); 
} 

void MeshWidget::updateUniforms() { 

    GLuint texture_flip_uniform = glGetUniformLocation(shader_prog_id_, "yflip"); 
    glUniform1f(texture_flip_uniform, float(yflip_texture_ * 1.0f)); 

    GLuint tex_loc = glGetUniformLocation(shader_prog_id_, "tex"); 
    glUniform1i(tex_loc, texture_id_); 
} 

我的着色器(還是有一些垃圾在這裏,因爲我嘗試,但沒有什麼影響輸出):

varying vec3 normal, lightDir, eyeVec; 
uniform float yflip; 

void main() 
{ 
    normal = gl_NormalMatrix * gl_Normal; 

    vec3 vVertex = vec3(gl_ModelViewMatrix * gl_Vertex); 

    lightDir = vec3(gl_LightSource[0].position.xyz - vVertex); 
    eyeVec = -vVertex; 

    gl_TexCoord[0].x = gl_MultiTexCoord0.x; 
    gl_TexCoord[1].x = gl_MultiTexCoord1.x; 

    if (yflip == 1.0) { 
     gl_TexCoord[0].y = 1 - gl_MultiTexCoord0.y; 
     gl_TexCoord[1].y = 1 - gl_MultiTexCoord1.y; 
    } else { 
     gl_TexCoord[0].y = gl_MultiTexCoord0.y; 
     gl_TexCoord[1].y = gl_MultiTexCoord1.y; 
    } 

    gl_Position = ftransform(); 
} 

片段着色器:

varying vec3 normal, lightDir, eyeVec; 
uniform sampler2D tex2; 

void main (void) 
{ 

    vec4 texel = texture2D(tex2, gl_TexCoord[0].st); 

    vec4 final_color = 
(gl_FrontLightModelProduct.sceneColor * gl_FrontMaterial.ambient) + 
(gl_LightSource[0].ambient * gl_FrontMaterial.ambient); 

    vec3 N = normalize(normal); 
    vec3 L = normalize(lightDir); 

    float lambertTerm = dot(N,L); 

    if(lambertTerm > 0.0) 
    { 
     final_color += gl_LightSource[0].diffuse * 
        gl_FrontMaterial.diffuse * 
        lambertTerm; 

     vec3 E = normalize(eyeVec); 
     vec3 R = reflect(-L, N); 
     float specular = pow(max(dot(R, E), 0.0), 
        gl_FrontMaterial.shininess); 
     final_color += gl_LightSource[0].specular * 
        gl_FrontMaterial.specular * 
        specular;  
    } 

    gl_FragColor = final_color * texel; 
} 

回答

6

glUniform1i(tex_loc,texture_id_);

第二個參數應該指定紋理單元的ID(提示:glActiveTexture設置當前活動的紋理單元),而不是特定紋理對象的ID。

+1

只是爲了澄清,你的意思是我應該通過'GL_TEXTURE0'來代替'texture_id_'嗎? – usm

+0

是的。或者,您可以傳遞0,如glActiveTexture鏈接中所述。 – arul

+0

根據我的OpenGL SuperBible副本,它應該是'0',而不是enum中的值,當我剛剛嘗試時它導致崩潰。謝謝! – usm