修改OpenGL中的单个顶点位置

时间:2015-12-07 01:58:52

标签: c++ opengl

我现在正在将我的代码从OpenGL 2转换为我使用glBegin()glVertex3f()到OpenGL 3.3并使用VBO,EBO。我阅读了一些教程,但我找不到一个非常重要的东西,我希望有人能够在这里帮助我。

在以前的版本中感谢glBegin(GL_POLYGON)和4 glVertex3f(floa, float, float)我能够创建我想要的形状。或者更确切地说是用户想要的 - 他可以抓住一个顶点并修改基本矩形。所以有可能创建这样的东西:

previous

现在我绘制基本矩形的代码如下所示:

box_vertices[] = {
            0.5f, 0.5f, 0.0f,
            0.5f, -0.5f, 0.0f,
            -0.5f, -0.5f, 0.0f,
            -0.5f, 0.5f, 0.0f
};

box_indices[] = {
            0, 1, 3,
            1, 2, 3
};

GLuint VAO, VBO, EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);

glBindVertexArray(VAO);

glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(box_vertices), box_vertices, GL_STATIC_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(box_indices), box_indices, GL_STATIC_DRAW);

// Position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);

glBindBuffer(GL_ARRAY_BUFFER, 0);

glBindVertexArray(0); 

while(true) {
    GLint modelLoc = glGetUniformLocation(box_shader.Program, "model");
    GLint viewLoc = glGetUniformLocation(box_shader.Program, "view");
    GLint projLoc = glGetUniformLocation(box_shader.Program, "projection");

    glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
    glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));

    glBindVertexArray(VAO);

    model = glm::mat4();
    model = glm::scale(model, glm::vec3(0.25, 0.75, 1.0));
    // Position box at it's location
    model = glm::translate(model, glm::vec3(x, y, z));
    glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));

    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);
}

,结果如下所示:

now

也许这可能是有用的,这是我的顶点着色器代码:

#version 330 core
layout (location = 0) in vec3 position;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    gl_Position = projection * view * model * vec4(position, 1.0f);
}

我几乎无法找到如何修改一个顶点,因为首先它是我在VBO中理解的,然后必须按照我的理解将其标准化为一个(如果不是OpenGL会这样做的话)为了我)。我怀疑每次都需要生成新的box_vertices数组,那么它是如何完成的呢?

有人可以告诉我如何实现目标吗?

修改

基于vesan回答的修改代码

while(true) {
    GLint modelLoc = glGetUniformLocation(box_shader.Program, "model");
    GLint viewLoc = glGetUniformLocation(box_shader.Program, "view");
    GLint projLoc = glGetUniformLocation(box_shader.Program, "projection");

    glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
    glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));

    glBindVertexArray(VAO);

    MakeSomeChangesToVerticesArray();
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(box_vertices), box_vertices, GL_DYNAMIC_DRAW);

    model = glm::mat4();
    model = glm::scale(model, glm::vec3(0.25, 0.75, 1.0));
    // Position box at it's location
    model = glm::translate(model, glm::vec3(x, y, z));
    glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));

    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);
}

1 个答案:

答案 0 :(得分:3)

您只需修改缓冲区中的数据即可。数据仍然存在,VAO只指向它。

因此,在渲染周期开始时,只需根据需要修改box_vertices数组,然后调用与第一次放入数据时相同的内容:

glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(box_vertices), box_vertices, GL_STATIC_DRAW);

您的阵列非常小,因此性能不应该是一个问题。如果是,请确保仅在形状实际发生变化时才修改缓冲区,请考虑使用GL_DYNAMIC_DRAW代替GL_STATIC_DRAW或使用glBufferSubData仅替换部分缓冲区(I不幸的是,没有这个方便的好例子。

编辑:当然,修改缓冲区的代码不必在绘图循环中。它可以在任何地方(例如在鼠标或键盘处理程序中)。我建议把它放在循环中,因为代码的结构方式,没有别的地方可以放置它。