我最近需要在QT + OPENGL环境中实现一个功能,也就是说,我在自己定义的帧缓冲区(我将其定义为fbo)中绘制了一个多维数据集(大概在视图的中心),并将其着色为红色。而且没有在默认缓冲区中绘制任何内容,因此我在视图中看不到我的多维数据集(但它是在帧缓冲区fbo中绘制的)
我希望当我单击视图中间(多维数据集的位置)时,可以显示多维数据集的颜色-红色,而不是视图背景的颜色。
这是我遇到的问题: 我只能用鼠标获得视图背景的颜色,并且不会拾取在帧缓冲区中绘制的多维数据集(该多维数据集为红色)。
在initializeGL()
函数中,我初始化并配置了帧缓冲区fbo以及绘制立方体所需的一些配置。
在paintGL()
函数中,我将定义的帧缓冲区绑定到GL_FRAMEBUFFER
,然后进行绘制。
在mousePressEvent(QMouseEvent *e)
函数中,我进行了拣配工作。这是QT鼠标单击的响应功能。我将glReadPixels
读取的信息放入数组pix中并打印出来。
void OpenglWidget::initializeGL()
{
core1 = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_4_0_Core>();
core = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_3_Core>();
core->glGenFramebuffers(1, &fbo);
core->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
// Create the texture object for the primitive information buffer
core->glGenTextures(1, &m_pickingTexture);
glBindTexture(GL_TEXTURE_2D, m_pickingTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32UI, SCR_WIDTH, SCR_HEIGHT,
0, GL_RGB_INTEGER, GL_UNSIGNED_INT, NULL);
core1->glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D,
m_pickingTexture, 0);
// Create the texture object for the depth buffer
core->glGenTextures(1, &m_depthTexture);
core->glBindTexture(GL_TEXTURE_2D, m_depthTexture);
core->glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, SCR_WIDTH, SCR_HEIGHT,
0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
core1->glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
m_depthTexture, 0);
// Disable reading to avoid problems with older GPUs
core->glReadBuffer(GL_NONE);
// Verify that the FBO is correct
GLenum Status = core->glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (Status == GL_FRAMEBUFFER_COMPLETE) {
qDebug() << "ok";
}
// Restore the default framebuffer
core->glBindTexture(GL_TEXTURE_2D, 0);
core->glBindFramebuffer(GL_FRAMEBUFFER, 0);
GLfloat verticPosition[] = {
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
-0.5f, 0.5f, -0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, -0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
0.5f, 0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
0.5f, -0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, -0.5f,
};
GLint beamIndices[] = {
0,1,2,3,4,5,6,7
};
core->glGenVertexArrays(1, &VAOBeam);
core->glGenBuffers(1, &VBOBeam);
core->glGenBuffers(1, &EBOBeam);
core->glBindVertexArray(VAOBeam);
core->glBindBuffer(GL_ARRAY_BUFFER, VBOBeam);
core->glBufferData(GL_ARRAY_BUFFER,sizeof(float) * 3 * 36, verticPosition, GL_STATIC_DRAW);
core->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBOBeam);
core->glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLint) * 8, beamIndices, GL_STATIC_DRAW);
core->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
core->glEnableVertexAttribArray(0);
core->glBindBuffer(GL_ARRAY_BUFFER, 0);
core->glBindVertexArray(0);
}
void OpenglWidget::paintGL()
{
core->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glClearColor(0,0,1,1);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
float frametime =GetFrameTime();
mCamera.Update(frametime);
Shader GLprogram = Shader("E:\\QT\\OpenglTest\\vs.vert","E:\\QT\\OpenglTest\\fs.frag");
GLprogram.use();
core->glBindVertexArray(VAOBeam);
glm::mat4 model = glm::mat4(1.0f);
model = glm::translate(model, mCamera.TempTranslateVrc);
glm::mat4 view = glm::mat4(1.0f);
//view = glm::lookAt(glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(0.5f,0.5f,0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
view = glm::lookAt(mCamera.mPos,mCamera.mViewCenter,mCamera.mUp);
glm::mat4 projection = glm::mat4(1.0f);
projection = glm::perspective(glm::radians(45.0f), (float)1.0, 0.1f, 100.0f);
GLprogram.setMatrix4f("model",model);
GLprogram.setMatrix4f("view",view);
GLprogram.setMatrix4f("projection",projection);
core->glDrawArrays(GL_TRIANGLES,0,36);
core->glUseProgram(0);
update();
}
void OpenglWidget::mousePressEvent(QMouseEvent *e)
{
core1 = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_4_0_Core>();
float pix[4] = {0.0};
mCamera.getInitPos(e->x(),e->y());//This is the camera's setup function, no need to worry about it.
core1->glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
core1->glReadBuffer(GL_COLOR_ATTACHMENT1);
core1->glReadPixels(e->x() , 500 - e->y() + 65, 1, 1, GL_RGBA, GL_FLOAT, pix);
qDebug() << e->x()<< 500 - e->y() <<pix[0] << pix[1] << pix[2] << pix[3];
}
我只能用鼠标获得视图背景的颜色,并且不会拾取在帧缓冲区中绘制的多维数据集(多维数据集为红色)。
答案 0 :(得分:1)
引起该问题的原因是,在附加到GLCOLOR ATTACHMENT1
的颜色缓冲区中,从未渲染过该颜色。
第一个颜色缓冲区的枚举器常量的名称是GL_COLOR_ATTACHMENT0
,而不是GL_COLOR_ATTACHMENT1
:{p> 3可以将其附加到帧缓冲区:
void OpenglWidget::initializeGL()
{
// [...]
core1->glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0, // <---- GL_COLOR_ATTACHMENT0 instead of GL_COLOR_ATTACHMENT1
GL_TEXTURE_2D,
m_pickingTexture, 0);
// [...]
}
void OpenglWidget::mousePressEvent(QMouseEvent *e)
{
// [...]
core1->glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
core1->glReadBuffer(GL_COLOR_ATTACHMENT0); // <---- GL_COLOR_ATTACHMENT0
// [ ...]
}
请注意,默认情况下,它将呈现到帧缓冲区的第一个颜色缓冲区(GL_COLOR_ATTACHMENT0
)。如果要渲染到第一个以外的其他颜色缓冲区,则必须由glFramebufferTexture2D
显式指定一个颜色缓冲区(列表)。
请参见glDrawBuffers
:
17.4.1选择写入缓冲区
[...]写入所有片段颜色的帧缓冲区对象的缓冲区集由命令控制
void DrawBuffers( sizei n, const enum *bufs ); void NamedFramebufferDrawBuffers( uint framebuffer, sizei n, const enum *bufs );
[...] 对于帧缓冲区对象,在初始状态下,绘制缓冲区用于 片段颜色零为
COLOR_ATTACHMENT0
。对于这两个默认帧缓冲区 和framebuffer对象,除零以外的片段颜色的绘制缓冲区的初始状态为NONE
。