OpenGL3.3 3D拾取

3D拾取
教程模仿网站:http://ogldev.atspace.co.uk/www/tutorial29/tutorial29.html
实现过程:
1.创建帧缓冲(包含颜色缓冲和深度模板缓冲)
2.在帧缓冲绑定为当前缓冲
3.绘制一次需要被鼠标拾取的对象
4.恢复默认缓冲
5.再真正绘制所有场景

核心思想:
让每一个像素都有自己独特的索引,当鼠标点击时获取鼠标点击处的像素和像素索引(一般glReadPixels函数是获取鼠标点击处的指定的数据,比如说3d拾取我们就选择获取rgb颜色数据 但是我们并不是真正的获取颜色数据,而是在颜色纹理中填充的是三元索引,所以我们从颜色纹理中获取的是三元索引),就可知道点击的像素属于哪个对象 就可以知道点击到了哪个对象
原理:
通过创建帧缓冲 将三元索引代替每个顶点像素的颜色rgb存储进入帧缓冲的颜色缓冲,从而使像素位置和索引相对应。这样在点击的时候就可以知道点击到了哪个索引

拾取着色器的作用:把模型的各个顶点放入帧缓冲的深度纹理,把模型的对象索引,绘制索引,原始索引放入帧缓冲的颜色纹理
步骤:
(拾取阶段)就是把相应数据利用拾取着色器传进帧缓冲
开启拾取帧缓冲
开启拾取着色器
把模型相应数据传进拾取着色器
绘制一遍模型(把相应的顶点和索引绘制进帧缓冲)
恢复默认缓冲
(绘制阶段)就是绘制出模型的红色边框
如果左键点击了:获取鼠标点击处的像素的三元索引
如果该像素不是背景:通过得到的该像素的绘制索引和原始索引绘制出相应片段

(真正绘制阶段)
正常绘制

对象索引:每绘制一个模型就会+1 当绘制一个新模型的时候对象索引就会+1 在每次绘制之前会被传去拾取着色器
绘制索引:绘制一个模型的时候每绘制一个网格就会+1 (但是上面说对象索引和绘制索引是一样的 不知道为什么)在模型绘制当中 每变一个网格的时候就会被传如拾取着色器
原始索引:在片段着色器里面 应该是每个片段都会+1 在着色器内部的内置索引 每次调用着色器都会+1

函数:
glReadBuffer(GL_COLOR_ATTACHMENT0);
glReadBuffer()函数指定要读取的颜色缓冲区。 为像素选择颜色缓冲源
原因是FBO可以包含多个颜色缓冲区(FS可以同时将其渲染到其中),
但我们一次只能读取一个缓冲区。
参数可接受:
指定颜色缓冲区。可接受的值为GL_FRONT_LEFT,GL_FRONT_RIGHT,GL_BACK_LEFT,GL_BACK_RIGHT,GL_FRONT,GL_BACK,GL_LEFT,GL_RIGHT和GL_AUX i,其中i在0和GL_AUX_BUFFERS -1之间。
glDrawBuffer(GL_COLOR_ATTACHMENT0);就是指定要写入的颜色缓冲区,这个缓冲区的设定在颜色纹理附加给帧缓冲的时候可以设置( glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pickingTexture, 0);)

glReadPixels(x, y, 1, 1, GL_RGB, GL_FLOAT, &Pixel);

void glReadPixels
(GLint x,    指定从帧缓冲区读取的第一个像素!(也就是最上面那个像素)的窗口坐标。 此位置是矩形像素块的左下角。(一般传入的是鼠标在屏幕上点击的坐标)

GLint y,

GLsizei width,  指定像素矩形的尺寸。 一个宽度和高度对应于单个像素  

GLsizei height,

GLenum format,   指定像素数据的格式。 接受以下符号值:GL_ALPHA,GL_RGB和GL_RGBA
	比如GL_RGB就会依次读取像素的红、绿、蓝三种数据,
	GL_RGBA则会依次读取像素的红、绿、蓝、alpha四种数据,
	GL_RED则只读取像素的红色数据(类似的还有GL_GREEN,GL_BLUE,以及GL_ALPHA)
	还可以读取其它内容,例如深度缓冲区的深度数据等

GLenum type,   表示读取的内容保存到内存时所使用的格式,例如:GL_UNSIGNED_BYTE会把各种数据保存为GLubyte,GL_FLOAT会把各种数据保存为GLfloat等。

GLvoid * data);   表示一个指针,像素数据被读取后,将被保存到这个指针所表示的地址  需要保证该地址有足够的可以使用的空间,以容纳读取的像素数据。例如一幅大小为256x256的图象,如果读取其RGB数据,且每一数据被保存为GLubyte,总大小就是:256x256x3 = 196608字节,即192千字节。如果是读取RGBA数据,则总大小就是256x256x4 = 262144字节,即256千字节

lReadPixels实际上是从缓冲区中读取数据,如果使用了双缓冲区,则默认是从正在显示的缓冲(即前缓冲)中读取,而绘制工作是默认绘制到后缓冲区的。因此,如果需要读取已经绘制好的像素,往往需要先交换前后缓冲。

内置变量gl_PrimitiveID:
统自动维护的原语的运行索引。gl_PrimitiveID只能在GS和PS中使用
系统在绘制开始时将gl_PrimitiveID重置为零
3D拾取demo
3D拾取修改

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值