如何在OpenGL中绘制到屏幕外颜色缓冲区,然后将结果绘制到精灵曲面?

apeeds0o  于 2022-11-04  发布在  其他
关注(0)|答案(1)|浏览(172)

以下是对该问题的描述:
1.我想渲染一些VBO形状(矩形,圆形等)到一个屏幕外的帧缓冲对象。这可以是任何形状。
1.然后我想在一个简单的sprite表面上绘制结果作为纹理,而不是在整个屏幕本身上。
我似乎无法使它正常工作。
当我运行代码时,我看到图形被绘制在整个屏幕上,但中间的sprite中没有。它仍然是空白的。尽管看起来我用1个颜色纹理设置了FBO,但它仍然只呈现在屏幕上,即使我在上下文中选择了FBO对象。
我想要实现的是将这些形状绘制到屏幕外的纹理上(显然是使用FBO),然后将其渲染到屏幕上某个位置绘制的sprite(或立方体,或我们)的表面上。然而,无论我绘制什么,看起来都是在屏幕上绘制的。
tex(tex_对象_ID);函数只是OpenGL标准纹理绑定的一个简单的 Package 器。它选择一个纹理到当前的渲染环境中。
无论我怎么尝试我都得到这样的结果:sprite是空白的,但是所有这些形状应该出现在那里,而不是在主屏幕上。(我没有绑定渲染到FBO吗?为什么它仍然在屏幕上渲染?)

我想这只是一个逻辑设置FBO在正确的顺序,我错过了。谁能告诉我的代码有什么问题?
不知道为什么背景是红色的,因为我清除它后,我选择了FBO。这是精灵,应该得到红色的背景和形状画在它上面。

/*-- Initialization -- */

GLuint texture = 0;
GLuint Framebuffer = 0;

GLuint GenerateFrameBuffer(int dimension)
{
    glEnable(GL_TEXTURE_2D);
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, dimension, dimension, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);

    glGenFramebuffers(1, &Framebuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, Framebuffer);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);

    glDrawBuffer(GL_COLOR);
    glReadBuffer(GL_COLOR);

    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
        console_log("GL_FRAMEBUFFER != GL_FRAMEBUFFER_COMPLETE\n");

    return texture;
}

// Store framebuffer texture (should I store texture here or Framebuffer object?)
GLuint FramebufferHandle = GenerateFrameBuffer( 256 );

标准的OpenGL初始化代码如下,内存分配,VBO的创建和绑定,等等。这是正确的工作,没有错误的初始化。我可以渲染VBO,多边形,纹理多边形,线等,在标准的双缓冲区成功。
接下来,在渲染循环中,我执行以下操作:

// Possible problem?
// Should FramebufferHandle be passed here?
// I tried "texture" and "Framebuffer " as well, to no effect:

glBindFramebuffer(GL_FRAMEBUFFER, FramebufferHandle); 

// Correct projection, just calculates the view based on current zoom
Projection = setOrthoFrustum(-config.zoomed_width/2, config.zoomed_width/2, -config.zoomed_height/2, config.zoomed_height/2, 0, 100);
View.identity();
Model.identity();

// Mini shader, 100%  *guaranteed* to work, there are no errors in it (works normally on the screen)
shaderProgramMini.use();

//Clear frame buffer with blue color
glClearColor(0.0f, 0.0f, 1.0f,  1.0f);
glClear(GL_COLOR_BUFFER_BIT);// | GL_DEPTH_BUFFER_BIT);

// Set yellow to draw different shapes on the framebuffer
color = {1.0f,1.0f,0.0f};

// Draw several shapes (already correctly stored in VBO objects)
Memory.select(VBO_RECTANGLES); // updates uniforms
glDrawArrays(GL_QUADS, 0, Memory.renderable[VBO_RECTANGLES].indexIndex);
Memory.select(VBO_CIRCLES); // updates uniforms
glDrawArrays(GL_LINES, 0, Memory.renderable[VBO_CIRCLES].indexIndex);
Memory.select(VBO_2D_LIGHT); // updates uniforms
glDrawArrays(GL_LINES, 0, Memory.renderable[VBO_2D_LIGHT].indexIndex);

// Done writing to framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);

// Correct projection, just calculates the view based on current zoom
Projection = setOrthoFrustum(-config.zoomed_width/2, config.zoomed_width/2, -config.zoomed_height/2, config.zoomed_height/2, 0, 100);
View.identity();
Model.identity();
Model.scale(10.0);

// Select texture shader to draw what was drawn on offscreen Framebuffer / texture
// Standard texture shader, 100% *guaranteed* to work, there are no errors in it (works normally on the screen)
shaderProgramTexture.use();

// This is a wrapper for bind texture to ID, just shorthand function name
tex(texture); // FramebufferHandle; // ? // maybe the mistake in binding to the wrong target object?

color = {0.5f,0.2f,0.0f};
Memory.select(VBO_SPRITE); Select a square VBO for rendering sprites (works if any other texture is assigned to it)

// finally draw the sprite with Framebuffer's texture:
glDrawArrays(GL_TRIANGLES, 0, Memory.renderable[VBO_SPRITE].indexIndex);

我可能得到了一些完全错误的顺序。或者FramebufferHandle/Framebuffer/texture对象没有被正确地传递给一些东西。但是我花了一整天的时间,希望比我更有经验的人能看到这个错误。

qeeaahzv

qeeaahzv1#

GL_COLOR不是glDrawBuffer的可接受值
请参阅OpenGL 4.6 API Compatibility Profile Specification, 17.4.1 Selecting Buffers for Writing, Table 17.4 and Table 17.5, page 628
第一个月第二个月第一个月,第一个月第三个月,第一个月第四个月,第一个月第五个月,第一个月第六个月,第一个月第七个月,第一个月第八个月,第一个月第九个月,第一个月第十个月,第一个月第十一个月,第一个月第十二个月。
DrawBuffer的参数(当上下文绑定到默认帧缓冲区时),以及它们所指示的缓冲区。相同的参数对ReadBuffer有效,但只选择了一个缓冲区,如第节所述。
COLOR_ATTACHMENTi
当上下文绑定到帧缓冲区对象时,DrawBuffer(s)和ReadBuffer的参数,以及它们指示的缓冲区。COLOR_ATTACHMENTi中的 i 的范围可以从零到MAX_COLOR_ATTACHMENTS的值减一。
这意味着glDrawBuffer(GL_COLOR);glReadBuffer(GL_COLOR);将生成GL_INVALID_ENUM错误。请尝试改用COLOR_ATTACHMENT0
此外,glCheckFramebufferStatus(GL_FRAMEBUFFER)检查绑定到 target 的帧缓冲区对象的完整性。
这就意味着

glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE

必须在之前

glBindFramebuffer(GL_FRAMEBUFFER, 0);

或者您必须用途:

glNamedFramebufferReadBuffer(Framebuffer, GL_FRAMEBUFFER);

相关问题