代码之家  ›  专栏  ›  技术社区  ›  NeoKuro

C++纹理显示不正确:合并为1种颜色

  •  1
  • NeoKuro  · 技术社区  · 9 年前

    然而,在应用纹理时,它似乎取纹理中所有颜色的平均值,然后将该平均值应用于整个立方体。这导致它看起来像是用普通、规则的颜色“绘制”的,如下面的屏幕截图所示:

    这是纹理;

    我不知道为什么会发生这种事。下面是我的init、loadTexture和display函数的代码(我没有编写loadTextture函数):

    初始化函数 (仅显示与立方体+纹理相关的代码) . . . pyramidTexture=TextureLoader::fiLoadTexture(wstring(L“Common\Resources\Textures\sandsone.png”);

    // Setup VAO for pyramid object
        glGenVertexArrays(1, &pyramidVAO);
        glBindVertexArray(pyramidVAO);
    
    // Setup VBO for vertex position data
        glGenBuffers(1, &pyramidVertexBuffer);
        glBindBuffer(GL_ARRAY_BUFFER, pyramidVertexBuffer);
        glBufferData(GL_ARRAY_BUFFER, sizeof(pyramidVertices), pyramidVertices, GL_STATIC_DRAW);
        glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)0); // attribute 0 gets data from bound VBO (so assign vertex position buffer to attribute 0)
    
    // Setup VBO for vertex colour data
        glGenBuffers(1, &pyramidColourBuffer);
        glBindBuffer(GL_ARRAY_BUFFER, pyramidColourBuffer);
        glBufferData(GL_ARRAY_BUFFER, sizeof(pyramidColours), pyramidColours, GL_STATIC_DRAW);
        glVertexAttribPointer(1, 4, GL_FLOAT, GL_TRUE, 0, (const GLvoid*)0); // attribute 1 gets colour data
    
        glGenBuffers(3, &pyramidTexCoordBuffer);
        glBindBuffer(GL_ARRAY_BUFFER, pyramidTexCoordBuffer);
        glBufferData(GL_ARRAY_BUFFER, sizeof(pyramidTexCoordArray), pyramidTexCoordArray, GL_STATIC_DRAW);
        glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)0);
    
    // Enable vertex position and colour + Texture attribute arrays
        glEnableVertexAttribArray(0);
        glEnableVertexAttribArray(1);
        glEnableVertexAttribArray(3);
    
    // Setup VBO for face index array
        glGenBuffers(1, &pyramidIndexBuffer);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, pyramidIndexBuffer);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(pyramidVertexIndices), pyramidVertexIndices, GL_STATIC_DRAW);
    
        glBindVertexArray(0);
    
    
        glEnable(GL_NORMALIZE); // If we scale objects, ensure normal vectors are re-normalised to length 1.0 to keep lighting calculations correct (see lecture notes)
        glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Best colour interpolation results
        .
        .
        .
    }
    

    LoadTexture函数

    GLuint TextureLoader::fiLoadTexture(const wstring& textureFilePath) {
    
        BOOL                fiOkay = FALSE;
        GLuint              newTexture = 0;
        fipImage            I;
    
    // Convert wstring to const char*
        wstring_convert<codecvt_utf8<wchar_t>, wchar_t> stringConverter;
    
        string S = stringConverter.to_bytes(textureFilePath);
        const char *filename = S.c_str();
    
    
    // Call FreeImage to load the image file
        fiOkay = I.load(filename);
    
        if (!fiOkay) {
    
                cout << "FreeImagePlus: Cannot open image file.\n";
                return 0;
        }
    
        fiOkay = I.flipVertical();
        fiOkay = I.convertTo24Bits();
    
        if (!fiOkay) {
    
                cout << "FreeImagePlus: Conversion to 24 bits successful.\n";
                return 0;
        }
    
        auto w = I.getWidth();
        auto h = I.getHeight();
    
        BYTE *buffer = I.accessPixels();
    
        if (!buffer) {
    
                 cout << "FreeImagePlus: Cannot access bitmap data.\n";
                 return 0;
        }
    
    
        glGenTextures(1, &newTexture);
        glBindTexture(GL_TEXTURE_2D, newTexture);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGR, GL_UNSIGNED_BYTE, buffer);
    
        // Setup default texture properties
        if (newTexture) {
    
                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);
        }
    
        return newTexture;
    }
    

    显示功能

    void display(void) {
    
        glClearColor(0.0, 0.0, 0.0, 0.0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
        // Set viewport to the client area of the current window
        glViewport(0, 0, glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
    
        // Get view-projection transform as a GUMatrix4
        GUMatrix4 T = mainCamera->projectionTransform() * mainCamera->viewTransform();
    
        if (principleAxes)
            principleAxes->render(T);
    
        if (texturedQuad)
                texturedQuad->render(T * GUMatrix4::translationMatrix(0.5f, 0.5f, 0.0f));
    
    
    // Fixed function rendering (Compatability profile only) - use this since CGImport is written against OpenGL 2.1
        glUseProgram(0);
    
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glMultMatrixf((const float*)mainCamera->projectionTransform().M);
    
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glMultMatrixf((const float*)mainCamera->viewTransform().M);
        glMultMatrixf((const float*)GUMatrix4::translationMatrix(0.0f, -0.15f, 0.0f).M);
    
        glEnable(GL_TEXTURE_2D);
    
        glPolygonMode(GL_FRONT, GL_FILL);
    
        if (exampleModel)
            exampleModel->renderTexturedModel();
    
        glDisable(GL_TEXTURE_2D);
    
        //Define position and direction (so appear at fixed point in scene)
        glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, lightDirection);
        glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
    
        // enable texturing
        glEnable(GL_TEXTURE_2D);
    
    
        glEnable(GL_LIGHTING);
    
    
        glEnable(GL_LIGHT0);
    //
    // Pyramid VBO rendering
    //
    
        // Use basic shader for rendering pyramid (we'll look at this in more detail next week)
        glUseProgram(basicShader);
    
        static GLint mvpLocationPyramid = glGetUniformLocation(basicShader, "mvpMatrix");
    
        glUniformMatrix4fv(mvpLocationPyramid, 1, GL_FALSE, (const GLfloat*)&(T.M));
    
        GUMatrix4 pyramidModelTransform = GUMatrix4::translationMatrix(-5.75f, 0.0f, 0.0f) * GUMatrix4::scaleMatrix(2.0f, 2.0f, 2.0f);
        GUMatrix4 mvpPyramid = T * pyramidModelTransform;
        glUniformMatrix4fv(mvpLocationPyramid, 1, GL_FALSE, (const GLfloat*)&(mvpPyramid.M));
    
        // Bind VAO that contains all relevant pyramid VBO buffer and attribute pointer bindings
        glBindVertexArray(pyramidVAO);
    
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, pyramidTexture);
        // Draw pyramid
        glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, (const GLvoid*)0);
    
        // Unbind pyramid VAO (or bind another VAO)
        glBindVertexArray(0);
    
    
        glutSwapBuffers();
    }
    

    我已经尝试了几个小时来解决这个问题,但没有任何运气,因此任何支持都将非常感谢!!!

    编辑:添加到VAO属性+着色器中

    // Per-vertex position vectors
    static float pyramidVertices[32] =
    {
      //Front
      0.0f, 0.0f, 0.0f, 1.0f,   //BtmLeft
      1.0f, 0.0f, 0.0f, 1.0f,   //BtmRight
      1.0f, 1.0f, 0.0f, 1.0f,   //TopRight
      0.0f, 1.0f, 0.0f, 1.0f,   //TopLeft
      //Back
      0.0f, 1.0f, 1.0f, 1.0f,   //TopLeft
      1.0f, 1.0f, 1.0f, 1.0f,   //TopRight
      1.0f, 0.0f, 1.0f, 1.0f,   //BottomRight
      0.0f, 0.0f, 1.0f, 1.0f    //BottomLeft
    };
    
    
    // Per-vertex colours (RGBA) floating point values
    static float pyramidColours[32] =
    {
        1.0f, 0.0f, 0.0f, 1.0f,
        0.0f, 1.0f, 0.0f, 1.0f,
        0.0f, 0.0f, 1.0f, 1.0f,
        1.0f, 0.0f, 1.0f, 1.0f,
        0.0f, 1.0f, 1.0f, 1.0f,
        0.0f, 0.0f, 1.0f, 1.0f,
        1.0f, 0.0f, 1.0f, 1.0f,
        1.0f, 0.0f, 0.0f, 1.0f
    };
    
    // 5 faces each with 3 vertices (each face forms a triangle)
    static unsigned short pyramidVertexIndices[36] =
    {
        //Front
        0, 3, 2,
        2, 1, 0,
        //Right
        4, 3, 0,
        0, 7, 4,
        //Back
        4, 7, 6,
        6, 5, 4, 
        //Top
        4, 5, 3,
        3, 5, 2,
        //Left
        2, 5, 1,
        1, 5, 6,
        //Bottom
        6, 7, 0, 
        0, 1, 6
    };
    
    
    static unsigned short pyramidTexCoordArray[24] =
    {
        -1.0f, -1.0f, -1.0f,
        1.0f, -1.0f, -1.0f,
        1.0f, 1.0f, -1.0f,
        -1.0f, 1.0f, -1.0f,
        -1.0f, -1.0f, 1.0f,
        1.0f, -1.0f, 1.0f,
        1.0f, 1.0f, 1.0f,
        -1.0f, 1.0f, 1.0f
    };
    

    顶点着色器

    #version 330
    
    uniform mat4 mvpMatrix;
    
    layout (location=0) in vec4 vertexPos;
    layout (location=3) in vec2 vertexTexCoord;
    
    out vec2 texCoord;
    
    void main(void) {
    
        mat4 M;
        M[0] = vec4(1.0);
    
        ivec2 a = ivec2(1, 2);
        //vec3 b = vec3(2.0, 4.0, 1.0) + a;
    
        texCoord = vertexTexCoord;
        gl_Position = mvpMatrix * vertexPos;
    }
    

    片段着色器

    #version 330
    
    uniform sampler2D texture;
    
    in vec2 texCoord;
    
    layout (location=0) out vec4 fragColour;
    
    void main(void) {
    
        vec4 texColor = texture2D(texture, texCoord);
        fragColour = texColor;
    
    }
    
    2 回复  |  直到 9 年前
        1
  •  3
  •   Yakov Galka    9 年前

    您将数据定义为 unsigned short :

    static unsigned short pyramidTexCoordArray[24]
    

    但这是必须的 float .

        2
  •  1
  •   BDL Vyxzl    9 年前

    有很多奇怪的事情:

    您正在为纹理坐标生成3个VBO,但仅使用一个。除非pyramidTexCoordBuffer是GLuint[3]类型(我假设这不是由于&),你写得太离谱了。

    编辑: 这是指 glGenBuffers(3, &pyramidTexCoordBuffer); 行,它分配3个缓冲区并将它们连续存储三个 GLuint 变量开始于 pyramidTexCoordBuffer 自从 pyramidTexCoordBuffer 很可能是 胶粘 , pyramidTexCoordBuffer[1] pyramidTexCoordBuffer[2] 请参阅未分配内存。

    pyramidTexCoordArray 数组指定为 unsigned short

    glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)0);
    

    数据类型为的行 GL_FLOAT (它不是)并且每个顶点有两个浮点(但数据每个顶点有3个元素):