纹理无法填充图形-OpenGL

问题描述

我正在尝试在整个窗口上显示图像。 为此,我只绘制一个矩形,该矩形将整个窗口并为其应用纹理。

问题是图像根本无法填满整个屏幕: Output image

图像不是太小,因为它是5600 x3000。而且,我也不想重复图像。我不是我想念的东西,为什么它没有填满屏幕,为什么它只在左上角。我已经尝试过此解决方案,但无法正常工作:Texture does not fit in the square - OpenGL

这是我创建和绑定着色器的方法

Shader::Shader(const char* vertSrcFile,const char* fragSrcFile,const char* texSrcFile) {
    gluint vertShader = glCreateShader(GL_VERTEX_SHADER);
    gluint fragShader = glCreateShader(GL_FRAGMENT_SHADER);

    GLint vlen;
    GLint flen;
    char* source = loadFile(vertSrcFile,vlen);
    char* fragment = loadFile(fragSrcFile,flen);

    glShaderSource(vertShader,1,&source,&vlen);
    glShaderSource(fragShader,&fragment,&flen);

    GLint compiled = 0;
    glCompileShader(vertShader);
    glGetShaderiv(vertShader,GL_COMPILE_STATUS,&compiled);
    if (!compiled) {
        GLint maxLength = 0;
        glGetShaderiv(vertShader,GL_INFO_LOG_LENGTH,&maxLength);

        // The maxLength includes the NULL character
        std::vector<GLchar> infoLog(maxLength);
        glGetShaderInfoLog(vertShader,maxLength,&maxLength,&infoLog[0]);

        // We don't need the shader anymore.
        glDeleteShader(vertShader);

        Logger::GetSystemLogger()->error("Vertex shader compilation error");
        Logger::GetSystemLogger()->error("{}",infoLog.data());

        return;
    }

    glCompileShader(fragShader);
    glGetShaderiv(fragShader,&compiled);
    if (!compiled) {
        GLint maxLength = 0;
        glGetShaderiv(fragShader,&maxLength);

        // The maxLength includes the NULL character
        std::vector<GLchar> infoLog(maxLength);
        glGetShaderInfoLog(fragShader,&infoLog[0]);

        // We don't need the shader anymore.
        glDeleteShader(fragShader);

        Logger::GetSystemLogger()->error("Fragment shader compilation error");
        Logger::GetSystemLogger()->error("{}",infoLog.data());

        return;
    }

    prog = glCreateProgram();

    glAttachShader(prog,vertShader);
    glAttachShader(prog,fragShader);

    glLinkProgram(prog);
    GLint isLinked = 0;
    glGetProgramiv(prog,GL_LINK_STATUS,(int*)&isLinked);
    if (isLinked == GL_FALSE)
    {
        GLint maxLength = 0;
        glGetProgramiv(prog,&maxLength);

        // The maxLength includes the NULL character
        std::vector<GLchar> infoLog(maxLength);
        glGetProgramInfoLog(prog,&infoLog[0]);

        // We don't need the program anymore.
        glDeleteProgram(prog);
        // Don't leak shaders either.
        glDeleteShader(vertShader);
        glDeleteShader(fragShader);

        Logger::GetSystemLogger()->error("Program link error");
        Logger::GetSystemLogger()->error("{}",infoLog.data());
        return;
    }

    glDetachShader(prog,vertShader);
    glDetachShader(prog,fragShader);

    glGenTextures(1,&texID); // generate texture ID

    glBindTexture(GL_TEXTURE_2D,texID);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_BORDER);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_BORDER);

    LoadTexture(texSrcFile);
}

这是我将图像加载为纹理的方式:

void Shader::LoadTexture(const char* texSrcFile) const {
        int width,height,nrChannels;
        unsigned char* data = stbi_load(texSrcFile,&width,&height,&nrChannels,0);
        if (data)
        {
            glTexImage2D(GL_TEXTURE_2D,GL_RGB,width,GL_UNSIGNED_BYTE,data);
            glGenerateMipmap(GL_TEXTURE_2D);
        }
        else
        {
            Logger::GetSystemLogger()->error("Failed to load textures");
        }
        stbi_image_free(data);
    }

这是我的着色器: 片段:

#version 330
precision highp float; // needed only for version 1.30

layout(location = 0) out vec4 out_Color;

in vec2 ex_Tex;

uniform sampler2D textureUnit0;

void main(void){
    out_Color = texture(textureUnit0,ex_Tex);
}

顶点:

#version 330

layout (location = 0) in vec3 in_Position;
layout (location = 1) in vec2 in_Tex;

out vec2 ex_Tex;

void main(void){
    gl_Position = vec4(in_Position,1.0);
    
    ex_Tex = in_Tex;
}

这是主要代码

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

glGenBuffers(1,&m_VBO);
glBindBuffer(GL_ARRAY_BUFFER,m_VBO);

GLfloat vertices[4 * 5]{
      // Positions           // Textures
    -1.0f,-1.0f,0.0f,1.0f,0.0f
};

glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);

// Position
glEnabLevertexAttribArray(0);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,5 * sizeof(float),nullptr);

// Texture coord
glEnabLevertexAttribArray(1);
glVertexAttribPointer(1,2,nullptr);

glGenBuffers(1,&m_IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,m_IBO);

unsigned int indices[6] = { 0,3 };
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),indices,GL_STATIC_DRAW);

m_Shader = std::make_shared<Engine::Shader>("src/Shaders/Background.vert","src/Shaders/Background.frag","res/background.jpg");

这是主循环

while (m_Running) {
    // clear the screen and set the background color to grey
    glClearColor(0.5f,0.5f,1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    m_Shader->Bind();

    glBindTexture(GL_TEXTURE_2D,m_Shader->GetTexID());
    glBindVertexArray(m_VAO);
    glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,nullptr);

    m_Window->OnUpdate();
}

解决方法

尽管视口坐标从负1变为一[-1,1),但是纹理坐标从零变为1 [0,1)。因此,根据GL_CLAMP_TO_BORDER政策,视口的四分之三被黑色填充。

您需要按以下步骤修正VAO坐标:

GLfloat vertices[4 * 5]{
      // Positions           // Textures
    -1.0f,-1.0f,0.0f,1.0f,0.0f
};

编辑:您的纹理坐标偏移也不正确。应该是:

// Texture coord
glEnableVertexAttribArray(1);
glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,5 * sizeof(float),(void*)(3*sizeof(float)));

如果没有适当的偏移,它将使用纹理坐标位置的X和Y。