如何使用GLFW使用renderbuffer和glBlit渲染到四个Windows

时间:2018-10-10 00:07:55

标签: c++ opengl rendering glfw framebuffer

问题陈述

这应该是一个非常明显的答案,在某个地方我可能已经弄糟了一两行,但是我似乎无法让三角形绘制到帧缓冲区。

我想做的是将两个三角形添加到一个较大的渲染缓冲区对象,并附加一个帧缓冲区,然后在四个窗口之一中使用glBlitFramebuffer显示较大的渲染缓冲区/帧缓冲区的一部分。

我正在使用init_FB()定义要渲染的三角形以及要在其中渲染这些三角形的RBO。我创建了一个renderbuffer对象和一个与renderbuffer对象相关联的framebuffer对象。在compute_FB()函数中,我绑定了RBO的帧缓冲区,然后调用绘制到该帧缓冲区中。在绘制三角形之前,我将帧缓冲区清除为一种特定的颜色royalblue


真正发生的事情

在第一个称为window的窗口中,显示的只是由绘制到renderbuffer对象的帧缓冲区中的函数(royalblue)定义的颜色compute_FB()。但是,即使我在glDrawArrays(...)的末尾调用了compute_FB()函数,也没有绘制任何三角形。

可能发生的情况的假设

我开始相信RBO需要自己的上下文才能成功呈现,但是我不知道如何为RBO设置上下文。我认为上下文仅适用于GLFW中的Windows。


代码说明

我将基于最初的OpenGL Redbook示例01-三角形进行尝试。在此示例中,我已经编码了四个唯一的窗口,并最终希望将大的RBO /帧缓冲区复制到四个窗口中的每个窗口-目前,我仅关注第一个显示。

我正在将带有GLFW的OpenGL4.5用于窗口。


CODE

//////////////////////////////////////////////////////////////////////////////
//
//  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中的一个或两个。 注意至此,我还没有在第三个窗口或第四个窗口上实现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();
}

3 个答案:

答案 0 :(得分:1)

我看到一些问题:

您正在创建四个不同的gl上下文,每个窗口一个。您想将在window_1中渲染的帧缓冲区用于其他窗口。为此,您需要做两件事:
1)使用共享上下文,可以在glfwCreateWindow调用中创建共享上下文。
2)共享 renderbuffer RB ,而不是 FBO (不能共享FBO,如VAO)。这意味着您需要为每个窗口使用不同的FBO,并将相同的RB附加到每个FBO。

在从缓冲区(VBO)进行绘制之前,必须通过#recent-posts{ background: #D2C198; } #posts{ /*max-height: 90%;*/ overflow-y: auto; } .posts-container{ background-color: #D2C198; -webkit-box-shadow: 0 0px 0px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); -moz-box-shadow: 0 0px 0px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); box-shadow: 0 0px 0px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); } .card-header{ -webkit-box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); -moz-box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); padding: 0.35rem 1.25rem; } .forum-badge{ float: left; } .forum-badge img, .last-poster-avatar img, .reply-poster-avatar img, .reply-poster-guild-crest img{ -webkit-border-radius: 50%; -moz-border-radius: 50%; border-radius: 50%; object-fit: cover; } .forum-badge img{ width: 100px; height: 100px; } .divider{ border-bottom: 1px solid #222; padding-top: 5px; } .post-details{ padding-top: 10px; } .last-poster{ display: inline-flex; margin-left: 14px; } .post-description{ padding-left: 30px; height: 25px; margin-left: 86px; } .last-poster-avatar{ margin-right: 12px; } .last-poster-avatar img{ width: 50px; height: 50px; } .post-statistics, .reply-poster-guild-detail{ float: right; text-align: right; } .reply-poster-avatar, .reply-poster-detail, .reply-poster-guild-crest, .reply-poster-guild-detail{ display: inline-block; } .reply-poster-avatar{ vertical-align: top; float: left; } .reply-poster-avatar img{ width: 75px; height: 75px; } .reply-poster-detail{ /*width: 38.7%;*/ margin-left: 5px; float: left; } .reply-poster-detail div{ text-align: left; } .reply-poster-guild-crest{ padding-top: 18px; } .reply-poster-guild-crest img{ width: 40px; height: 40px; } .reply-poster-guild-detail,.reply-poster-detail{ top: 11px; position: relative; } .reply-detail-container{ width: 100%; text-align: center; } .replier-avatar-detail { float: left; display: inline-block; } .replier-avatar-detail, .reply-poster-guild-detail { max-width: 50%; min-width: 45%; } <div id="recent-posts" class="card"> <div class="card-body"> <div id="posts"> <div class="card posts-container" id="a"> <div class="card-header post" data-toggle="collapse" data-target="#post-replies" aria-expanded="true" aria-controls="post-replies"> <div class="forum-badge"> <img src="https://i.postimg.cc/6QjQvk77/poedelve_copy.jpg" alt="Path of Exile"> </div> <div class="post-container"> <div class="post-description"> <h5 class="mb-0"><div><!-- Post text goes here-->Sulphite WP farming is stupid as hell</div></h5> <div class="divider"></div> </div> <div class="post-details"> <div class="last-poster"> <div class="last-poster-avatar"> <img src="https://i.postimg.cc/NfHQ0y7r/img_avatar.png" alt="Last Poster Avatar"> </div> <div class="poster-detail-sm"> <div>Harold</div> <div>3 hours ago</div> </div> </div> <div class="post-statistics"> <div class="post-replies"> Replies <span>999</span> </div> <div class="post-views"> Views <span>999,999</span> </div> </div> </div> </div> </div> <!-- replies section --> <div id="post-replies" class="collapse replies-container" aria-labelledby="a list of replies" data-parent="#posts"><!-- New replies must have dash and postnumber following post-replies e.g post-replies-223333 --> <div class="card-body"> <!-- replies --> <div id="replies"><!-- New replies must have dash and postnumber following replies e.g replies-223333 --> <div class="card replies-container"> <div class="card-header reply" data-toggle="collapse" data-target="#reply-content" aria-expanded="true" aria-controls="reply-content"><!-- New replies must have dash and postnumber following reply-content e.g reply-content-223333 --> <div class="reply-detail-container"> <div class="replier-avatar-detail"> <div class="reply-poster-avatar"> <img src="https://i.postimg.cc/cJHx0FDd/female-default.png" alt="Poster's Avatar"> </div> <div class="reply-poster-detail"> <div>Aurianna</div> <div>2 hours ago</div> </div> </div> <div class="reply-poster-guild-crest"> <img src="https://i.postimg.cc/yYH7k1fQ/Dragon-design.jpg" alt="Guild Crest"> </div> <div class="reply-poster-guild-detail"> <div>House of Myrmadons</div> <div>Rank: Officer</div> </div> </div> </div> <div id="reply-content" class="reply-message collapse" aria-labelledby="reply-header" data-parent="#replies"><!-- New replies must have dash and postnumber following reply-content e.g reply-content-223333 --> <div class="card-body poster-body"> Reply Content Here </div> </div> </div> <div class="card replies-container"> <div class="card-header reply" data-toggle="collapse" data-target="#reply-content1" aria-expanded="true" aria-controls="reply-content1"><!-- New replies must have dash and postnumber following reply-content e.g reply-content-223333 --> <div class="reply-detail-container"> <div class="replier-avatar-detail"> <div class="reply-poster-avatar"> <img src="https://i.postimg.cc/cJHx0FDd/female-default.png" alt="Poster's Avatar"> </div> <div class="reply-poster-detail"> <div>Chris</div> <div>2 hours ago</div> </div> </div> <div class="reply-poster-guild-crest"> <img src="https://i.postimg.cc/yYH7k1fQ/Dragon-design.jpg" alt="Guild Crest"> </div> <div class="reply-poster-guild-detail"> <div>House of GGG</div> <div>Rank: CEO</div> </div> </div> </div> <div id="reply-content1" class="reply-message collapse" aria-labelledby="reply-header" data-parent="#replies"><!-- New replies must have dash and postnumber following reply-content e.g reply-content-223333 --> <div class="card-body poster-body"> <div>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus accusantium amet autem corporis, deserunt eaque facilis laborum magni nobis officia officiis optio quibusdam, quisquam repellat velit. Molestiae non temporibus voluptatum! </div> <div>Ad consequuntur corporis cum cumque dolorem hic incidunt iure natus necessitatibus nihil obcaecati officiis quas quibusdam quis quo repellat reprehenderit ut, vel vitae, voluptatum. Accusamus ad obcaecati odio vero voluptas. </div> </div> </div> </div> <div class="card replies-container"> <div class="card-header reply" data-toggle="collapse" data-target="#reply-content3" aria-expanded="true" aria-controls="reply-content3"><!-- New replies must have dash and postnumber following reply-content e.g reply-content-223333 --> <div class="reply-detail-container"> <div class="replier-avatar-detail"> <div class="reply-poster-avatar"> <img src="https://i.postimg.cc/cJHx0FDd/female-default.png" alt="Poster's Avatar"> </div> <div class="reply-poster-detail"> <div>Chris</div> <div>2 hours ago</div> </div> </div> <div class="reply-poster-guild-crest"> <img src="https://i.postimg.cc/yYH7k1fQ/Dragon-design.jpg" alt="Guild Crest"> </div> <div class="reply-poster-guild-detail"> <div>House of GGG</div> <div>Rank: CEO</div> </div> </div> </div> <div id="reply-content3" class="reply-message collapse" aria-labelledby="reply-header" data-parent="#replies"><!-- New replies must have dash and postnumber following reply-content e.g reply-content-223333 --> <div class="card-body poster-body"> <div>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus accusantium amet autem corporis, deserunt eaque facilis laborum magni nobis officia officiis optio quibusdam, quisquam repellat velit. Molestiae non temporibus voluptatum! </div> <div>Ad consequuntur corporis cum cumque dolorem hic incidunt iure natus necessitatibus nihil obcaecati officiis quas quibusdam quis quo repellat reprehenderit ut, vel vitae, voluptatum. Accusamus ad obcaecati odio vero voluptas. </div> </div> </div> </div> </div> <!-- End replies --> </div> </div> </div> 在VAO中对其进行“关联”。换句话说,每个窗口都需要自己的VAO。
您不是在请求 Core Profile 上下文。这是通过glVertexAttribPointercontext hints 之前 glfwWindowHint来实现的。不这样做可能会起作用,因为某些驱动程序会提供兼容性配置文件;但可能并非如此,因此最好使用Core Profile。核心个人资料需要要求

在将某些gl-context设置为current之后,应调用

glfwCreateWindow。我不知道glfw是否以某种方式使当前上下文成为当前上下文,所以您不会出错。

您的枚举分别为gl3wInit()NumVAOs = 1。因此,NumBuffers = 1和其他glGenVertexArrays调用覆盖了最后一个值。这会使图纸弄乱。

glGenXXX,您创建了一个VBO,但未设置其大小。因此,init()不知道必须“清除”多少字节。

答案 1 :(得分:1)

最后找到了解决方法。

注释

  • 我要感谢Ripi2朝着正确的方向提供文档和代码的初审。我非常感谢您的帮助和指导。
  • 此答案中发布的代码不是复杂的,也不是预期的,因此,这显然不是生产质量的代码。我在这里概述的内容应该容易被任何人阅读-无论是初学者还是高级者
  • 作为一个经验不足的OpenGL程序员,可能做出的风格选择不是最佳或最佳实践。我将更新此答案,以反映对该代码的任何可行改进,对于那些新概念的新手仍然保持易读性。
  • 我想采用的更复杂的窗口系统看起来像this.,这里的开发人员创建了一个非常强大的窗口系统。如果要进行更改,那就是创建一个窗口类。但是...这是一次学术讨论,与当前的答案高度相切。

什么是解决方案?

  1. 正在处理上下文共享。再次感谢Ripi2 。最初,我要在单独的上下文中渲染大帧缓冲区,例如在第五个窗口(不可见窗口)中渲染,然后对每个活动窗口执行glBlit复制。这可能行得通,但是在指导下,我被告知要在主窗口中执行实际渲染,然后将其复制到最后三个窗口中。因为操作较少,所以速度更快
  2. 实际上打开了与GLFW的上下文共享。每个glfwCreateWindow();命令的末尾是一个参数,从另一个窗口传递上下文。由于我是在第一个窗口的初始init()中创建渲染缓冲区的,因此必须为所有其他三个窗口的最终参数设置window,例如:GLFWwindow *window2 = glfwCreateWindow(width, height, title, NULL, window-whose-context-i-want-to-share);
  3. 对我来说,困难的部分是确切地知道如何导航可共享渲染缓冲区对象的想法,其数据也可以共享,但是您只能通过不能访问的项目来访问它跨上下文共享。这导致了为所有窗口提供一个渲染缓冲区,为每个窗口提供一个帧缓冲区的想法。事实证明,实际执行此操作比预期的要简单-但这是经过数小时的阅读和研究之后。希望这个答案将帮助您跳过问题的核心。
  4. 每次调用init函数之一都会创建一个帧缓冲区,并将渲染缓冲区绑定到当前上下文。
  5. 您必须将渲染缓冲区重新绑定到当前上下文,即使它是共享资源。不这样做将不会从第一个display()函数中加载渲染的数据。换句话说,虽然渲染的数据仍然存在,但是只有在将其绑定到当前上下文中之后,您才能访问它……每次更改渲染到新窗口时。
  6. 我只需要弄清
  7. REALLY 重要部分,就可以确保设置了正确的 renderbuffer-target 。在这种情况下,您会在init2(const int)中注意到将当前上下文的帧缓冲区绑定到共享渲染缓冲区glNamedFramebufferRenderbuffer(...)的命令必须具有与 renderbuffer-target 相同的init()GL_COLOR_ATTACHMENT0中定义的原始 renderbuffer-target 。事后看来,这应该是显而易见的,但是很难找到用于渲染缓冲区对象的多窗口渲染的文档数量。几乎所有其他人都使用glTexture对象而不是renderbuffers进行了演示。 GL_COLOR_ATTACHMENTi就像一个内部地址,可以存储多组渲染的数据,这对于以后的项目是一个很好的提示。
  8. display2(const int)函数中为每个上下文绑定帧缓冲区时,此处要设置的重要一点是,帧缓冲区仅要从渲染缓冲区进行 READ ,因此请使用{{1 }}-因为数据已经存在,并且我们只是使用framebuffer对象作为获取对renderbuffer中数据的一种方式。 FBO是管道,而不是存储设备。实际上,如果不先附加FBO,就无法访​​问渲染缓冲区中的数据。
  9. 调试-我开始使用GL_READ_FRAMEBUFFER函数家族的各种版本,以获取有关不同上下文中的渲染缓冲区以及帧缓冲区的信息。当获得的结果符合我的期望时,我知道自己的方向正确。您将在glGet中看到,我在其中留下了两行以获取renderbuffer参数:width。我在此代码段中将其留给了其他可能对其工作方式感兴趣的人。从display2(const int)函数进行警告打印对于除基本调试以外的任何事情都不是一个好主意,因为它将每个周期写入一次控制台-写入stdout太慢了。

代码

display

最终渲染

enter image description here

答案 2 :(得分:0)

您的初始化功能正在尝试在上下文之间共享状态。 GL的上下文是所有GL状态的实例,只有instructed to do so explicitly when initialized时,上下文才共享数据。我建议只使用一个窗口,然后使用glviewport对其进行分区。

也许您还犯了一个错误,即没有使对象成为数组数组,因为每个glgen都会覆盖它们。这不是GL的错误,而是C数组语法的错误。