使用现代OpenGL进行物体的点选,OpenGL4.5和C++示例

已经有了很多示例代码,为什么要写

现在百度找到的大多数已有的OpenGL点选代码,使用的是老版本OpenGL的拾取功能,老版本的OpenGL是通过固定管线渲染,有渲染模式和选择模式,但是如果我们使用的现代OpenGL(好像OpenGL3.0以上),则不会有选择模式,需要我们手动去写着色器进行选择。

选择方法

这里使用的方法比较简单,创建一个帧缓冲,对这个帧缓冲添加颜色纹理和深度纹理,根据鼠标点击位置的深度值和颜色纹理判断选择了哪个绘制的物体,这里的颜色纹理并非是物体的本身颜色,我们为每个物体增加一个ID,将ID的值赋值给颜色纹理,来达到点选的目的。

示例代码

我这里使用的是OpenGL4.5版本。
顶点着色器:

#version 450
layout(location = 0) in vec3 aPosition;
uniform int ID = 0;
out VS_OUT_POINTS
{
    vec4 vs_color;
}vs_out;

void main()
{
 	gl_Position = aPosition;
 	vs_out.vs_color = vec4(ID,ID,ID,ID);
 }

片段着色器:

#version 450

out vec4 FragColor;

in VS_OUT_POINTS
{
    vec4 vs_color;
}vs_in;

void main() 
{   
	FragColor =vs_in.vs_color;
}

在绘制时,需要将物体的ID传输给着色器:

glUniform1i(glGetUniformLocation(m_shaderID, "ID"), Object->getID());

帧缓冲的创建:

//创建帧缓冲
glGenFramebuffers(1, &m_framebufferPick);
glBindFramebuffer(GL_FRAMEBUFFER, m_framebufferPick);
// 创建纹理附件
glGenTextures(1, &m_textureColorBufferPick);
glBindTexture(GL_TEXTURE_2D, m_textureColorBufferPick);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, m_glViewport.width(), m_glViewport.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_textureColorBufferPick, 0);

// 创建深度纹理
glGenTextures(1, &m_textureDepthBufferPick);
glBindTexture(GL_TEXTURE_2D, m_textureDepthBufferPick);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, m_glViewport.width(), m_glViewport.height(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_textureDepthBufferPick, 0);
// 检查当前帧缓冲是否完整
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
	std::cout << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!"<<std::endl;

//切换到Qt的默认帧缓冲
glBindFramebuffer(GL_FRAMEBUFFER,0);	

点选代码:

	int select_index = -1;			
	glBindFramebuffer(GL_FRAMEBUFFER, m_framebufferPick);
	glViewport(0, 0, m_context.glWidth, m_context.glHeight);
	glDisable(GL_BLEND);
	glEnable(GL_DEPTH_TEST); // enable depth testing (is disabled for rendering screen-space quad)
	glClearColor(m_context.backgroundColor.r, m_context.backgroundColor.g, m_context.backgroundColor.b, m_context.backgroundColor.a);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glBindTexture(GL_TEXTURE_2D, m_textureColorBufferPick);
	GLfloat _depth = -1.0f;
	//picking
	for (int ii = 0; ii < Objects.size(); ++ii)
	{				
		glClearColor(m_context.backgroundColor.r, m_context.backgroundColor.g, m_context.backgroundColor.b, m_context.backgroundColor.a);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		drawObject(Objects[ii], true);
		GLfloat depth_;
		glReadPixels(x, m_glViewport.height() - 1 - y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth_);
		//防止因为渲染顺序导致深度测试无效
		if (depth_!=1.0f)
		{
			if (_depth<0.0f)
			{
				_depth = depth_;
			}
			if (depth_<=_depth)
			{
				GLfloat pixelValue[4];
				glReadPixels(x, m_glViewport.height() - 1 - y, 1, 1, GL_RGBA, GL_FLOAT, pixelValue);
				if (pixelValue[0] != 0)
				{
					//最终得到的ObjectID
					select_index = pixelValue[0];
				}
			}
		}
	}			
	glBindTexture(GL_TEXTURE_2D, 0);
	glBindFramebuffer(GL_FRAMEBUFFER,0);
  • 10
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

福尔磨叽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值