提问者:小点点

纹理加载问题OpenGL无法找出原因


我有麻烦应用纹理到一个图像。我就是找不到问题所在

没有纹理代码,代码可以正常工作。

主文件:

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <filesystem>
#include <stb_image.h>

#include "Shaders/Shader.h"


bool isWireFrame = false;

const int SCREEN_WIDTH = 1280;
const int SCREEN_HEIGHT = 720;

void framebufferCallBack(GLFWwindow* window, int width, int height)
{
    glViewport(0, 0, width, height);
}

void keyCallBack(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
    {
        isWireFrame = !isWireFrame;
    }
}

int main(void)
{
    GLFWwindow* window;
    /* Initialize the library */

    if (!glfwInit())
    {
        std::cout << "GLFW did not init!" << std::endl;
        return EXIT_FAILURE;
    }
    /* Create a windowed mode window and its OpenGL context */
    window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Hello World", NULL, NULL);
    if (window == NULL)
    {
        glfwTerminate();
        return EXIT_FAILURE;
    }

    /* Make the window's context current */
    glfwMakeContextCurrent(window);

    GLenum err = glewInit();
    if (GLEW_OK != err)
    {
        /* Problem: glewInit failed, something is seriously wrong. */
        std::cerr << "Error: " << glewGetErrorString(err) << std::endl;
        return EXIT_FAILURE;
    }
    std::cerr << "Status: Using GLEW " << glewGetString(GLEW_VERSION) << std::endl;


    /*
     We have to tell OpenGL the size of the rendering window so OpenGL knows how we want to display the data and coordinates with respect to the window. We can set those dimensions via the glViewport function
    */
    glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);

    glfwSetFramebufferSizeCallback(window, framebufferCallBack);
    glfwSetKeyCallback(window, keyCallBack);

    Shader shader("Shaders/glsl/vert.glsl", "Shaders/glsl/frag.glsl");

    float vertices[] = {
       // positions         // tex coords
       0.5f,  0.5f, 0.0f,   1.0f, 1.0f,               // top right
       0.5f, -0.5f, 0.0f,   1.0f, 0.0f,               // bottom right
      -0.5f, -0.5f, 0.0f,   0.0f, 0.0f,               // bottom left
      -0.5f,  0.5f, 0.0f,   0.0f, 1.0f                // top left 
    };

    unsigned int indices[] = {
        0, 1, 3,
        1, 2, 3

    };

    unsigned int VBO, VAO, EBO, texture;

    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);

    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glGenBuffers(1, &EBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);

    glEnable(GL_TEXTURE_2D);

    glGenTextures(1, &texture);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture);


    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);


    int width, height, nrChannels;
    unsigned char* data = stbi_load("Images/Crate.png", &width, &height, &nrChannels, 0);
    if (data)
    {
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
        glGenerateMipmap(GL_TEXTURE_2D);
    }
    else 
    {
        std::cout << "Failed to load the texture" << std::endl;
    }
    stbi_image_free(data);

    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_TEXTURE_2D, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);


    /* Loop until the user closes the window */
    while (!glfwWindowShouldClose(window))
    {
        /* Render here */
        glClear(GL_COLOR_BUFFER_BIT);
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);

        float timeValue = glfwGetTime();
        float greenValue = (sin(timeValue) / 2.0f) + 0.5f;
        Vector4 colour(0.0f, greenValue, 0.0f, 1.0f);

        glBindTexture(GL_TEXTURE_2D, texture);


        shader.use();
        shader.setVec4("Colour", colour);
        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, sizeof(indices) / sizeof(int), GL_UNSIGNED_INT, 0);

        glDrawArrays(GL_TRIANGLES, 0, 3);

        /* Swap front and back buffers */
        glfwSwapBuffers(window);

        /* Poll for and process events */
        glfwPollEvents();

        if (isWireFrame == true)
        {
            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        }
        else if (isWireFrame == false)
        {
            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        }

    }

    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    glDeleteBuffers(1, &EBO);
    glDeleteProgram(shader.ID);

    glfwTerminate();
    return 0;
}

片段着色器:

#version 330 core

out vec4 fragColour;

uniform vec4 Colour;

in vec2 TexCoord;

uniform sampler2D Texture;

void main()
{
    fragColour = texture(Texture, TexCoord);
} 

顶点着色器:

#version 330 core

layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;

out vec2 TexCoord;

void main()
{
    gl_Position = vec4(aPos.xyz, 1.0);
    TexCoord = aTexCoord;
}

没有错误。

这是我画的对象。

这是我想要绘制的实际图像:

图像应该是一个矩形,但它是一个三角形,我不知道为什么会这样,也许这一点信息可以帮助。

编辑,所以我发现我没有使用正确的使用正确的颜色格式

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);

但在format参数为gl_rgb而不是gl_rgba之前

但现在我有了一个半绘制的纹理:


共1个答案

匿名用户

步幅的论点是错误的。您的属性包含5个组件(x,y,z,u,v)。因此stride是5*sizeof(float)而不是8*sizeof(float)

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);

默认情况下,OpenGL假定图像的每一行的开头是4个字节。这是因为GL_UNPACK_ALIGNING参数默认为4。
由于图像有3个颜色通道(GL_RGB),并且压缩得很紧,图像的行大小可能无法对齐为4个字节。

当将具有3个颜色通道的RGB图像加载到纹理对象且3*width不能被4整除时,GL_UNPACK_ALIGNING必须设置为1:

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);