openGL - 无法显示图像

openGL - failed to display an images

学习使用 QOpenGLWidget 显示图像。但是,我遇到了一些问题。

  1. 如何将 GLuint texture 变量(从图像加载的实际纹理)传递给着色器脚本?比如如何将 GLuint texture 绑定到 uniform sampler2D texture?也许我只是没有意识到我已经这样做了。
  2. attribute vec4 vertexColorInuniform sampler2D texture 有什么区别?我认为颜色来自纹理。
  3. 我可以使用 glTexCoord2f()glVertex2f() 代替 glVertexAttribPointer()glVertexAttribPointer() 吗?因为他们对我来说更好。

虽然我做了很多研究,但我仍然不清楚 openGL 如何显示图像的概念。我不确定自己做错了什么。图片没有显示。

MyGLWiget.cpp

着色器脚本:

#define STR(x) #x
#define VS_LOCATION 0
#define FS_LOCATION 1

const char* vertextShader = STR(
    attribute vec4 position;
    attribute vec4 vertexColorIn;
    varying vec4 vertexColorOut;
    void main(void)
    {
        gl_Position = position;
        vertexColorOut = vertexColorIn;
    }
);

const char* fragmentShader = STR(
    varying vec4 vertexColorOut;
    uniform sampler2D texture;
    void main(void)
    {
        ??? = texture2D(???, textureOut).r // no clue how to use it
        gl_FragColor = vertexColorOut;
    }   
);

正在加载图像纹理:

void MyGLWiget::loadTexture(const char* file_path)
{
    img_data = SOIL_load_image(file_path, &width, &height, &channels, SOIL_LOAD_RGB);

    glEnable(GL_TEXTURE_2D);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, img_data);

    SOIL_free_image_data(img_data);
}

初始化:

void MyGLWiget::initializeGL()
{
    initializeOpenGLFunctions();

    program.addShaderFromSourceCode(QGLShader::Vertex, vertextShader);
    program.bindAttributeLocation("position", VS_LOCATION);

    program.addShaderFromSourceCode(QGLShader::Fragment, fragmentShader);
    program.bindAttributeLocation("vertexColorIn", FS_LOCATION);

    program.link();
    program.bind();


    static const GLfloat ver[] = {
        -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f
    };

    static const GLfloat  tex[] = {
        0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f
    };

    glVertexAttribPointer(VS_LOCATION, 2, GL_FLOAT, 0, 0, ver);
    glEnableVertexAttribArray(VS_LOCATION);

    glVertexAttribPointer(FS_LOCATION, 2, GL_FLOAT, 0, 0, tex);
    glEnableVertexAttribArray(FS_LOCATION);

    program.setUniformValue("texture", texture); 
    //texture = program.uniformLocation("texture");
}

paintGL:

这部分我真的很困惑。我不知道我应该用什么来制作它来绘制图像。

void MyGLWiget::paintGL()
{
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, img_data);
    glUniform1i(texture, 0);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 1);
}

How can I pass the GLuint texture variable (the actual texture loaded from the image) into the shader scripts? Like how to bind GLuint texture to uniform sampler2D texture? Maybe I am just not realising I already did that.

这会将纹理绑定到纹理单元 0:

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);

这是无效的,因为texture不是一个统一的位置,所以删除这一行:

glUniform1i(texture, 0); // <-- invalid

这也是无效的,因为统一texture应该设置为纹理单元的编号:

program.setUniformValue("texture", texture); // <-- invalid

所以替换为:

program.setUniformValue("texture", 0); // <-- sampler2D texture uses GL_TEXTURE0

注意:我在这里假设 setUniformValue 工作正常。


What's the difference between attribute vec4 vertexColorIn and uniform sampler2D texture? I think the color comes from the texture.

vertexColorIn 来自 VAO,每个顶点都不同。 texture 是从绑定到您上面设置的纹理单元的纹理中采样的采样器。

在您的代码中您不需要顶点颜色,但您确实需要纹理坐标。所以你的着色器应该看起来像:

const char* vertextShader = STR(
    attribute vec4 position;
    attribute vec4 texcoordIn;
    varying vec4 texcoordOut;
    void main(void)
    {
        gl_Position = position;
        texcoordOut = texcoordIn;
    }
);

const char* fragmentShader = STR(
    varying vec4 texcoordOut;
    uniform sampler2D texture;
    void main(void)
    {
        gl_FragColor = texture2D(texture, texcoordOut);
    }   
);

Can I use glTexCoord2f() and glVertex2f() instead of glVertexAttribPointer() and glVertexAttribPointer()? It's because they seem better to me.

glTexCoord2fglVertex2f 是已在 OpenGL 3 中删除的遗留函数,仅在兼容性配置文件中可用。你不应该使用它们。


这几行在错误的地方:

 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

绑定纹理后它们会消失:

 glGenTextures(1, &texture);
 glBindTexture(GL_TEXTURE_2D, texture);
 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, img_data);
 // sets the filtering for the bound texture:
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

由于问题已标记:在这种情况下您不需要设置任何制服。您可以直接在着色器中指定位置和绑定:

const char* vertextShader =
    "#version 450 core\n" STR(
    layout(location = 0) in vec4 position;
    layout(location = 1) in vec4 texcoordIn;
    layout(location = 0) out vec4 texcoordOut;
    void main(void)
    {
        gl_Position = position;
        texcoordOut = texcoordIn;
    }
);

const char* fragmentShader =
    "#version 450 core\n" STR(
    layout(location = 0) in vec4 texcoord;
    layout(binding = 0) uniform sampler2D TEX;
    layout(location = 0) out vec4 OUT;
    void main(void)
    {
        OUT = texture(TEX, texcoord);
    }   
);

一些编辑

   const char* vertextShader = STR(
    attribute vec4 position;
    attribute vec4 vertexColorIn;
    varying vec4 vertexColorOut;
    out vec2 TexCoord;//--->add
    void main(void)
    {
        gl_Position = position;
        vertexColorOut = vertexColorIn;
        TexCoord = vec2(aPos.x/2.0+0.5, 0.5-aPos.y/2.0);//a hack,ideally you need to pass the UV coordinates for proper texture mapping.UVs need to be passed in as a uniform or an attribute depending on preference.
    }
);

const char* fragmentShader = STR(
    varying vec4 vertexColorOut;
    uniform sampler2D texture;
    in vec2 TexCoord; //---->add
    void main(void)
    {
        gl_FragColor  = texture2D(texture,TexCoord) //( no clue how to use it) -->here is the change
        //gl_FragColor = vertexColorOut;
    }   
);