这应该是一个非常明显的答案,在某个地方我可能已经弄糟了一两行,但是我似乎无法让三角形绘制到帧缓冲区。
我想做的是将两个三角形添加到一个较大的渲染缓冲区对象,并附加一个帧缓冲区,然后在四个窗口之一中使用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用于窗口。
//////////////////////////////////////////////////////////////////////////////
//
// 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();
}
由于@ 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();
}
答案 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 上下文。这是通过glVertexAttribPointer
与context hints 之前 glfwWindowHint
来实现的。不这样做可能会起作用,因为某些驱动程序会提供兼容性配置文件;但可能并非如此,因此最好使用Core Profile。核心个人资料需要要求。
glfwCreateWindow
。我不知道glfw是否以某种方式使当前上下文成为当前上下文,所以您不会出错。
您的枚举分别为gl3wInit()
和NumVAOs = 1
。因此,NumBuffers = 1
和其他glGenVertexArrays
调用覆盖了最后一个值。这会使图纸弄乱。
在glGenXXX
,您创建了一个VBO,但未设置其大小。因此,init()
不知道必须“清除”多少字节。
答案 1 :(得分:1)
注释
glBlit
复制。这可能行得通,但是在指导下,我被告知要在主窗口中执行实际渲染,然后将其复制到最后三个窗口中。因为操作较少,所以速度更快glfwCreateWindow();
命令的末尾是一个参数,从另一个窗口传递上下文。由于我是在第一个窗口的初始init()
中创建渲染缓冲区的,因此必须为所有其他三个窗口的最终参数设置window
,例如:GLFWwindow *window2 = glfwCreateWindow(width, height, title, NULL, window-whose-context-i-want-to-share);
init
函数之一都会创建一个帧缓冲区,并将渲染缓冲区绑定到当前上下文。display()
函数中加载渲染的数据。换句话说,虽然渲染的数据仍然存在,但是只有在将其绑定到当前上下文中之后,您才能访问它……每次更改渲染到新窗口时。init2(const int)
中注意到将当前上下文的帧缓冲区绑定到共享渲染缓冲区glNamedFramebufferRenderbuffer(...)
的命令必须具有与 renderbuffer-target 相同的init()
:GL_COLOR_ATTACHMENT0
中定义的原始 renderbuffer-target 。事后看来,这应该是显而易见的,但是很难找到用于渲染缓冲区对象的多窗口渲染的文档数量。几乎所有其他人都使用glTexture对象而不是renderbuffers进行了演示。 GL_COLOR_ATTACHMENTi
就像一个内部地址,可以存储多组渲染的数据,这对于以后的项目是一个很好的提示。display2(const int)
函数中为每个上下文绑定帧缓冲区时,此处要设置的重要一点是,帧缓冲区仅要从渲染缓冲区进行 READ ,因此请使用{{1 }}-因为数据已经存在,并且我们只是使用framebuffer对象作为获取对renderbuffer中数据的一种方式。 FBO是管道,而不是存储设备。实际上,如果不先附加FBO,就无法访问渲染缓冲区中的数据。GL_READ_FRAMEBUFFER
函数家族的各种版本,以获取有关不同上下文中的渲染缓冲区以及帧缓冲区的信息。当获得的结果符合我的期望时,我知道自己的方向正确。您将在glGet
中看到,我在其中留下了两行以获取renderbuffer参数:width。我在此代码段中将其留给了其他可能对其工作方式感兴趣的人。从display2(const int)
函数进行警告打印对于除基本调试以外的任何事情都不是一个好主意,因为它将每个周期写入一次控制台-写入stdout太慢了。display
答案 2 :(得分:0)
您的初始化功能正在尝试在上下文之间共享状态。 GL的上下文是所有GL状态的实例,只有instructed to do so explicitly when initialized时,上下文才共享数据。我建议只使用一个窗口,然后使用glviewport对其进行分区。
也许您还犯了一个错误,即没有使对象成为数组数组,因为每个glgen都会覆盖它们。这不是GL的错误,而是C数组语法的错误。