欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

OpenGL3.3 3D拾取

程序员文章站 2024-03-25 16:37:16
...

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

相关标签: opengl