C++ 使用VAO在OpenGL中实例化顺序更改绘图
我尝试使用VAOs、VBOs和IBOs在平面上绘制一组球体。在使用这些工具之前,一切都按预期绘制。在我开始使用这些之后,事情变得很奇怪。我不能在这里发布我的全部代码,因为我有5个类(但如果有必要,我可以提供代码链接),所以我将尝试发布我认为有用的内容 使用该类,我可以绘制一个球体:C++ 使用VAO在OpenGL中实例化顺序更改绘图,c++,opengl,vbo,vao,C++,Opengl,Vbo,Vao,我尝试使用VAOs、VBOs和IBOs在平面上绘制一组球体。在使用这些工具之前,一切都按预期绘制。在我开始使用这些之后,事情变得很奇怪。我不能在这里发布我的全部代码,因为我有5个类(但如果有必要,我可以提供代码链接),所以我将尝试发布我认为有用的内容 使用该类,我可以绘制一个球体: SphereShaderProgram::SphereShaderProgram(std::string vertexShaderPath, std::string fragmentShaderPath) : Pro
SphereShaderProgram::SphereShaderProgram(std::string vertexShaderPath, std::string fragmentShaderPath) : ProgramManager(vertexShaderPath, fragmentShaderPath)
{
_sphereH = 20;
_sphereW = 20;
_vbo = 0;
_vao = 0;
_ibo = 0;
CreateProgram();
BuildSphere();
BuildVAO();
}
SphereShaderProgram::~SphereShaderProgram()
{
glDeleteVertexArrays(1, &_vao);
glDeleteBuffers(1, &_vbo);
glDeleteBuffers(1, &_ibo);
}
void SphereShaderProgram::DrawSphere(const glm::mat4 &Projection, const glm::mat4 &ModelView)
{
_ModelViewProjection = Projection * ModelView;
_ModelView = ModelView;
Bind(); //glUseProgram
glBindVertexArray(_vao);
LoadVariables();
glDrawElements(GL_TRIANGLES, _sphereIndexes.size(), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
UnBind();
}
int SphereShaderProgram::Get1DIndex(int line, int column)
{
return line * (int) _sphereH + column;
}
void SphereShaderProgram::BuildSphere()
{
for (int l = 0; l < _sphereH - 1; l++)
{
for (int c = 0; c < _sphereW - 1; c++)
{
int v1_1 = Get1DIndex(l, c);
int v2_1 = Get1DIndex(l + 1, c + 1);
int v3_1 = Get1DIndex(l + 1, c);
int v1_2 = Get1DIndex(l, c);
int v2_2 = Get1DIndex(l, c + 1);
int v3_2 = Get1DIndex(l + 1, c + 1);
_sphereIndexes.push_back(v1_1);
_sphereIndexes.push_back(v2_1);
_sphereIndexes.push_back(v3_1);
_sphereIndexes.push_back(v1_2);
_sphereIndexes.push_back(v2_2);
_sphereIndexes.push_back(v3_2);
}
}
for (int l = 0; l < _sphereH; l++)
{
for (int c = 0; c < _sphereW; c++)
{
float theta = ((float) l / (_sphereH - 1)) * (float) PI;
float phi = ((float) c / (_sphereW - 1)) * 2 * (float) PI;
float x = sin(theta) * cos(phi);
float z = sin(theta) * sin(phi);
float y = cos(theta);
_sphereCoordinates.push_back(x);
_sphereCoordinates.push_back(y);
_sphereCoordinates.push_back(z);
}
}
}
void SphereShaderProgram::BuildVAO()
{
// Generate and bind the vertex array object
glGenVertexArrays(1, &_vao);
glBindVertexArray(_vao);
// Generate and bind the vertex buffer object
glGenBuffers(1, &_vbo);
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferData(GL_ARRAY_BUFFER, _sphereCoordinates.size() * sizeof(float), &_sphereCoordinates[0], GL_STATIC_DRAW);
// Generate and bind the index buffer object
glGenBuffers(1, &_ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, _sphereIndexes.size() * sizeof(unsigned int), &_sphereIndexes[0], GL_STATIC_DRAW);
glBindVertexArray(0);
}
void SphereShaderProgram::LoadUniformVariables()
{
glm::mat4 MVP = _ModelViewProjection;
glm::mat4 MV = _ModelView;
glm::mat3 N = glm::transpose(glm::inverse(glm::mat3(MV)));
glm::vec4 AC = glm::vec4(0.2, 0.2, 0.2, 1.0);
glm::vec4 DC = glm::vec4(0.7, 0.0, 0.0, 1.0);
glm::vec4 SC = glm::vec4(0.1, 0.1, 0.1, 1.0);
glm::vec3 LP = glm::vec3(1.0, 6.0, 4.0);
// OpenGL Matrices
GLuint ModelViewProjection_location = glGetUniformLocation(GetProgramID(), "mvpMatrix");
glUniformMatrix4fv(ModelViewProjection_location, 1, GL_FALSE, glm::value_ptr(MVP));
GLuint ModelView_location = glGetUniformLocation(GetProgramID(), "mvMatrix");
glUniformMatrix4fv(ModelView_location, 1, GL_FALSE, glm::value_ptr(MV));
GLuint Normal_location = glGetUniformLocation(GetProgramID(), "normalMatrix");
glUniformMatrix3fv(Normal_location, 1, GL_FALSE, glm::value_ptr(N));
// Lighting
GLuint AmbientColor_location = glGetUniformLocation(GetProgramID(), "ambientColor");
glUniform4fv(AmbientColor_location, 1, glm::value_ptr(AC));
GLuint DiffuseColor_location = glGetUniformLocation(GetProgramID(), "diffuseColor");
glUniform4fv(DiffuseColor_location, 1, glm::value_ptr(DC));
GLuint SpecularColor_location = glGetUniformLocation(GetProgramID(), "specularColor");
glUniform4fv(SpecularColor_location, 1, glm::value_ptr(SC));
GLuint LightPosition_location = glGetUniformLocation(GetProgramID(), "vLightPosition");
glUniform3fv(LightPosition_location, 1, glm::value_ptr(LP));
}
void SphereShaderProgram::LoadAtributeVariables()
{
// Vertex Attributes
GLuint VertexPosition_location = glGetAttribLocation(GetProgramID(), "vPosition");
glEnableVertexAttribArray(VertexPosition_location);
glVertexAttribPointer(VertexPosition_location, 3, GL_FLOAT, GL_FALSE, 0, 0);
}
void SphereShaderProgram::LoadVariables()
{
LoadUniformVariables();
LoadAtributeVariables();
}
另一方面,这是我的主要观点:
int main(void)
{
// Set the error callback
glfwSetErrorCallback(ErrorCallback);
// Initialize GLFW
if (!glfwInit())
{
printf("Error initializing GLFW!\n");
exit(EXIT_FAILURE);
}
// Set the GLFW window creation hints - these are optional
glfwWindowHint(GLFW_SAMPLES, 4);
// Create a window and create its OpenGL context
GLFWwindow* window = glfwCreateWindow(width, height, "OpenGL 4 Base", NULL, NULL);
// If the window couldn't be created
if (!window)
{
fprintf(stderr, "Failed to open GLFW window.\n");
glfwTerminate();
exit(EXIT_FAILURE);
}
// Sets the context of the specified window on the calling thread
glfwMakeContextCurrent(window);
// Initialize GLEW
glewExperimental = true;
GLenum glewError = glewInit();
if (glewError != GLEW_OK)
{
printf("Error initializing GLEW! %s\n", glewGetErrorString(glewError));
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwSetKeyCallback(window, KeyCallback);
glfwSetWindowSizeCallback(window, WindowSizeCallback);
glfwSetScrollCallback(window, ScrollCallback);
// Set the view matrix
glm::mat4 ModelView = glm::lookAt(glm::vec3(0.0f, 7.0f, 15.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
// Init matrix stack
glm_ModelViewMatrix.push(ModelView);
PlaneShaderProgram PlaneShaderProgram("FloorVertexShader.txt", "FloorFragShader.txt");
SphereShaderProgram SphereShaderProgram("ADSPerVertexVertexShader.txt", "ADSPerVertexFragShader.txt");
//SphereShaderProgram SphereShaderProgram = SphereShaderProgram("ADSPerPixelVertexShader.txt", "ADSPerPixelFragShader.txt");
// Set a background color
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
// 3D objects
glEnable(GL_DEPTH_TEST);
float d = 2.0f;
float p0 = -10.0f + d / 2;
// Main Loop
while (!glfwWindowShouldClose(window))
{
// Clear color buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Clone current modelview matrix, which can now be modified
glm_ModelViewMatrix.push(glm_ModelViewMatrix.top());
{
//------- ModelView Transformations
// Zoom in/out
glm_ModelViewMatrix.top() = glm::translate(glm_ModelViewMatrix.top(), glm::vec3(0.0, 0.0, zoom));
// Rotation
glm_ModelViewMatrix.top() = glm::rotate(glm_ModelViewMatrix.top(), beta, glm::vec3(1.0, 0.0, 0.0));
glm_ModelViewMatrix.top() = glm::rotate(glm_ModelViewMatrix.top(), alpha, glm::vec3(0.0, 0.0, 1.0));
//------- Draw the plane
glm_ModelViewMatrix.push(glm_ModelViewMatrix.top());
{
glm_ModelViewMatrix.top() = glm::scale(glm_ModelViewMatrix.top(), glm::vec3(7.0f, 1.0f, 7.0f));
PlaneShaderProgram.DrawPlane(Projection, glm_ModelViewMatrix.top());
}
glm_ModelViewMatrix.pop();
//------- Draw spheres
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
glm_ModelViewMatrix.push(glm_ModelViewMatrix.top());
{
glm_ModelViewMatrix.top() = glm::scale(glm_ModelViewMatrix.top(), glm::vec3(0.5f, 0.5f, 0.5f));
glm_ModelViewMatrix.top() = glm::translate(glm_ModelViewMatrix.top(), glm::vec3(p0 + i * d, 1.0f, p0 + j * d));
SphereShaderProgram.DrawSphere(Projection, glm_ModelViewMatrix.top());
}
glm_ModelViewMatrix.pop();
}
}
}
glm_ModelViewMatrix.pop();
// Swap buffers
glfwSwapBuffers(window);
// Get and organize events, like keyboard and mouse input, window resizing, etc...
glfwPollEvents();
}
// Close OpenGL window and terminate GLFW
glfwDestroyWindow(window);
// Finalize and clean up GLFW
glfwTerminate();
exit(EXIT_SUCCESS);
}
int main(无效)
{
//设置错误回调
glfwSetErrorCallback(ErrorCallback);
//初始化GLFW
如果(!glfwInit())
{
printf(“初始化GLFW时出错!\n”);
退出(退出失败);
}
//设置GLFW窗口创建提示-这些是可选的
glfwWindowHint(GLFW_样本,4个);
//创建窗口并创建其OpenGL上下文
GLFWwindow*window=glfwCreateWindow(宽度、高度,“OpenGL 4 Base”,NULL,NULL);
//如果无法创建窗口
如果(!窗口)
{
fprintf(stderr,“无法打开GLFW窗口。\n”);
glfwTerminate();
退出(退出失败);
}
//在调用线程上设置指定窗口的上下文
glfwMakeContextCurrent(窗口);
//初始化GLEW
glewExperimental=true;
GLenum glewError=glewInit();
如果(glewError!=GLEW_OK)
{
printf(“初始化GLEW时出错!%s\n”,glewGetErrorString(glewError));
GLFW窗口(窗口);
glfwTerminate();
退出(退出失败);
}
glfwSetKeyCallback(窗口,KeyCallback);
glfwSetWindowSizeCallback(窗口,WindowSizeCallback);
glfwSetScrollCallback(窗口、滚动回调);
//设置视图矩阵
glm::mat4 ModelView=glm::lookAt(glm::vec3(0.0f,7.0f,15.0f),glm::vec3(0.0f,0.0f,0.0f),glm::vec3(0.0f,1.0f,0.0f));
//初始化矩阵堆栈
glm_ModelViewMatrix.push(ModelView);
PlaneShaderProgram PlaneShaderProgram(“FloorVertexShader.txt”、“FloorFragShader.txt”);
SphereShareProgram SphereShareProgram(“ADSPerVertexVertexShader.txt”、“ADSPerVertexFragShader.txt”);
//SphereShaderProgram SphereShaderProgram=SphereShaderProgram(“ADSPerPixelVertexShader.txt”、“ADSPerPixelFragShader.txt”);
//设置背景色
glClearColor(0.0f、0.0f、0.0f、0.0f);
//三维对象
glEnable(GLU深度试验);
浮球d=2.0f;
浮动p0=-10.0f+d/2;
//主回路
而(!glfwWindowShouldClose(窗口))
{
//清晰颜色缓冲区
glClear(GL_颜色_缓冲_位| GL_深度_缓冲_位);
//克隆当前modelview矩阵,现在可以对其进行修改
glm_ModelViewMatrix.push(glm_ModelViewMatrix.top());
{
//-------模型视图转换
//放大/缩小
glm_ModelViewMatrix.top()=glm::translate(glm_ModelViewMatrix.top(),glm::vec3(0.0,0.0,zoom));
//轮换
glm_ModelViewMatrix.top()=glm::rotate(glm_ModelViewMatrix.top(),beta,glm::vec3(1.0,0.0,0.0));
glm_ModelViewMatrix.top()=glm::rotate(glm_ModelViewMatrix.top(),alpha,glm::vec3(0.0,0.0,1.0));
//-------画飞机
glm_ModelViewMatrix.push(glm_ModelViewMatrix.top());
{
glm_ModelViewMatrix.top()=glm::scale(glm_ModelViewMatrix.top(),glm::vec3(7.0f,1.0f,7.0f));
DrawPlane(投影,glm_ModelViewMatrix.top());
}
glm_ModelViewMatrix.pop();
//-------画球体
对于(int i=0;i<10;i++)
{
对于(int j=0;j<10;j++)
{
glm_ModelViewMatrix.push(glm_ModelViewMatrix.top());
{
glm_ModelViewMatrix.top()=glm::scale(glm_ModelViewMatrix.top(),glm::vec3(0.5f,0.5f,0.5f));
glm_ModelViewMatrix.top()=glm::translate(glm_ModelViewMatrix.top(),glm::vec3(p0+i*d,1.0f,p0+j*d));
DrawSphere(投影,glm_ModelViewMatrix.top());
}
glm_ModelViewMatrix.pop();
}
}
}
glm_ModelViewMatrix.pop();
//交换缓冲区
glfwSwapBuffers(窗口);
//获取并组织事件,如键盘和鼠标输入、窗口大小调整等。。。
glfwPollEvents();
}
//关闭OpenGL窗口并终止GLFW
GLFW窗口(窗口);
//最终确定并清理GLFW
glfwTerminate();
退出(退出成功);
}
实例化平面和球体程序,我得到以下结果(根本没有平面):
更改顺序,即结果:
我正试图找到一个关于我遗漏了什么的线索,因为我不知道到底是什么错了。在使用VAOs之前(仅使用glvertexattributepointer
和gldrawerelements
),所有内容都正确绘制
提前感谢。问题在于
glvertexattributepointer()
调用的位置。您在LoadAtributeVariables()
方法中调用它,然后从Draw*()
方法调用它
这应该是VAO设置的一部分,原因如下:
- 每次重画都打电话是没有效率的。此调用设置作为VAO状态一部分的状态。这就是最初使用VAO的全部想法。您可以在设置过程中设置所有此状态一次,然后只需在draw调用之前再次绑定VAO,这将使用单个调用再次设置所有状态
- 在您的情况下,VBO在您呼叫时不受约束
设置属性以从当前绑定的VBO中提取数据,即绑定为glVertexAttribPointer()
GL\u ARRAY\u buffer的缓冲区
int main(void)
{
// Set the error callback
glfwSetErrorCallback(ErrorCallback);
// Initialize GLFW
if (!glfwInit())
{
printf("Error initializing GLFW!\n");
exit(EXIT_FAILURE);
}
// Set the GLFW window creation hints - these are optional
glfwWindowHint(GLFW_SAMPLES, 4);
// Create a window and create its OpenGL context
GLFWwindow* window = glfwCreateWindow(width, height, "OpenGL 4 Base", NULL, NULL);
// If the window couldn't be created
if (!window)
{
fprintf(stderr, "Failed to open GLFW window.\n");
glfwTerminate();
exit(EXIT_FAILURE);
}
// Sets the context of the specified window on the calling thread
glfwMakeContextCurrent(window);
// Initialize GLEW
glewExperimental = true;
GLenum glewError = glewInit();
if (glewError != GLEW_OK)
{
printf("Error initializing GLEW! %s\n", glewGetErrorString(glewError));
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwSetKeyCallback(window, KeyCallback);
glfwSetWindowSizeCallback(window, WindowSizeCallback);
glfwSetScrollCallback(window, ScrollCallback);
// Set the view matrix
glm::mat4 ModelView = glm::lookAt(glm::vec3(0.0f, 7.0f, 15.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
// Init matrix stack
glm_ModelViewMatrix.push(ModelView);
PlaneShaderProgram PlaneShaderProgram("FloorVertexShader.txt", "FloorFragShader.txt");
SphereShaderProgram SphereShaderProgram("ADSPerVertexVertexShader.txt", "ADSPerVertexFragShader.txt");
//SphereShaderProgram SphereShaderProgram = SphereShaderProgram("ADSPerPixelVertexShader.txt", "ADSPerPixelFragShader.txt");
// Set a background color
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
// 3D objects
glEnable(GL_DEPTH_TEST);
float d = 2.0f;
float p0 = -10.0f + d / 2;
// Main Loop
while (!glfwWindowShouldClose(window))
{
// Clear color buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Clone current modelview matrix, which can now be modified
glm_ModelViewMatrix.push(glm_ModelViewMatrix.top());
{
//------- ModelView Transformations
// Zoom in/out
glm_ModelViewMatrix.top() = glm::translate(glm_ModelViewMatrix.top(), glm::vec3(0.0, 0.0, zoom));
// Rotation
glm_ModelViewMatrix.top() = glm::rotate(glm_ModelViewMatrix.top(), beta, glm::vec3(1.0, 0.0, 0.0));
glm_ModelViewMatrix.top() = glm::rotate(glm_ModelViewMatrix.top(), alpha, glm::vec3(0.0, 0.0, 1.0));
//------- Draw the plane
glm_ModelViewMatrix.push(glm_ModelViewMatrix.top());
{
glm_ModelViewMatrix.top() = glm::scale(glm_ModelViewMatrix.top(), glm::vec3(7.0f, 1.0f, 7.0f));
PlaneShaderProgram.DrawPlane(Projection, glm_ModelViewMatrix.top());
}
glm_ModelViewMatrix.pop();
//------- Draw spheres
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
glm_ModelViewMatrix.push(glm_ModelViewMatrix.top());
{
glm_ModelViewMatrix.top() = glm::scale(glm_ModelViewMatrix.top(), glm::vec3(0.5f, 0.5f, 0.5f));
glm_ModelViewMatrix.top() = glm::translate(glm_ModelViewMatrix.top(), glm::vec3(p0 + i * d, 1.0f, p0 + j * d));
SphereShaderProgram.DrawSphere(Projection, glm_ModelViewMatrix.top());
}
glm_ModelViewMatrix.pop();
}
}
}
glm_ModelViewMatrix.pop();
// Swap buffers
glfwSwapBuffers(window);
// Get and organize events, like keyboard and mouse input, window resizing, etc...
glfwPollEvents();
}
// Close OpenGL window and terminate GLFW
glfwDestroyWindow(window);
// Finalize and clean up GLFW
glfwTerminate();
exit(EXIT_SUCCESS);
}
// Generate and bind the vertex buffer object
glGenBuffers(1, &_vbo);
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferData(GL_ARRAY_BUFFER, _sphereCoordinates.size() * sizeof(float), &_sphereCoordinates[0], GL_STATIC_DRAW);
LoadAtributeVariables();