【问题标题】:opengl 2d game only drawing second sprite texture and not firstopengl 2d游戏只绘制第二个精灵纹理而不是第一个
【发布时间】:2017-07-29 12:28:03
【问题描述】:

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

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

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

渲染器.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 中输入 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 还是 OpenGL ES 并相应地编辑标签。
  • @Reaper 抱歉,我关闭了 openGL ES。它是openGL
  • @Rabbid76 哦,对不起。我是新的,我会忘记发布一些东西。它设置在我的 Renderer::Init() 函数中,该函数在 GLuint uniformLocation = this-&gt;shaderProgram.GetUniformLocation("basicTexture"); 之前被调用并使用 glUniform1i(uniformLocation, 0) 设置
  • @Rabbid76 我使用的是矢量 3D 而不是 2D,因为我不确定以后是否需要 z 值用于某种排序技术(这是我第一次尝试游戏我边走边学)。
  • @Rabbid76 是的。它似乎只绘制指定的最后一个精灵纹理

标签: c++ opengl graphics2d


【解决方案1】:

所以我想这对任何渴望学习和使用 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 存储顶点属性信息,因此您不必每次都指定顶点属性指针函数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-20
    • 2015-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多