OpenGL:渲染到帧缓冲区以及显示
OpenGL: Render to framebuffer as well as to display
我有一个可以在显示器上渲染的 3d 场景。但是,除了渲染它以显示之外,我还希望能够将渲染的场景导出为图像(比如每 100 帧一次)(比如 JPG 或 PNG 图像),也许将其保存为文件保存在我的某个地方机.
我尝试了如下操作:
do{
glBindFramebuffer(GL_FRAMEBUFFER, framebuffername);
drawScene();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
drawScene();
}while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS
我不确定我是否正确使用了 FrameBuffer 对象,但正在寻找关于如何根据我的目标继续进行的建议。从上面的代码中,我将帧缓冲区绑定到我定义的 FBO,然后绘制场景(如果我是正确的,应该绘制到 FBO?)。然后我再次绘制到我的常规显示。但是,此代码导致显示在我的场景和我不想要的空(黑色)场景之间不断切换。我希望我的场景作为一个漂亮干净的 3d 场景显示在显示设备上,而不是一直全黑。
我的绘图函数看起来像这样:
void drawScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//glBindTexture(GL_TEXTURE_2D, 0);
//glBindFramebuffer(GL_FRAMEBUFFER, framebuffername);
// Use our shader
glUseProgram(programID);
// Compute the MVP matrix from keyboard and mouse input
computeMatricesFromInputs();
glm::mat4 ProjectionMatrix = getProjectionMatrix();
glm::mat4 ViewMatrix = getViewMatrix();
glm::mat4 ModelMatrix = glm::mat4(1.0); //DEFINE MODEL TO WORLD TRANSFORMATION
//glm::mat4 ModelMatrix = glm::scale(2.0,2.0,2.0);
glm::mat4 MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;
// Send our transformation to the currently bound shader,
// in the "MVP" uniform
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
glUniform1f(FARPLANE, farplane_control);
glUniform1f(NEARPLANE, nearplane_control);
glUniformMatrix4fv(ModelMatrixID, 1, GL_FALSE, &ModelMatrix[0][0]);
glUniformMatrix4fv(ViewMatrixID, 1, GL_FALSE, &ViewMatrix[0][0]);
glm::vec3 lightPos = glm::vec3(0, 0, 4);
glUniform3f(LightID, lightPos.x, lightPos.y, lightPos.z);
// 1st attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// 2nd attribute buffer : normals
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glVertexAttribPointer(
1, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Draw the triangle !
glDrawArrays(GL_TRIANGLES, 0, (GLsizei)vertices.size());
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glReadBuffer(GL_FRONT);
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
}
您的 drawScene()
代码在末尾包含这些行:
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
如果您在实际没有渲染到屏幕时调用它,您认为会发生什么?
显而易见的解决方案是在函数中包含一个标志,指示是否执行缓冲区交换:
void drawScene(bool swap = true) {
/*...*/
if(swap) {
glfwSwapBuffers(window);
glfwPollEvents();
}
}
do{
glBindFramebuffer(GL_FRAMEBUFFER, framebuffername);
drawScene(false);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
drawScene(true);
}while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS
或者,您可以将这些调用移到函数外部,这可能更好,因为首先将它们置于绘图函数的本地并没有多大意义。
do{
glfwPollEvents(); //Prefer having this be the first call, in case you need the window
//responding to user input immediately
glBindFramebuffer(GL_FRAMEBUFFER, framebuffername);
drawScene();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
drawScene();
glfwSwapBuffers(window); //No longer in drawScene() function
}while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS
我有一个可以在显示器上渲染的 3d 场景。但是,除了渲染它以显示之外,我还希望能够将渲染的场景导出为图像(比如每 100 帧一次)(比如 JPG 或 PNG 图像),也许将其保存为文件保存在我的某个地方机.
我尝试了如下操作:
do{
glBindFramebuffer(GL_FRAMEBUFFER, framebuffername);
drawScene();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
drawScene();
}while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS
我不确定我是否正确使用了 FrameBuffer 对象,但正在寻找关于如何根据我的目标继续进行的建议。从上面的代码中,我将帧缓冲区绑定到我定义的 FBO,然后绘制场景(如果我是正确的,应该绘制到 FBO?)。然后我再次绘制到我的常规显示。但是,此代码导致显示在我的场景和我不想要的空(黑色)场景之间不断切换。我希望我的场景作为一个漂亮干净的 3d 场景显示在显示设备上,而不是一直全黑。
我的绘图函数看起来像这样:
void drawScene() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//glBindTexture(GL_TEXTURE_2D, 0);
//glBindFramebuffer(GL_FRAMEBUFFER, framebuffername);
// Use our shader
glUseProgram(programID);
// Compute the MVP matrix from keyboard and mouse input
computeMatricesFromInputs();
glm::mat4 ProjectionMatrix = getProjectionMatrix();
glm::mat4 ViewMatrix = getViewMatrix();
glm::mat4 ModelMatrix = glm::mat4(1.0); //DEFINE MODEL TO WORLD TRANSFORMATION
//glm::mat4 ModelMatrix = glm::scale(2.0,2.0,2.0);
glm::mat4 MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;
// Send our transformation to the currently bound shader,
// in the "MVP" uniform
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
glUniform1f(FARPLANE, farplane_control);
glUniform1f(NEARPLANE, nearplane_control);
glUniformMatrix4fv(ModelMatrixID, 1, GL_FALSE, &ModelMatrix[0][0]);
glUniformMatrix4fv(ViewMatrixID, 1, GL_FALSE, &ViewMatrix[0][0]);
glm::vec3 lightPos = glm::vec3(0, 0, 4);
glUniform3f(LightID, lightPos.x, lightPos.y, lightPos.z);
// 1st attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(
0, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// 2nd attribute buffer : normals
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glVertexAttribPointer(
1, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Draw the triangle !
glDrawArrays(GL_TRIANGLES, 0, (GLsizei)vertices.size());
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glReadBuffer(GL_FRONT);
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
}
您的 drawScene()
代码在末尾包含这些行:
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
如果您在实际没有渲染到屏幕时调用它,您认为会发生什么?
显而易见的解决方案是在函数中包含一个标志,指示是否执行缓冲区交换:
void drawScene(bool swap = true) {
/*...*/
if(swap) {
glfwSwapBuffers(window);
glfwPollEvents();
}
}
do{
glBindFramebuffer(GL_FRAMEBUFFER, framebuffername);
drawScene(false);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
drawScene(true);
}while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS
或者,您可以将这些调用移到函数外部,这可能更好,因为首先将它们置于绘图函数的本地并没有多大意义。
do{
glfwPollEvents(); //Prefer having this be the first call, in case you need the window
//responding to user input immediately
glBindFramebuffer(GL_FRAMEBUFFER, framebuffername);
drawScene();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
drawScene();
glfwSwapBuffers(window); //No longer in drawScene() function
}while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS