OpenGL使用渲染到纹理实现鼠标拾取对象

一、鼠标拾取原理

在设计软件中,常有鼠标拾取对象的功能。其实现有多种方法,本文介绍使用OpenGL离屏渲染实现鼠标拾取的方法。该方法分成两步:

         第一步:将屏幕像素对应的物体ID写入与帧缓冲区同样大小的另一缓冲区中,可称离屏缓冲区;

         第二步:在鼠标单击时,读取离屏缓冲区对应物体的ID,进行进一步处理即可。

二、渲染到纹理

首先要创建一个帧缓冲对象,并绑定它:

GLuint m_fbo = 0;
glGenFramebuffers(1, &m_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);

接下来我们需要创建一个纹理图像,将它作为一个颜色附件附加到帧缓冲上。纹理的维度设置为窗口的宽度和高度,并且不初始化它的数据。物体的id就写入这个纹理中:

// Create the texture object for the primitive information buffer
GLuint m_pickingTexture = 0;
glGenTextures(1, &m_pickingTexture);
glBindTexture(GL_TEXTURE_2D, m_pickingTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32UI, WindowWidth, WindowHeight, 0, GL_RGB_INTEGER, GL_UNSIGNED_INT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pickingTexture, 0);

绘制物体id的时候还需要进行深度测试,不能后面的物体覆盖前面物体的id,所以还需要添加一个深度附件到缓冲中。

// Create the texture object for the depth buffer
glGenTextures(1, &m_depthTexture);
glBindTexture(GL_TEXTURE_2D, m_depthTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, WindowWidth, WindowHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthTexture, 0);

 最后使用的时候用glBindFramebuffer绑定离屏帧缓冲,渲染管线会渲染到该缓冲中,渲染完需切换到默认帧缓冲。

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo);
.... 离屏渲染中间过程

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);

三、写入物体ID到纹理与读取

在画每一个物体的时候,可以物体的id传入片元所色器的uniform变量中,片元着色器写入颜色即可。

#version 330

uniform uint gObjectIndex;
uniform uint gDrawIndex;

out uvec3 FragColor;

void main()
{
   FragColor = uvec3(gObjectIndex, gDrawIndex, gl_PrimitiveID);
}

读取像素使用OpenGL提供的API:

glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo);

glReadBuffer(GL_COLOR_ATTACHMENT0);

PixelInfo Pixel;
glReadPixels(x, y, 1, 1, GL_RGB_INTEGER, GL_UNSIGNED_INT, &Pixel);

glReadBuffer(GL_NONE);

glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);

具体代码参见:

ogldev/tutorial31_youtube at master · emeiri/ogldev · GitHub

猜你喜欢

转载自blog.csdn.net/loveoobaby/article/details/127992000