【问题标题】:Trying to display a texture but only getting a solid color with OpenGL尝试显示纹理但仅使用 OpenGL 获得纯色
【发布时间】:2019-02-15 16:19:27
【问题描述】:

我的目标是显示一个立方体,其纹理取自 png 文件 (DarkDirt.png)。问题是,我只得到一个纯棕色,而且我的照明随着每个三角形形成立方体而变化。

现在,我一直在阅读,我认为这可能与将索引设置为 1 有关,但我没有获得任何成功。我尝试使用 UV 值,但它只会改变照明的行为方式并且不会修复任何问题。所以现在我在想也许我的顶点(代码中的顶点)是错误的?

c++代码,数组:

const GLuint NumVertices = 24;
const GLuint NumTriCubes = 12;
const GLuint NumNormals = 6;
const GLuint NumUvs = 4;

GLfloat uvs[NumUvs][2] = {
    { 0, 0 },
    { 1, 0 },
    { 0, 1 },
    { 1, 1 },
};

GLfloat vertices[NumVertices][3] = {
    //Front
    { -0.5f, -0.5f, 0.5f }, //0
    { 0.5f, -0.5f, 0.5f }, //1
    { 0.5f, 0.5f, 0.5f }, //2
    { -0.5f, 0.5f, 0.5f }, //3

    //Right
    { 0.5f, -0.5f, 0.5f }, //4
    { 0.5f, -0.5f, -0.5f }, //5
    { 0.5f, 0.5f, -0.5f }, //6
    { 0.5f, 0.5f, 0.5f }, //7

    //Back
    { -0.5f, -0.5f, -0.5f },  //8
    { -0.5f, 0.5f, -0.5f }, //9
    { 0.5f, 0.5f, -0.5f }, //10
    { 0.5f, -0.5f, -0.5f }, //11

    //Left
    { -0.5f, -0.5f, 0.5f }, //12
    { -0.5f, 0.5f, 0.5f }, //13
    { -0.5f, 0.5f, -0.5f }, //14
    { -0.5f, -0.5f, -0.5f }, //15

    //Upper
    { -0.5f, 0.5f, 0.5f }, //16
    { 0.5f, 0.5f, 0.5f }, //17
    { 0.5f, 0.5f, -0.5f }, //18
    { -0.5f, 0.5f, -0.5f }, //19

    //Bottom
    { -0.5f, -0.5f, 0.5f }, //20
    { -0.5f, -0.5f, -0.5f }, //21
    { 0.5f, -0.5f, -0.5f }, //22
    { 0.5f, -0.5f, 0.5f }, //23

};

GLuint vertexIndices[NumTriCubes][3] = {
    //Front
    { 0, 1, 2 },
    { 0, 2, 3 },

    //Right
    { 4, 5, 6 },
    { 4, 6, 7 },

    //Back
    { 8, 9, 10 },
    { 8, 10, 11 },

    //Left
    { 12, 13, 14 },
    { 12, 14, 15 },

    //Upper
    { 16, 17, 18 },
    { 16, 18, 19 },

    //Bottom
    { 20, 21, 22 },
    { 20, 22, 23 }
};

GLfloat normals[NumVertices][3] = {

    //Front
    { 0.0f, 0.0f, 1.0f},
    { 0.0f, 0.0f, 1.0f},
    { 0.0f, 0.0f, 1.0f},
    { 0.0f, 0.0f, 1.0f},

    //Right
    { 1.0f, 0.0f, 0.0f},
    { 1.0f, 0.0f, 0.0f},
    { 1.0f, 0.0f, 0.0f},
    { 1.0f, 0.0f, 0.0f},

    //Back
    { 0.0f, 0.0f, -1.0f},
    { 0.0f, 0.0f, -1.0f},
    { 0.0f, 0.0f, -1.0f},
    { 0.0f, 0.0f, -1.0f},

    //Left
    { -1.0f, 0.0f, 0.0f},
    { -1.0f, 0.0f, 0.0f},
    { -1.0f, 0.0f, 0.0f},
    { -1.0f, 0.0f, 0.0f},

    //Upper
    { 0.0f, 1.0f, 0.0f},
    { 0.0f, 1.0f, 0.0f},
    { 0.0f, 1.0f, 0.0f},
    { 0.0f, 1.0f, 0.0f},

    //Bottom
    { 0.0f, -1.0f, 0.0f},
    { 0.0f, -1.0f, 0.0f},
    { 0.0f, -1.0f, 0.0f},
    { 0.0f, -1.0f, 0.0f}

};


c++代码,我在draw()函数中绑定纹理:

    m_texture->bind();

c++代码,初始化:

    glGenBuffers(NumBuffers, m_Buffers);
    glBindBuffer(GL_ARRAY_BUFFER, m_Buffers[VBO_Cube]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices)+ sizeof(uvs) + sizeof(normals), nullptr, GL_STATIC_DRAW);
    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
    glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertices), sizeof(uvs), uvs);
    glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertices) + sizeof(uvs), sizeof(normals), normals);

...

    glEnableVertexAttribArray(GLuint(m_vNormalLocation));
    glVertexAttribPointer(GLuint(m_vNormalLocation), 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(vertices)));

    glVertexAttribPointer(GLuint(m_vUVLocation), 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(vertices)));
    glEnableVertexAttribArray(GLuint(m_vUVLocation));

...
    m_texture = new QOpenGLTexture(QImage("DarkDirt.png").mirrored());
    m_texture->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear);
    m_texture->setMagnificationFilter(QOpenGLTexture::Linear);

我试图让纹理显示在立方体的每一侧。所以它会给我一个“污垢立方体”,例如在我的世界中。但是,是的,现在它只显示为一个实心的棕色立方体,到处都是灯光。任何帮助将不胜感激。谢谢!

【问题讨论】:

    标签: c++ qt opengl


    【解决方案1】:

    每个顶点坐标都需要一个纹理坐标属性。由于您有 24 (4*6) 个顶点坐标,因此您也需要 24 个纹理坐标属性:

    const GLuint NumUvs = 24;
    GLfloat uvs[NumUvs][2] = {
        { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 },
        { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 },
        { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 },
        { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 },
        { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 },
        { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 }
    };
    

    法向量的偏移量计算错误:

    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
    glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertices), sizeof(uvs), uvs);
    glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertices) + sizeof(uvs), sizeof(normals), normals);
    
    glVertexAttribPointer(GLuint(m_vNormalLocation), 3, GL_FLOAT, GL_FALSE, 0,
          BUFFER_OFFSET(sizeof(vertices)));
    

    必须是:

    glVertexAttribPointer(GLuint(m_vNormalLocation), 3, GL_FLOAT, GL_FALSE, 0, 
        BUFFER_OFFSET(sizeof(vertices) + sizeof(uvs)));
    

    您的程序中似乎从未设置纹理坐标的属性索引(m_vUVLocation)。

    可以通过QOpenGLShaderProgram::attributeLocation获取某个属性的属性索引:

    m_vUVLocation = m_programRender->attributeLocation("vUV");
    

    glGetAttribLocation 的原生 OpenGL:

    m_vUVLocation = glGetAttribLocation(m_programRender->programId(), "vUV");
    

    注意,也可以使用GLSL Layout Qualifiers在shader代码中定义属性位置:

    例如顶点着色器:

    #version 400 core
    
    layout(location = 0) in vec4 vPosition;
    layout(location = 1) in vec4 vColor;
    layout(location = 2) in vec3 vNormal;
    layout(location = 3) in vec2 vUV;
    

    在这种情况下,m_vUVLocation 的值将是 3。

    【讨论】:

    • 非常感谢,它有效!我最近在 OpenGL 上遇到了很多困难,但你帮我弄清楚了一些事情。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多