[英]how to use framebuffer in a separate viewport along with default framebuffer?
我試圖了解幀緩沖如何工作。 AFAIK,幀緩沖區可以將渲染存儲為紋理,而渲染緩沖區存儲深度信息,而顏色緩沖區存儲顏色信息。 有一個默認的幀緩沖區,然后是我可能創建的用於存儲單獨渲染的任何其他幀緩沖區。 現在,我想在整個屏幕上渲染默認的幀緩沖區,而在一個小的側面視口上,應該有我的新幀緩沖區存儲的渲染。 這在下面的源代碼中沒有發生。
代碼:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <stdio.h>
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
int main() {
GLFWwindow *window = NULL;
GLuint vao;
GLuint vbo;
GLfloat points[] = { 0.0f, 0.5f, 0.0f, 0.5f, -0.5f, 0.0f, -0.5f, -0.5f, 0.0f };
const char *vertex_shader = "#version 410\n"
"in vec3 vp;"
"void main () {"
" gl_Position = vec4(vp, 1.0);"
"}";
const char *fragment_shader = "#version 410\n"
"out vec4 frag_colour;"
"void main () {"
" frag_colour = vec4(0.5, 0.0, 0.5, 1.0);"
"}";
GLuint vert_shader, frag_shader;
GLuint shader_programme;
if ( !glfwInit() ) {
fprintf( stderr, "ERROR: could not start GLFW3\n" );
return 1;
}
glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 4 );
glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 6 );
glfwWindowHint( GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE );
glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
window = glfwCreateWindow( WINDOW_WIDTH, WINDOW_HEIGHT, "Hello Triangle", NULL, NULL );
if ( !window ) {
fprintf( stderr, "ERROR: could not open window with GLFW3\n" );
glfwTerminate();
return 1;
}
glfwMakeContextCurrent( window );
glewExperimental = GL_TRUE;
glewInit();
glEnable( GL_DEPTH_TEST ); /* enable depth-testing */
glDepthFunc( GL_LESS );
glGenBuffers( 1, &vbo );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, 9 * sizeof( GLfloat ), points, GL_STATIC_DRAW );
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
glEnableVertexAttribArray( 0 );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, NULL );
vert_shader = glCreateShader( GL_VERTEX_SHADER );
glShaderSource( vert_shader, 1, &vertex_shader, NULL );
glCompileShader( vert_shader );
frag_shader = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( frag_shader, 1, &fragment_shader, NULL );
glCompileShader( frag_shader );
shader_programme = glCreateProgram();
glAttachShader( shader_programme, frag_shader );
glAttachShader( shader_programme, vert_shader );
glLinkProgram( shader_programme );
GLuint g_fb;
GLuint g_fb_tex;
glGenFramebuffers( 1, &g_fb );
glGenTextures( 1, &g_fb_tex );
glBindTexture( GL_TEXTURE_2D, g_fb_tex );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, WINDOW_WIDTH/2, WINDOW_HEIGHT/2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glBindFramebuffer( GL_FRAMEBUFFER, g_fb );
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, g_fb_tex, 0 );
GLuint rb = 0;
glGenRenderbuffers( 1, &rb );
glBindRenderbuffer( GL_RENDERBUFFER, rb );
glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT, WINDOW_WIDTH/2, WINDOW_HEIGHT/2 );
glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb );
GLenum draw_bufs[] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers( 1, draw_bufs );
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
while ( !glfwWindowShouldClose( window ) ) {
glBindFramebuffer(GL_FRAMEBUFFER, g_fb);
glViewport(0, 0, WINDOW_WIDTH/2, WINDOW_HEIGHT/2);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glUseProgram( shader_programme );
glBindVertexArray( vao );
glDrawArrays( GL_TRIANGLES, 0, 3 );
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glUseProgram( shader_programme );
glBindVertexArray( vao );
glDrawArrays( GL_TRIANGLES, 0, 3 );
glfwPollEvents();
glfwSwapBuffers( window );
}
glfwTerminate();
return 0;
}
在這里,僅最后提到的緩沖區被渲染。 我該如何糾正? 另外,我在項目中編寫了一個場景類和一個渲染器類。 應該為每個渲染器對象存儲幀緩沖區,還是應該在場景類中存儲任何渲染器實例的所有幀緩沖區? 主要是,存儲多個fbo需要多少存儲/計算量?
編輯 :我按照答案中的說明放置了新紋理,但是我仍然只獲得上一次渲染的結果。 請指出錯誤。 我是否需要為新的幀緩沖區使用新的着色器? 如果是這樣,為什么以前的着色器不能重復使用?
碼:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <stdio.h>
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
int main() {
GLFWwindow *window = NULL;
GLuint vao;
GLuint vbo;
GLfloat points[] = { 0.0f, 0.5f, 0.0f, 0.5f, -0.5f, 0.0f, -0.5f, -0.5f, 0.0f };
const char *vertex_shader = "#version 410\n"
"in vec3 vp;"
"void main () {"
" gl_Position = vec4(vp, 1.0);"
"}";
const char *fragment_shader = "#version 410\n"
"out vec4 frag_colour;"
"void main () {"
" frag_colour = vec4(0.5, 0.0, 0.5, 1.0);"
"}";
GLuint vert_shader, frag_shader;
GLuint shader_programme;
if ( !glfwInit() ) {
fprintf( stderr, "ERROR: could not start GLFW3\n" );
return 1;
}
glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 4 );
glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 6 );
glfwWindowHint( GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE );
glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
window = glfwCreateWindow( WINDOW_WIDTH, WINDOW_HEIGHT, "Hello Triangle", NULL, NULL );
if ( !window ) {
fprintf( stderr, "ERROR: could not open window with GLFW3\n" );
glfwTerminate();
return 1;
}
glfwMakeContextCurrent( window );
glewExperimental = GL_TRUE;
glewInit();
glEnable( GL_DEPTH_TEST ); /* enable depth-testing */
glDepthFunc( GL_LESS );
glGenBuffers( 1, &vbo );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, 9 * sizeof( GLfloat ), points, GL_STATIC_DRAW );
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
glEnableVertexAttribArray( 0 );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, NULL );
vert_shader = glCreateShader( GL_VERTEX_SHADER );
glShaderSource( vert_shader, 1, &vertex_shader, NULL );
glCompileShader( vert_shader );
frag_shader = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( frag_shader, 1, &fragment_shader, NULL );
glCompileShader( frag_shader );
shader_programme = glCreateProgram();
glAttachShader( shader_programme, frag_shader );
glAttachShader( shader_programme, vert_shader );
glLinkProgram( shader_programme );
GLuint g_fb;
GLuint g_fb_tex;
glGenFramebuffers( 1, &g_fb );
glGenTextures( 1, &g_fb_tex );
glBindTexture( GL_TEXTURE_2D, g_fb_tex );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, WINDOW_WIDTH/2, WINDOW_HEIGHT/2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glBindFramebuffer( GL_FRAMEBUFFER, g_fb );
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, g_fb_tex, 0 );
GLuint rb = 0;
glGenRenderbuffers( 1, &rb );
glBindRenderbuffer( GL_RENDERBUFFER, rb );
glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT, WINDOW_WIDTH/2, WINDOW_HEIGHT/2 );
glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb );
GLenum draw_bufs[] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers( 1, draw_bufs );
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
while ( !glfwWindowShouldClose( window ) ) {
glBindFramebuffer(GL_FRAMEBUFFER, g_fb);
glViewport(0, 0, WINDOW_WIDTH/2, WINDOW_HEIGHT/2);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glUseProgram( shader_programme );
glBindVertexArray( vao );
glDrawArrays( GL_TRIANGLES, 0, 3 );
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glUseProgram( shader_programme );
glBindVertexArray( vao );
glDrawArrays( GL_TRIANGLES, 0, 3 );
GLuint m_vbo, m_vao;
GLfloat points[] = {
-0.5f, 0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f
};
glGenBuffers(1, &m_vbo);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), points, GL_STATIC_DRAW);
glGenVertexArrays(1, &m_vao);
glBindVertexArray(m_vao);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glBindTexture(GL_TEXTURE_2D, g_fb_tex);
glViewport(0, 0, WINDOW_WIDTH/2, WINDOW_HEIGHT/2);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glUseProgram( shader_programme );
glBindVertexArray( m_vao );
glDrawArrays( GL_TRIANGLES, 0, 6 );
glfwPollEvents();
glfwSwapBuffers( window );
}
glfwTerminate();
return 0;
}
渲染循環的第一塊渲染為g_fb
。 結果進入g_fb_tex
。 如果要在窗口的“小視口”(= framebuffer 0)上顯示此紋理,則應渲染適當大小的矩形並使用從g_fb_tex
采樣的着色器。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.