opengl 2d 游戏只绘制第二个精灵纹理而不是第一个

opengl 2d game only drawing second sprite texture and not first

我目前正在使用 OpenGL 创建一个 2d 格斗游戏,我遇到了一个问题 运行 OpenGL 只在我最后一次初始化的精灵位置上绘制,不管我初始化并尝试绘制了多少精灵.即使我初始化 sprite1sprite2 但只绘制 sprite1sprite 仍然会被绘制。它从我的 sprite class 开始,我在屏幕上初始化我想要我的图像的位置以及要使用的图像:

Sprite.cpp

 Init(int screenCoordinateX, int screenCoordinateY, uint imageWidth, unsigned int imageHeight, std::string imageFilePath)
{
    //casting to float since GLSL shader variables vec2,3,4 require vertex data to be in floats
    this->x = static_cast<float>(x);
    this->y = static_cast<float>(y);
    this->width = static_cast<float>(width);
    this->height = static_cast<float>(height);

    glGenBuffers(1, &vboID);

    Blz::Graphics::GLTexture texture(imageFilePath);
    this->texture = texture;

    float halfWidth = this->width / 2;

    //Setting sprite origin at bottom middle of image by subtracting half width 
    this->vertexData.at(0).SetPosition(glm::vec3{ this->x + (this->width - halfWidth), this->y + this->height, 0.0f });//Top right corner
    this->vertexData.at(1).SetPosition(glm::vec3{ this->x - halfWidth, this->y + height, 0.0f });//Top left corner
    this->vertexData.at(2).SetPosition(glm::vec3{ this->x - halfWidth, this->y, 0.0f });//Bottom left corner
    this->vertexData.at(3).SetPosition(glm::vec3{ this->x - halfWidth, this->y, 0.0f });//Bottom left corner
    this->vertexData.at(4).SetPosition(glm::vec3{ this->x + (this->width - halfWidth), this->y, 0.0f });//Bottom right corner
    this->vertexData.at(5).SetPosition(glm::vec3{ this->x + (this->width - halfWidth), this->y + this->height, 0.0f });//Top right corner

    this->vertexData.at(0).SetUV(glm::vec2{ 1.0f, 1.0f });
    this->vertexData.at(1).SetUV(glm::vec2{ 0.0f, 1.0f });
    this->vertexData.at(2).SetUV(glm::vec2{ 0.0f, 0.0f });
    this->vertexData.at(3).SetUV(glm::vec2{ 0.0f, 0.0f });
    this->vertexData.at(4).SetUV(glm::vec2{ 1.0f, 0.0f });
    this->vertexData.at(5).SetUV(glm::vec2{ 1.0f, 1.0f });

    glBindBuffer(GL_ARRAY_BUFFER, vboID);
    glBufferData(GL_ARRAY_BUFFER, (sizeof(Vector3D) * this->vertexData.size()), &this->vertexData.front(), GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3D), (void*)offsetof(Vector3D, position));
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vector3D), (void*)offsetof(Vector3D, textureCoordinates));

    //Unbind 
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

然后我尝试像这样渲染传递给渲染器的精灵:

Renderer.cpp

void Renderer::Draw(Sprite& sprite)
{
    glm::mat4 orthoProjection = glm::ortho(0.0f, static_cast<sfloat>(1024), 0.0f, static_cast<sfloat>(768));
    GLuint transformationMatrixUniformLocation = this->shaderProgram.GetUniformLocation("transformationMatrix");

    glUniformMatrix4fv(transformationMatrixUniformLocation, 1, GL_FALSE, &(orthoProjection[0][0]));

    glBindTexture(GL_TEXTURE_2D, sprite.texture.id);
    glBindBuffer(GL_ARRAY_BUFFER, sprite.vboID);

    glDrawArrays(GL_TRIANGLES, 0, 6);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

这是我的 main.cpp 我开始调用所有内容的地方:

int main() 
{
    Blz::Graphics::Renderer renderer;
    Blz::Window window;
    Blz::Input input;
    Scene scene;

    window.Initialize();
    renderer.Init();

    Sprite sprite1;
    sprite.Init(900, 300, 200, 200, "CharImage.png");

    Sprite sprite2;
    sprite2.Init(100, 100, 200, 200, "CharImage.png");

    while (!input.IsKeyPressed(SDLK_ESCAPE))
    {
        window.ClearBuffers();

        renderer.Draw(sprite1);

        window.SwapBuffers();
    }

    return 0;
}

因此,即使我要求绘制 sprite1,屏幕上也只会绘制 100x 100y 的 sprite2 位置。即使我手动尝试在 renderer.cpp 中输入 1 的 vboID(即 sprite1vboID),它仍然绘制 sprite2 的位置。我做错了什么?

如有必要,这是我的着色器:

VertexShader.glsl

#version 430

in vec3 vertexPosition;
in vec2 textCoord;

out vec2 TextureCoord;

uniform mat4 transformationMatrix;

void main()
{
    vec4 position = vec4(vertexPosition, 1.0f);
    gl_Position = transformationMatrix * position;
    TextureCoord = textCoord;
};

FragmentShader.glsl

#version 430

out vec4 daColor;
in vec2 TextureCoord;

uniform sampler2D basicTexture;

void main()
{
    vec4 texel = texture(basicTexture, TextureCoord);
    daColor = texel;
};

所以我想这对任何有志于学习和使用 OpenGL 的人来说都是一堂课。任何时候您使用 VBO 和 vbo id 绑定 OpenGL 缓冲区,您还需要在绘制之前再次指定您的顶点属性指针。所以我的新 renderer.cpp 文件如下所示:

void Renderer::Draw(Sprite& sprite)
{
    glm::mat4 orthoProjection = glm::ortho(0.0f, static_cast<sfloat>(1024), 0.0f, static_cast<sfloat>(768));
    GLuint transformationMatrixUniformLocation = this->shaderProgram.GetUniformLocation("transformationMatrix");

    glUniformMatrix4fv(transformationMatrixUniformLocation, 1, GL_FALSE, &(orthoProjection[0][0]));

    glBindTexture(GL_TEXTURE_2D, sprite.texture.id);
    glBindBuffer(GL_ARRAY_BUFFER, sprite.vboID);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3D), (void*)offsetof(Vector3D, position));
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vector3D), (void*)offsetof(Vector3D, textureCoordinates));

    glDrawArrays(GL_TRIANGLES, 0, 6);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

另一个 SO 答案给出了原因:is VertexAttribPointer needed after each BindBuffer?。为避免这种情况,您可以使用较新的 VAO,它存储顶点属性信息,这样您就不必每次都指定 vertexattribpointer 函数。