纹理显示为纯黑色,除非我将无效值传递给纹理均匀位置

时间:2012-01-22 18:27:32

标签: c++ opengl glsl

到目前为止,我的计划一直运作良好,但结果证明我很幸运。我开始对着色器进行一些清理,因为它充满了实验性的东西,并且我在片段着色器的末尾有以下行:

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

1 个答案:

答案 0 :(得分:6)

  

glUniform1i(tex_loc,texture_id _);

第二个参数应指定纹理单元的ID(提示:glActiveTexture设置当前活动的纹理单元),而不是特定纹理对象的ID。