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

时间:2017-07-29 12:28:03

标签: c++ opengl graphics2d

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

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,只有sprite2在100x 100y的位置会被吸引到屏幕上。即使我手动尝试在renderer.cpp中输入vboID为1(vboID sprite1},它仍会绘制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;
};

1 个答案:

答案 0 :(得分:0)

所以我想这对任何有志于学习和使用OpenGL的人来说都是一个教训。无论何时使用VBO和vbo id将OpenGL缓冲区绑定到您,还需要在绘制之前再次指定vertexattribpointers。所以我的新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);
}

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