Постановка задачи
Это должен быть действительно очевидный ответ, и где-то я, вероятно, испортил одну или две линии, и все же я не могу заставить треугольники рисовать в кадровом буфере.
Я пытаюсь получить два треугольника для большого объекта буфера рендеринга с прикрепленным кадровым буфером, а затем в одном из четырех окон отобразить фрагмент большего буфера / кадрового буфера рендеринга, используя glBlitFramebuffer.
Я использую init_FB()
для определения треугольников для рендеринга и RBO для рендеринга этих треугольников.Я создал объект renderbuffer и объект framebuffer, связанный с объектом renderbuffer.В функции compute_FB()
я связываю кадровый буфер RBO, а затем выполняю вызов для рисования в этом кадровом буфере.Прежде чем нарисовать треугольники, я очищаю кадровый буфер до определенного цвета, royalblue
.
Что происходит
В первом окне, которое называется window
, отображается следующее:только цвет royalblue
, определенный функцией (compute_FB()
), который рисует в кадровом буфере объекта renderbuffer.Однако ни один из треугольников не рисуется, хотя у меня есть функция glDrawArrays(...)
, вызываемая в конце compute_FB()
.
Возможная гипотеза о том, что происходит
Я начинаю верить, что RBO нужен свой собственный контекст для успешного рендеринга, но я не знаю, как настроить контекст дляБВУ.Я думал, что контексты были только для окон в GLFW.
Объяснение кода
Я основываю свою попытку на первоначальном примере OpenGL Redbook 01-треугольники.В этом примере я закодировал четыре уникальных окна и хочу со временем скопировать большой RBO / кадровый буфер в каждое из четырех окон - в настоящее время я просто фокусируюсь на первом дисплее.
Я использую OpenGL4.5 с GLFW для управления окнами.
КОД
//////////////////////////////////////////////////////////////////////////////
//
// 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 и renderbuffer.Как-то, хотя я не правильно использую один или оба из renderbuffer и другой FBO для второго окна. NOTE На данный момент я еще не реализую glBlit в третьем или четвертом окне (хотя я сделаю это, как только смогу успешно интегрировать renderbuffer и 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();
}