c++ - OpenGL 纹理映射不起作用

标签 c++ opengl glsl shader texture-mapping

我必须使用 OpenGL API 和着色器对网格进行纹理化。

为此,我执行了以下步骤:

  1. 加载图片并创建纹理

    img::ImageLoader imgLoader;
    unsigned char* data = imgLoader.LoadTextureFromFile("../Texturen/brickwork.jpg", &width, &height, true);
    
    glGenTextures(1, &texId);
    glBindTexture(GL_TEXTURE_2D, texId);{
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    }
    
  2. 创建顶点、法线和纹理坐标

    std::vector<float> v, n, t;
    
    // actual calculation is left out to make it more readable
    
    obj = new GLBatch;
        obj->Begin(GL_TRIANGLES, v.size()/3, t.size()/2);{
        obj->CopyVertexData3f(v.data());
        obj->CopyNormalDataf(n.data());
        obj->CopyTexCoordData2f(t.data(), 0);
    }obj->End();
    
  3. 加载着色器

    shaders =  gltLoadShaderPairWithAttributes("VertexShader.glsl", "FragmentShader.glsl", 2, 
        GLT_ATTRIBUTE_VERTEX, "vVertex", 
        GLT_ATTRIBUTE_NORMAL, "vNormal",
        GLT_ATTRIBUTE_TEXTURE0, "vTexCoord");
    
    gltCheckErrors(shaders);
    

    (VertexShader.glsl)

    #version 130
    in vec4 vVertex;
    in vec4 vNormal;
    in vec2 vTexCoord;
    
    uniform mat4 mvpMatrix;
    uniform mat4 mvMatrix;
    uniform mat3 normalMatrix;
    /// Light position in Eye-Space
    uniform vec4 light_pos_vs ;
    /// Light diffuse color
    uniform vec4 light_diffuse ;
    uniform vec4 light_ambient ;
    /// Light specular color
    uniform vec4 light_specular ;
    /// Specular power (shininess)
    uniform float spec_power;
    
    /// Material parameters
    uniform vec4 mat_emissive;
    uniform vec4 mat_ambient; 
    uniform vec4 mat_diffuse;   
    uniform vec4 mat_specular;  
    
    /// output
    out vec4 color;
    out vec2 texCoords;
    
    void main()
    {   
        texCoords = vTexCoord;
        // Transform vertex from objekt to clip-space
        gl_Position = mvpMatrix * vVertex ;
    
        // Transform vertex from object to eye-space
        vec4 vertex_vs = mvMatrix * vVertex;
        vec3 ecPos = vertex_vs.xyz / vertex_vs.w;
    
        // Calculate light direction
        vec3 light_dir_vs = normalize(vec3(light_pos_vs.xyz));
    
        // Transform normals from object into eye-space
        vec3 normal_vs = normalize(normalMatrix * (vNormal).xyz) ;
    
        // Viewing vector in eye-space
        vec3 view_dir_vs = normalize(-ecPos );
    
        // Halfway vektor for Phong-Blinn light modell
        vec3 halfway_vs = normalize(view_dir_vs + light_dir_vs ) ;
    
        // Diffuse
        float NdotL = max(dot(normal_vs, light_dir_vs),0.0) ;
        vec4 diffuse_color = NdotL * mat_diffuse * light_diffuse ;
    
        // Specular
        float NdotH = max(dot(normal_vs, halfway_vs),0.0) ;
        vec4 specular_color = pow(NdotH ,spec_power) * mat_specular * light_specular ;
    
        // Color output
        color = mat_emissive + light_ambient*mat_ambient + diffuse_color + specular_color;
    }
    

    (FragmentShader.glsl)

    #version 130
    
    in vec2 texCoords;
    in vec4 color;
    
    uniform sampler2D textureMap;
    
    out vec4 fragColor;
    
    void main()
    {
        fragColor = texture(textureMap, texCoords);
        fragColor *= color;
    }
    
  4. 在显示函数中绘制所有内容

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    glLineWidth(INDICATOR_WIDTH);
    glBindTexture(GL_TEXTURE_2D, texId);
    
    modelViewMatrix.LoadIdentity();
    modelViewMatrix.Translate(0,0,-5);
    modelViewMatrix.PushMatrix();{
    
        M3DMatrix44f rot;
        m3dQuatToRotationMatrix(rot,rotation);
        modelViewMatrix.MultMatrix(rot);
    
        // set shader
        glUseProgram(shaders);
        // pass matrices
        glUniformMatrix4fv(glGetUniformLocation(shaders, "mvpMatrix"), 1, GL_FALSE, transformPipeline.GetModelViewProjectionMatrix());
        glUniformMatrix4fv(glGetUniformLocation(shaders, "mvMatrix"),  1, GL_FALSE, transformPipeline.GetModelViewMatrix());
        glUniformMatrix3fv(glGetUniformLocation(shaders, "normalMatrix"),  1, GL_FALSE, transformPipeline.GetNormalMatrix(true));
        // pass light properties
        glUniform4fv(glGetUniformLocation(shaders, "light_pos_vs"),1,light_pos);
        glUniform4fv(glGetUniformLocation(shaders, "light_ambient"),1,light_ambient);
        glUniform4fv(glGetUniformLocation(shaders, "light_diffuse"),1,light_diffuse);
        glUniform4fv(glGetUniformLocation(shaders, "light_specular"),1,light_specular);
        glUniform1f(glGetUniformLocation(shaders, "spec_power"),specular_power);
        // pass material properties
        glUniform4fv(glGetUniformLocation(shaders, "mat_emissive"),1,mat_emissive);
        glUniform4fv(glGetUniformLocation(shaders, "mat_ambient"),1,mat_ambient);
        glUniform4fv(glGetUniformLocation(shaders, "mat_diffuse"),1,mat_diffuse);
        glUniform4fv(glGetUniformLocation(shaders, "mat_specular"),1,mat_specular);
    
        drawObject();
    
    }modelViewMatrix.PopMatrix();
    
    gltCheckErrors(shaders);
    glutSwapBuffers();
    glutPostRedisplay();
    

完成所有这些步骤后,结果看起来不错,但没有纹理 :(

Screenshot

这里实际发生的是,每个顶点都映射到我的纹理的相同像素,该像素显然是灰色的。

我尝试了从(0,0) 到(1,1)(0,0) 到(width,height) 的纹理坐标 但没有任何改变。

最佳答案

改变

shaders =  gltLoadShaderPairWithAttributes(
    "VertexShader.glsl", 
    "FragmentShader.glsl",
    2, 
    GLT_ATTRIBUTE_VERTEX, "vVertex", 
    GLT_ATTRIBUTE_NORMAL, "vNormal",
    GLT_ATTRIBUTE_TEXTURE0, "vTexCoord");

shaders =  gltLoadShaderPairWithAttributes(
    "VertexShader.glsl", 
    "FragmentShader.glsl",
    3, // < -------------------- 
    GLT_ATTRIBUTE_VERTEX, "vVertex", 
    GLT_ATTRIBUTE_NORMAL, "vNormal",
    GLT_ATTRIBUTE_TEXTURE0, "vTexCoord");

因为函数签名中的第三个参数是紧随其后且应链接到着色器的属性数。在这种情况下,有 3 个属性:GLT_ATTRIBUTE_VERTEXGLT_ATTRIBUTE_NORMALGLT_ATTRIBUTE_TEXTURE0。 在原始代码中,只有 GLT_ATTRIBUTE_VERTEXGLT_ATTRIBUTE_NORMAL 链接在一起,因此没有纹理坐标传递给着色器。

关于c++ - OpenGL 纹理映射不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44709151/

相关文章:

c++ - Boost 多精度舍入模式

c++ - Assimp 不导入纹理

c++ - 错误消息 : "KHR/khrplatform.h" cannot be opened, 但 "khrplatform"在程序中的任何位置都不存在

opengl - GLSL 的 GPU 蒙皮问题

c - glGetUniform 为事件制服返回 -1

C++ 从源生成器生成文件 - 有这样的吗?

c++ - 可移植性库/框架

c++ - 为什么我的链接列表在函数调用后被删除?

c++ - 为什么valgrind使用GLUT和PORTAUDIO报告我的内存肯定丢失了12或24个字节

opengl-es - WebGL - 如何传递无符号字节顶点属性颜色值?