【发布时间】:2021-12-13 19:11:56
【问题描述】:
我尝试仅在 y 轴上移动我的对象。我创建了一个具有 4 个顶点的数组,并将数据放入我的 vertexBuffer 并绑定它。我还创建了一个 vertexArray 和一个 indexBuffer 来绑定它们并绘制我的四边形。
现在我只更改了四边形的 y 坐标,并想用 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(moveObject), moveObject); 覆盖我的 vertexBuffer 中的数据,但没有任何反应。只有在绑定索引缓冲区之前填充数据时,它才会起作用。之后我无法更改 VertexBuffer。
这是我的主要代码
#include <iostream>
#include "headerData/VertexBuffer.h"
#include "headerData/IndexBuffer.h"
#include "headerData/Shader.h"
#include "headerData/VertexLayout.h"
#include "headerData/VertexArray.h"
#include "headerData/Road.h"
#include "glm.hpp"
#include <gtc/matrix_transform.hpp>
#include <gtc/type_ptr.hpp>
static struct VertexShader {
std::string defaultShader = "#version 330 core\n"
"layout (location = 0) in vec4 aPos;\n"
"uniform mat4 scale;"
"void main()\n"
"{\n"
"gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0f)*scale;\n"
"}\0";
std::string yMoveShader = "#version 330 core\n"
"layout (location = 0) in vec4 aPos;\n"
"uniform mat4 scale;"
"uniform vec4 transform;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(aPos.x, aPos.y+transform.y, aPos.z, 1.0f)*scale;\n"
"}\0";
};
static struct FragmentShader {
std::string defaultShader = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(0.5f, 0.5f, 0.5f, 1.0);\n"
"}\n\0";
std::string greenShader = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(0.5f, 1.0f, 0.5f, 1.0);\n"
"}\n\0";
};
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
int main()
{
// glfw: initialize and configure
// ------------------------------
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
// glfw window creation
// --------------------
GLFWwindow* window = glfwCreateWindow(800, 800, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
// glad: load all OpenGL function pointers
// ---------------------------------------
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
// set up vertex data (and buffer(s)) and configure vertex attributes
// ------------------------------------------------------------------
VertexShader vertexShader;
FragmentShader fragmentShader;
Shader shaderCol(vertexShader.defaultShader, fragmentShader.defaultShader);
Shader shaderMove(vertexShader.yMoveShader, fragmentShader.greenShader);
shaderCol.bind();
//shaderMove.bind();
glm::mat4 scale = glm::ortho(-100.0f, 100.0f, -100.0f, 100.0f, -1.0f, 1.0f);
//glUniformMatrix4fv(glGetUniformLocation(shaderMove.getShaderID(), "scale"), 1, GL_FALSE, glm::value_ptr(scale));
glUniformMatrix4fv(glGetUniformLocation(shaderCol.getShaderID(), "scale"), 1, GL_FALSE, glm::value_ptr(scale));
glm::vec3 transform(0.0f, 0.0f, 0.0f);
float moveObject[] = {
20.0f, -50.0f, // top right
20.0f, -90.0f, // bottom right
-20.0f, -90.0f, // bottom left
-20.0f, -50.0f // top left
};
float colObject[] = {
2.0f, 2.0f, //top right
2.0f, -2.0f, //bottom right
-2.0f, 2.0f, //top left
-2.0, -2.0f //bot left
};
unsigned int indices[] = { // note that we start from 0!
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
unsigned int VA, VB, IB;
glGenVertexArrays(1, &VA);
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
//glBindBuffer(GL_ARRAY_BUFFER, VBO);
//glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//VertexBuffer vb;
//vb.bind(moveObject, 4 * 2 * sizeof(float));
//VertexBuffer
glGenBuffers(1, &VB);
glBindBuffer(GL_ARRAY_BUFFER, VB);
glBufferData(GL_ARRAY_BUFFER, 8 * 2 * sizeof(float), nullptr, GL_DYNAMIC_DRAW);
glBindVertexArray(VA);
//LAyout vom Buffer
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)(0));
glEnableVertexAttribArray(0);
//VertexLayout layout;
//layout.layoutPush(3);
//VertexArray va;
//va.addBuffer(vb, layout);
//IndexBuffer ib;
//ib.bind(indices, 6 * sizeof(unsigned int));
glGenBuffers(1, &IB);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IB);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), indices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, IB);
//Parameter
//glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)(0));
//glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)(3 * sizeof(float)));
//glEnableVertexAttribArray(0);
//glEnableVertexAttribArray(1);
// uncomment this call to draw in wireframe polygons.
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//Road road;
// render loop
// -----------
float time = 0;
while (!glfwWindowShouldClose(window))
{
// input
// -----
processInput(window);
// render
// ------
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
//shader.bind();
//glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, (void*)(sizeof(unsigned int) * 3));
//glDrawArrays(GL_TRIANGLES, 0, 3);
//glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, (void*)(sizeof(unsigned int) * 3));
//glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
//road.render();
//That not work
moveObject[1] += abs(90 * sin(glfwGetTime()));
moveObject[3] += abs(90 * sin(glfwGetTime()));
moveObject[5] += abs(90 * sin(glfwGetTime()));
moveObject[7] += abs(90 * sin(glfwGetTime()));
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(moveObject), moveObject);
//transform.y = 90 * abs(sin(glfwGetTime()));
//glUniform4f(glGetUniformLocation(shaderMove.getShaderID(), "transform"), transform.x, transform.y, 0.0f, 1.0f);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
//glDeleteBuffers(1, &IB);
//glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// glBindVertexArray(0); // no need to unbind it every time
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// -------------------------------------------------------------------------------
glfwSwapBuffers(window);
glfwPollEvents();
}
// optional: de-allocate all resources once they've outlived their purpose:
// ------------------------------------------------------------------------
//glDeleteVertexArrays(1, &test);
// glfw: terminate, clearing all previously allocated GLFW resources.
// ------------------------------------------------------------------
glfwTerminate();
return 0;
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
std::cout << "callback" << std::endl;
glViewport(0, 0, width, height);
}
【问题讨论】:
-
您确定不想在着色器中创建一个统一变量来更改着色器中的所有坐标吗?无需为缓冲区更新而烦恼
-
我想我有更多的方法来移动一个对象。一种方法是使用着色器,但使用着色器您无法检测到碰撞。此外,当您想使用着色器移动并检测碰撞时,您必须进行编程。因此,我寻找了另一种方式来改变我的四边形并使用我的四边形的坐标来检测碰撞。
-
仅仅为了移动一个对象就重新发送一百万个顶点是一种很大的浪费。如果您的对象有一个边界框(或一些简化的网格),并且您知道平移/变换(并且您知道,因为您在着色器中传递了它)。然后您可以在 CPU 端的边界框上复制变换,而无需重新发送所有顶点。传输数据是一个巨大的瓶颈。 GPU 可以很好地发送一次数据并在多次绘制中重复使用它
-
好吧,我认为这是我的数据量有多大的问题。我的意思是我知道我的盒子开始时没有偏移,并以 4*2*sizeof(float) 结束,所以我只能覆盖我的顶点数组的这一部分。最后,性能会比在我的着色器中编写复杂的转换要好。当我只使用着色器时,当我使用状态 GL_DYNAMIC_DRAW
-
矩阵乘法的顺序很重要。如果你想应用投影矩阵 -
scale到输入顶点,它应该是scale * position在着色器的代码中。