OpenGL - 缓冲区更新下一个渲染对象

问题描述 投票:0回答:1

Okej,所以我有一个非常奇怪的情况,我有三个(或两个,无关紧要)对象,其中一个更新其缓冲区为“动画”。换句话说,一个物体在移动而另一个物体静止不动。奇怪的部分在移动物体移动时进入,但在移动物体之后渲染的物体是精确的动画。移动物体移动但不动画。希望它有意义。

现在一些代码,因为我有故障排除它是缓冲相关我将这些部分:

Object::Object() {
    ...
    glGenVertexArrays(1, &VAO_);
    glGenBuffers(2, VBO_); 
    glGenBuffers(1, &EBO_);

    glBindVertexArray(VAO_);

    glBindBuffer(GL_ARRAY_BUFFER, VBO_[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 4 * 3, vertices, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
    glEnableVertexAttribArray(0);  

    glBindBuffer(GL_ARRAY_BUFFER, VBO_[1]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 4 * 2, tex_vert, GL_STREAM_DRAW);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
    glEnableVertexAttribArray(1);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO_);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * 6, indices, GL_STATIC_DRAW);

    glBindVertexArray(0);                       // unbind vertex
    glBindBuffer(GL_ARRAY_BUFFER, 0);           // unbind buffer
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);   // unbind buffer
}
void Object::Update() {
    ...
    glBindBuffer(GL_ARRAY_BUFFER, VBO_[1]);
    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float) * 4 * 2, tex_vert);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void Object::Render() {
    ...
    glUseProgram(Shader_.GetProgramID());
    glBindVertexArray(VAO_);
    glBindTexture(GL_TEXTURE_2D, Texture_);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);
}

int Main() {
    Object m();
    Object m2();
    Object m3();
    while (!glfwWindowShouldClose(engine.window)) {
        ...
        m.Update();
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        m.Render();
        m3.Render();
        m2.Render();
        glfwSwapBuffers(window);
        ...
    }
}

所以m3得到了格式化,但是m正在移动,如果m3和m2的变化位置,m2将会变得生动。如果我不渲染m2 / m3,m将获得动画和移动。值得一提的是,所有非动画对象都会获得纹理,但会保持初始状态,所以一开始看起来都很好。

VAO,VBO和EBO为每个对象获得了不同的值,但是“错误”缓冲区(VBO_ [1])得到了更新。

我想我尝试了解决这个问题的大多数错误方法,所以如果有人能指出我正确的方向,我将非常感激。

编辑:

有关如何填充缓冲区的添加信息等。

void Object::Update() {
    if (Keyboard::KeyPressed(GLFW_KEY_W)) {
        if (MovementY_ < 0) {
            MovementY_ = 0;
        }
        MovementY_ += MovementSpeed_ * Engine::GetDeltaTime();

        TextureTopLeft_      = glm::vec2((MALE_TEXTURE_SIZE_S * SpriteFrame_) - MALE_TEXTURE_SIZE_S,    MALE_UP_STAND_T - MALE_TEXTURE_SIZE_T);
        TextureTopRight_     = glm::vec2((MALE_TEXTURE_SIZE_S * SpriteFrame_),                          MALE_UP_STAND_T - MALE_TEXTURE_SIZE_T);
        TextureBottomLeft_   = glm::vec2((MALE_TEXTURE_SIZE_S * SpriteFrame_) - MALE_TEXTURE_SIZE_S,    MALE_UP_STAND_T);
        TextureBottomRight_  = glm::vec2((MALE_TEXTURE_SIZE_S * SpriteFrame_),                          MALE_UP_STAND_T);
    }
    float tex_vert[4][2] = {
        {TextureTopRight_.s,      TextureTopRight_.t},
        {TextureBottomRight_.s,   TextureBottomRight_.t},
        {TextureBottomLeft_.s,    TextureBottomLeft_.t},
        {TextureTopLeft_.s,       TextureTopLeft_.t},
    };
    glBindBuffer(GL_ARRAY_BUFFER, VBO_[1]);
    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float) * 4 * 2, tex_vert);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    PositionX_ += MovementX_;
    PositionY_ += MovementY_;
}
void Object::Render() {
    glm::mat4 Projection, Model;
    Projection = glm::orthoLH(0.0f, float(Engine::GetFrameBufferWidth()), 0.0f, float(Engine::GetFrameBufferHeight()), 0.0f, 1000.0f);

    Model = glm::translate(Model, glm::vec3(PositionX_, PositionY_, PositionY_));
    glm::mat4 mvp = Projection * Model;
    GLint MVP = glGetUniformLocation(Shader_.GetProgramID(), "MVP");
    glUniformMatrix4fv(MVP, 1, GL_FALSE, glm::value_ptr(mvp));

    glUseProgram(Shader_.GetProgramID());
    glBindVertexArray(VAO_);
    glBindTexture(GL_TEXTURE_2D, Texture_);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);
}

# These two never change, assigned in object-creation.
float vertices[4][3] = {
    {+SpriteWidth_, +SpriteHeight_, 0.0f},
    {+SpriteWidth_, -SpriteHeight_, 0.0f},
    {-SpriteWidth_, -SpriteHeight_, 0.0f},
    {-SpriteWidth_, +SpriteHeight_, 0.0f},
};

unsigned int indices[] = {
    2, 1, 0,
    2, 0, 3,
};

片段着色器:

out vec4 FragColor;
in vec2 TexCoord;
uniform sampler2D ourTexture;

void main() {
    FragColor = texture(ourTexture, TexCoord);
}

顶点着色器:

layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
out vec2 TexCoord;
uniform mat4 MVP;

void main() {
    gl_Position = MVP * vec4(aPos, 1.0);
    TexCoord = aTexCoord;
}
c++ opengl
1个回答
1
投票

问题不在于VBO_ [1]的更新,也就是应该呈现的纹理位置。

# Correct
glBindBuffer(GL_ARRAY_BUFFER, VBO_[1]);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float) * 4 * 2, tex_vert);
glBindBuffer(GL_ARRAY_BUFFER, 0);

问题是由于glUseProgram的错位,运动/位置(即MVP)没有更新正确的物体。第一个对象获取空MVP,第二个对象获取第一个对象MVP,第三个对象获取第二个对象MVP,第一个对象获取第三个对象MVP等。如果glUseProgram(0)已经在渲染函数结束时使用,则没有由于MVP从未获得真正的价值,因此对象将被正确放置。

# Updated with correct position of glUseProgram()

glm::mat4 Projection, Model;
Projection = glm::orthoLH(0.0f, float(Engine::GetFrameBufferWidth()), 0.0f, float(Engine::GetFrameBufferHeight()), 0.0f, 1000.0f);

Model = glm::translate(Model, glm::vec3(PositionX_, PositionY_, PositionY_));
glm::mat4 mvp = Projection * Model;
GLint MVP = glGetUniformLocation(Shader_.GetProgramID(), "MVP");

glUseProgram(Shader_.GetProgramID()); // This must be loaded before UniformMatrix4fv
glUniformMatrix4fv(MVP, 1, GL_FALSE, glm::value_ptr(mvp));
glBindVertexArray(VAO_);
glBindTexture(GL_TEXTURE_2D, Texture_);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);

所以,对其他人感到困惑的说明:

glUseProgram()之前的glUniformMatrix4fv()

感谢Rabbid76找到了解决方案!

© www.soinside.com 2019 - 2024. All rights reserved.