0
\$\begingroup\$

I'm currently creating a 2d fighting game utilizing OpenGL and I have run into a problem where OpenGL is only drawing at my last initialized sprite position, regardless of how many sprites I initialize and try and draw. Even when I initialize a sprite1 and sprite2 but only draw sprite1, sprite2 is what will still be drawn. It starts with my sprite class where I initialize where on the screen I want my image as well as what image to use:

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);
}

I then try and render sprites passed in to renderer like so:

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);
}

I here is my main.cpp where I begin to call everything:

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;
}

So even though I ask for sprite1 to be drawn, only sprite2's position at 100x 100y gets drawn to the screen. Even if I manually try and enter a vboID of 1 (which is the vboID of sprite1) within renderer.cpp, it still draws sprite2's position. What am I doing wrong?

Here are my Shaders if necessary:

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;
};
\$\endgroup\$
0
\$\begingroup\$

You are calling glVertexAttribPointer in Sprite.Init. So it makes sense that the last sprite initiated will be rendered, since that sprite's vertices are being pointed to.

Instead, one way to handler this is to create a method for Sprite called Render (I don't write in C++, so please excuse any case errors!). Call this method in your render loop, and call glVertexAttribPointer in the method. Then, the order in which you initiate the sprites won't matter.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.