【发布时间】:2019-03-14 19:32:06
【问题描述】:
问题陈述
这应该是一个非常明显的答案,我可能在某处弄脏了一两行,但我似乎无法将三角形绘制到帧缓冲区。
我想要做的是将两个三角形连接到一个大型渲染缓冲区对象,并附加一个帧缓冲区,然后在四个窗口之一中使用 glBlitFramebuffer 显示更大的渲染缓冲区/帧缓冲区的一部分。
我使用init_FB() 来定义要渲染的三角形以及渲染这些三角形的RBO。我创建了一个渲染缓冲区对象和一个与渲染缓冲区对象关联的帧缓冲区对象。在compute_FB() 函数中,我绑定了RBO 的帧缓冲区,然后调用以绘制到该帧缓冲区中。在绘制三角形之前,我将帧缓冲区清除为特定颜色,royalblue。
到底发生了什么
在名为window 的第一个窗口中,仅显示由绘制到渲染缓冲区对象的帧缓冲区的函数(compute_FB()) 定义的颜色royalblue。但是,即使我在compute_FB() 的末尾调用了一个glDrawArrays(...) 函数,也没有绘制任何三角形。
发生了什么的可能假设
我开始相信 RBO 需要自己的上下文才能成功渲染,但我不知道如何为 RBO 设置上下文。我认为上下文仅适用于 GLFW 中的窗口。
代码说明
我的尝试基于最初的 OpenGL 红皮书示例 01-三角形。在这个例子中,我编写了四个独特的窗口,并希望最终将一个大的 RBO/帧缓冲区复制到四个窗口中的每一个 - 目前我只关注第一个显示。
我正在使用带有 GLFW 的 OpenGL4.5 进行窗口化。
代码
//////////////////////////////////////////////////////////////////////////////
//
// Triangles.cpp
//
//////////////////////////////////////////////////////////////////////////////
#include "vgl.h"
#include "LoadShaders.h"
#include <vector>
enum VAO_IDs { Triangles, NumVAOs };
enum Buffer_IDs { ArrayBuffer, NumBuffers };
enum Attrib_IDs { vPosition = 0 };
GLuint VAOs[NumVAOs];
GLuint Buffers[NumBuffers];
const GLuint NumVertices = 6;
//////////////////////////////////////////////////
// Framebuffer Variables
//////////////////////////////////////////////////
enum {Color, NumRenderBuffers};
GLuint framebuffer, renderbuffer[NumRenderBuffers];
GLuint fbwidth = 3200;
GLuint fbheight = 600;
//----------------------------------------------------------------------------
//
// init
//
void init_FB( void )
{
// Create an Empty RenderBuffer and Associated Framebuffer
glCreateRenderbuffers(NumRenderBuffers, renderbuffer);
glNamedRenderbufferStorage(renderbuffer[Color], GL_RGBA, fbwidth, fbheight);
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
glNamedFramebufferRenderbuffer(framebuffer, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer[Color]);
glEnable(GL_DEPTH_TEST);
// Here's some info to initialize for the RBO
// The framebuffer for the RBO has been bound (above) and ?SHOULD? be ready to draw to, right?
glGenVertexArrays( NumVAOs, VAOs );
glBindVertexArray( VAOs[Triangles] );
GLfloat vertices[NumVertices][2] = {
{ -1.00f, -1.00f }, { -1.00f, 0.40f }, { 0.00f, -1.00f }, // Triangle 1
{ 0.00f, 0.40f }, { 0.40f, 0.40f }, { 0.40f, -0.40f } // Triangle 2
};
ShaderInfo shaders[] =
{
{ GL_VERTEX_SHADER, "media/shaders/triangles/triangles.vert" },
{ GL_FRAGMENT_SHADER, "media/shaders/triangles/triangles.frag" },
{ GL_NONE, NULL }
};
GLuint program = LoadShaders( shaders );
glUseProgram( program );
glVertexAttribPointer( vPosition, 2, GL_FLOAT,
GL_FALSE, 0, BUFFER_OFFSET(0) );
glEnableVertexAttribArray( vPosition );
}
void init( void )
{
// Create the standard window framebuffer for this window context
// Basically, I want to give the window a framebuffer so that I can draw into it later in the 'draw' phase
glCreateBuffers( NumBuffers, Buffers );
glBindBuffer( GL_ARRAY_BUFFER, Buffers[ArrayBuffer] );
static const float black[] = { 1.0f, 0.5f, 0.2f, 0.0f };
// May as well clear it to a color that's visually separate from the color that it will be cleared to
// .. in the draw phase.
glClearBufferfv(GL_COLOR, 0, black);
}
void init2( void )
{
glGenVertexArrays( NumVAOs, VAOs );
glBindVertexArray( VAOs[Triangles] );
GLfloat vertices[NumVertices][2] = {
{ -0.90f, -0.60f }, { -0.85f, -0.60f }, { -0.50f, -0.65f }, // Triangle 1
{ 0.90f, -0.85f }, { 0.90f, 0.90f }, { -0.85f, 0.90f } // Triangle 2
};
glCreateBuffers( NumBuffers, Buffers );
glBindBuffer( GL_ARRAY_BUFFER, Buffers[ArrayBuffer] );
glBufferStorage( GL_ARRAY_BUFFER, sizeof(vertices), vertices, 0);
ShaderInfo shaders[] =
{
{ GL_VERTEX_SHADER, "media/shaders/triangles/triangles.vert" },
{ GL_FRAGMENT_SHADER, "media/shaders/triangles/triangles.frag" },
{ GL_NONE, NULL }
};
GLuint program = LoadShaders( shaders );
glUseProgram( program );
glVertexAttribPointer( vPosition, 2, GL_FLOAT,
GL_FALSE, 0, BUFFER_OFFSET(0) );
glEnableVertexAttribArray( vPosition );
}
void init3( void )
{
glGenVertexArrays( NumVAOs, VAOs );
glBindVertexArray( VAOs[Triangles] );
GLfloat vertices[NumVertices][2] = {
{ -0.90f, -0.90f }, { -0.90f, 0.90f }, { 0.00f, -0.90f }, // Triangle 1
{ 0.00f, 0.90f }, { 0.90f, 0.90f }, { 0.90f, -0.90f } // Triangle 2
};
glCreateBuffers( NumBuffers, Buffers );
glBindBuffer( GL_ARRAY_BUFFER, Buffers[ArrayBuffer] );
glBufferStorage( GL_ARRAY_BUFFER, sizeof(vertices), vertices, 0);
ShaderInfo shaders[] =
{
{ GL_VERTEX_SHADER, "media/shaders/triangles/triangles.vert" },
{ GL_FRAGMENT_SHADER, "media/shaders/triangles/triangles.frag" },
{ GL_NONE, NULL }
};
GLuint program = LoadShaders( shaders );
glUseProgram( program );
glVertexAttribPointer( vPosition, 2, GL_FLOAT,
GL_FALSE, 0, BUFFER_OFFSET(0) );
glEnableVertexAttribArray( vPosition );
}
void init4( void )
{
glGenVertexArrays( NumVAOs, VAOs );
glBindVertexArray( VAOs[Triangles] );
GLfloat vertices[NumVertices][2] = {
{ -0.40f, -0.40f }, { -0.40f, 0.40f }, { 0.00f, -0.40f }, // Triangle 1
{ 0.00f, 0.40f }, { 0.40f, 0.40f }, { 0.40f, -0.40f } // Triangle 2
};
glCreateBuffers( NumBuffers, Buffers );
glBindBuffer( GL_ARRAY_BUFFER, Buffers[ArrayBuffer] );
glBufferStorage( GL_ARRAY_BUFFER, sizeof(vertices), vertices, 0);
ShaderInfo shaders[] =
{
{ GL_VERTEX_SHADER, "media/shaders/triangles/triangles.vert" },
{ GL_FRAGMENT_SHADER, "media/shaders/triangles/triangles.frag" },
{ GL_NONE, NULL }
};
GLuint program = LoadShaders( shaders );
glUseProgram( program );
glVertexAttribPointer( vPosition, 2, GL_FLOAT,
GL_FALSE, 0, BUFFER_OFFSET(0) );
glEnableVertexAttribArray( vPosition );
}
//----------------------------------------------------------------------------
//
// display
//
void compute_FB()
{
// Prepare to render into the framebuffer
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
glViewport(0, 0, fbwidth, fbheight);
// Clear before drawing. This shade of color comes through to the first window display
static const float black[] = { 0.0f, 0.3f, 0.8f, 0.0f };
glClearBufferfv(GL_COLOR, 0, black);
// Try drawing the triangles... Nuthin
glBindVertexArray( VAOs[Triangles] );
glDrawArrays( GL_TRIANGLES, 0, NumVertices );
}
// Read from a section of the RBO/framebuffer
void display( void )
{
static const float black[] = { 0.8f, 0.0f, 0.0f, 0.0f };
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer); // Set framebuffer to read from
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); // set window to draw to
glViewport(0, 0, 800, 600); // Probbaly not needed
// Copy from READ framebuffer to DRAW framebuffer
// QUESTION: Why isn't this copying to just a small corner of the window context's framebuffer?
glBlitFramebuffer(0, 0, fbwidth, fbheight, 0, 0, 100, 200, GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
void display2( void )
{
static const float black[] = { 0.0f, 0.3f, 0.4f, 0.0f };
glClearBufferfv(GL_COLOR, 0, black);
glBindVertexArray( VAOs[Triangles] );
glDrawArrays( GL_TRIANGLES, 0, NumVertices );
}
void display3( void )
{
static const float black[] = { 0.7f, 0.6f, 0.4f, 0.0f };
glClearBufferfv(GL_COLOR, 0, black);
glBindVertexArray( VAOs[Triangles] );
glDrawArrays( GL_TRIANGLES, 0, NumVertices );
}
void display4( void )
{
static const float black[] = { 0.2f, 0.3f, 0.7f, 0.0f };
glClearBufferfv(GL_COLOR, 0, black);
glBindVertexArray( VAOs[Triangles] );
glDrawArrays( GL_TRIANGLES, 0, NumVertices );
}
//----------------------------------------------------------------------------
//
// main
//
#ifdef _WIN32
int CALLBACK WinMain(
_In_ HINSTANCE hInstance,
_In_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nCmdShow
)
#else
int
main( int argc, char** argv )
#endif
{
// Initialize GLFW
glfwInit();
//TODO Create Windows Class
// Create Windows
GLFWwindow* window = glfwCreateWindow(800, 600, "Triangles", NULL, NULL);
GLFWwindow* window2 = glfwCreateWindow(800, 600, "Triangles2", NULL, NULL);
GLFWwindow* window3 = glfwCreateWindow(800, 600, "Triangles3", NULL, NULL);
GLFWwindow* window4 = glfwCreateWindow(800, 600, "Triangles4", NULL, NULL);
// Initialize OpenGL
gl3wInit();
// Framebuffer Initialization
init_FB();
// Initialize Windows
glfwMakeContextCurrent(window);
init();
glfwMakeContextCurrent(window2);
init2();
glfwMakeContextCurrent(window3);
init3();
glfwMakeContextCurrent(window4);
init4();
// Draw the Windows
while (!glfwWindowShouldClose(window) && !glfwWindowShouldClose(window2) && !glfwWindowShouldClose(window3) && !glfwWindowShouldClose(window4))
{
glfwMakeContextCurrent(window);
compute_FB();
display();
glfwSwapBuffers(window);
glfwPollEvents();
glfwMakeContextCurrent(window2);
display2();
glfwSwapBuffers(window2);
glfwPollEvents();
glfwMakeContextCurrent(window3);
display3();
glfwSwapBuffers(window3);
glfwPollEvents();
glfwMakeContextCurrent(window4);
display4();
glfwSwapBuffers(window4);
glfwPollEvents();
}
// Destroy Windows
glfwDestroyWindow(window);
glfwDestroyWindow(window2);
glfwDestroyWindow(window3);
glfwDestroyWindow(window4);
// Terminate GLFW Instance
glfwTerminate();
}
编辑#2
感谢@Ripi2,我现在可以使用 glBlit 和渲染缓冲区。不知何故,尽管我没有正确使用第二个窗口的渲染缓冲区和不同的 FBO 中的一个或两个。 注意此时,我还没有在第三个或第四个窗口上实现 glBlit(虽然我会,一旦我可以成功地将渲染缓冲区和 glBlit 集成到第二个窗口中)
编辑 #2 代码
//////////////////////////////////////////////////////////////////////////////
//
// Triangles.cpp
//
//////////////////////////////////////////////////////////////////////////////
#include <cstdio>
#include "vgl.h"
#include "LoadShaders.h"
enum VAO_IDs { Triangles, NumVAOs };
enum Buffer_IDs { ArrayBuffer, NumBuffers };
enum Attrib_IDs { vPosition = 0 };
GLuint VAOs[NumVAOs];
GLuint Buffers[NumBuffers];
const GLuint NumVertices = 6;
////////////////////////////////////
//RBO variables
enum {Color=0, NumRenderBuffers=1, NumFBOs=4};
GLuint renderbuffer[NumRenderBuffers], fbos[NumFBOs];
GLuint buffwidth = 3200;
GLuint buffheight = 600;
//----------------------------------------------------------------------------
//
// init
//
void
init( void )
{
glCreateRenderbuffers(NumRenderBuffers, renderbuffer);
glNamedRenderbufferStorage(renderbuffer[Color], GL_RGBA, buffwidth, buffheight);
glGenFramebuffers(1, &fbos[0]);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[0]);
glNamedFramebufferRenderbuffer(fbos[0], GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer[Color]);
glGenVertexArrays( NumVAOs, VAOs );
glBindVertexArray( VAOs[Triangles] );
GLfloat vertices[NumVertices][2] = {
{ -0.90f, -0.90f }, { -0.90f, 0.90f }, { 0.00f, -0.90f }, // Triangle 1
{ 0.00f, 0.90f }, { 0.90f, 0.90f }, { 0.90f, -0.90f } // Triangle 2
};
glCreateBuffers( NumBuffers, Buffers );
glBindBuffer( GL_ARRAY_BUFFER, Buffers[ArrayBuffer] );
glBufferStorage( GL_ARRAY_BUFFER, sizeof(vertices), vertices, 0);
ShaderInfo shaders[] =
{
{ GL_VERTEX_SHADER, "media/shaders/triangles/triangles.vert" },
{ GL_FRAGMENT_SHADER, "media/shaders/triangles/triangles.frag" },
{ GL_NONE, NULL }
};
GLuint program = LoadShaders( shaders );
glUseProgram( program );
glVertexAttribPointer( vPosition, 2, GL_FLOAT,
GL_FALSE, 0, BUFFER_OFFSET(0) );
glEnableVertexAttribArray( vPosition );
}
void
init2( void )
{
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer[Color]);
glGenFramebuffers(1, &fbos[1]);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]);
glNamedFramebufferRenderbuffer(fbos[1], GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, renderbuffer[Color]);
}
void
init3( void )
{
glGenVertexArrays( NumVAOs, VAOs );
glBindVertexArray( VAOs[Triangles] );
GLfloat vertices[NumVertices][2] = {
{ -0.90f, -0.90f }, { -0.90f, 0.90f }, { 0.00f, -0.90f }, // Triangle 1
{ 0.00f, 0.90f }, { 0.90f, 0.90f }, { 0.90f, -0.90f } // Triangle 2
};
glCreateBuffers( NumBuffers, Buffers );
glBindBuffer( GL_ARRAY_BUFFER, Buffers[ArrayBuffer] );
glBufferStorage( GL_ARRAY_BUFFER, sizeof(vertices), vertices, 0);
ShaderInfo shaders[] =
{
{ GL_VERTEX_SHADER, "media/shaders/triangles/triangles.vert" },
{ GL_FRAGMENT_SHADER, "media/shaders/triangles/triangles.frag" },
{ GL_NONE, NULL }
};
GLuint program = LoadShaders( shaders );
glUseProgram( program );
glVertexAttribPointer( vPosition, 2, GL_FLOAT,
GL_FALSE, 0, BUFFER_OFFSET(0) );
glEnableVertexAttribArray( vPosition );
}
void
init4( void )
{
glGenVertexArrays( NumVAOs, VAOs );
glBindVertexArray( VAOs[Triangles] );
GLfloat vertices[NumVertices][2] = {
{ -0.40f, -0.40f }, { -0.40f, 0.40f }, { 0.00f, -0.40f }, // Triangle 1
{ 0.00f, 0.40f }, { 0.40f, 0.40f }, { 0.40f, -0.40f } // Triangle 2
};
glCreateBuffers( NumBuffers, Buffers );
glBindBuffer( GL_ARRAY_BUFFER, Buffers[ArrayBuffer] );
glBufferStorage( GL_ARRAY_BUFFER, sizeof(vertices), vertices, 0);
ShaderInfo shaders[] =
{
{ GL_VERTEX_SHADER, "media/shaders/triangles/triangles.vert" },
{ GL_FRAGMENT_SHADER, "media/shaders/triangles/triangles.frag" },
{ GL_NONE, NULL }
};
GLuint program = LoadShaders( shaders );
glUseProgram( program );
glVertexAttribPointer( vPosition, 2, GL_FLOAT,
GL_FALSE, 0, BUFFER_OFFSET(0) );
glEnableVertexAttribArray( vPosition );
}
//----------------------------------------------------------------------------
//
// display
//
void
display( void )
{
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[0]);
glViewport(0, 0, buffwidth, buffheight);
static const float black[] = { 0.2f, 0.2f, 0.2f, 0.0f };
static const float redish[] = { 0.6f, 0.4f, 0.3f, 0.0f };
glClearBufferfv(GL_COLOR, 0, black);
glBindVertexArray( VAOs[Triangles] );
glDrawArrays( GL_TRIANGLES, 0, NumVertices );
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbos[0]);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glViewport(0, 0, 800, 600);
glClearBufferfv(GL_COLOR, 0, redish);
glBlitFramebuffer(0, 0, 800, 600, 0, 0, 800, 600, GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
void
display2( void )
{
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbos[1]);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glViewport(0, 0, 800, 600);
static const float redish[] = { 0.6f, 0.4f, 0.3f, 0.0f };
glClearBufferfv(GL_COLOR, 0, redish);
glBlitFramebuffer(buffwidth, 0, buffwidth+800, 600, 0, 0, 800, 600, GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
void
display3( void )
{
static const float black[] = { 0.7f, 0.6f, 0.4f, 0.0f };
glClearBufferfv(GL_COLOR, 0, black);
glBindVertexArray( VAOs[Triangles] );
glDrawArrays( GL_TRIANGLES, 0, NumVertices );
}
void
display4( void )
{
static const float black[] = { 0.2f, 0.3f, 0.7f, 0.0f };
glClearBufferfv(GL_COLOR, 0, black);
glBindVertexArray( VAOs[Triangles] );
glDrawArrays( GL_TRIANGLES, 0, NumVertices );
}
//----------------------------------------------------------------------------
//
// main
//
#ifdef _WIN32
int CALLBACK WinMain(
_In_ HINSTANCE hInstance,
_In_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nCmdShow
)
#else
int
main( int argc, char** argv )
#endif
{
// Initialize GLFW
glfwInit();
// Initialize OpenGL
// Place it here before any OpenGL objects are needed, other OpenGL crashes
// ... in a "Segmentation fault (core dumped)" error
gl3wInit();
//TODO Create Windows Class
// Create Windows
GLFWwindow* window = glfwCreateWindow(800, 600, "Triangles", NULL, NULL);
GLFWwindow* window2 = glfwCreateWindow(800, 600, "Triangles2", NULL, window);
GLFWwindow* window3 = glfwCreateWindow(800, 600, "Triangles3", NULL, window);
GLFWwindow* window4 = glfwCreateWindow(800, 600, "Triangles4", NULL, window);
// Initialize Windows
glfwMakeContextCurrent(window);
init();
glfwMakeContextCurrent(window2);
init2();
glfwMakeContextCurrent(window3);
init3();
glfwMakeContextCurrent(window4);
init4();
// Draw the Windows
while (!glfwWindowShouldClose(window) && !glfwWindowShouldClose(window2) && !glfwWindowShouldClose(window3) && !glfwWindowShouldClose(window4))
{
glfwMakeContextCurrent(window);
display();
glfwSwapBuffers(window);
glfwPollEvents();
glfwMakeContextCurrent(window2);
display2();
glfwSwapBuffers(window2);
glfwPollEvents();
glfwMakeContextCurrent(window3);
display3();
glfwSwapBuffers(window3);
glfwPollEvents();
glfwMakeContextCurrent(window4);
display4();
glfwSwapBuffers(window4);
glfwPollEvents();
}
// Destroy Windows
glfwDestroyWindow(window);
glfwDestroyWindow(window2);
glfwDestroyWindow(window3);
glfwDestroyWindow(window4);
// Terminate GLFW Instance
glfwTerminate();
}
【问题讨论】:
-
您可以将三角形渲染到默认帧缓冲区吗?你确定蓝色是来自 blit 而不是以前的清除?
标签: c++ opengl rendering glfw framebuffer