OpenGL3.3鼠标拾取物体
OpenGL3.3鼠标拾取物体
本文翻译自:http://www.lighthouse3d.com/tutorials/opengl-selection-tutorial/
在3D场景中拾取或选择特定项目可能对某些应用程序很有用。可以通过单击一个对象来执行选择,这需要一种确定鼠标放置在哪个对象上的方法。
实现此目的的简单解决方案是使用颜色编码,以特定颜色绘制每个可拾取对象。读取鼠标所在的像素以提供颜色,从而可以识别物体。
选择模式下的渲染使用非常简单的着色器,将恒定的颜色应用于像素。颜色是一个统一变量,在绘制每个对象之前应将其设置为唯一值。
顶点着色器可以如下所示:
#version 330uniform mat4 m_pvm;in vec4 position;void main()
{gl_Position = m_pvm * position ;
}
片段着色器很简单:
#version 330uniform int code;out vec4 outputF;void main()
{outputF = vec4(code/255.0, 0, 0, 0);
}
重要的是,我们收到的code
是整数而不是浮点数。在RGB模式下,每个分量只有256个可能的值,因此当您使用浮点数设置颜色时,OpenGL将选择最接近的可能颜色,这可能与您提供的值不完全相同。
请注意,我们将除以255.0,而不是除以255。使用后一种方法将是整数除法,结果也将是整数(0或1)。
如果有超过255个对象可供选择,则 uniform
的code
可以是ivec4
类型。
假设我们的场景有4个国际象棋棋子,如下图所示:
在此示例中,我们有四个可点击的对象,我们将为其分配从1到4的代码。选择渲染例程的背景可以设置为黑色,因此零表示没有任何选择。使用选择程序时,我们将获得如下图像(对比度大大提高):
该图像将永远不会呈现给用户,因为选择渲染不会交换缓冲区。
以下例程接收鼠标窗口坐标,并执行必要的步骤来确定选择了哪个对象。首先调用选择渲染程序,然后再进行选择。然后,它从后台缓冲区读取像素并检查返回的颜色。
要读取像素,我们将使用函数glReadPixels
。
void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *data);
参数:
x,y
:要读取的矩形块的第一个像素的坐标width,height
:块的大小。format
:像素数据的格式:GL_STENCIL_INDEX, GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL, GL_RED, GL_GREEN, GL_BLUE, GL_RGB, GL_BGR, GL_RGBA, GL_BGRA
type
:像素分量的数据类型:GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT, GL_UNSIGNED_INT, GL_INT, GL_HALF_FLOAT, GL_FLOAT, GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_24_8, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_UNSIGNED_INT_5_9_9_9_REV, or GL_FLOAT_32_UNSIGNED_INT_24_8_REV
data
:返回的像素数据。
void processSelection(int xx, int yy) {unsigned char res[4];GLint viewport[4]; renderSelection();glGetIntegerv(GL_VIEWPORT, viewport);glReadPixels(xx, viewport[3] - yy, 1,1,GL_RGBA, GL_UNSIGNED_BYTE, &res);switch(res[0]) {case 0: printf("Nothing Picked \n"); break;case 1: printf("Picked yellow\n"); break;case 2: printf("Picked red\n"); break;case 3: printf("Picked green\n"); break;case 4: printf("Picked blue\n"); break;default:printf("Res: %d\n", res[0]);}
}
为了获得正确的像素,我们必须将鼠标窗口坐标(左上角为原点)转换为帧缓冲区坐标(左下角的原点)。这要求我们知道视口的高度。函数glGetIntegerv
可用于此目的,将GL_VIEWPORT
作为第一个参数。返回变量viewport
是一个包含4个项目的数组,该数组提供x和y视口窗口坐标(起点:左上角),然后是视口的宽度和高度。然后,可以读取像素,并正确解码检索到的颜色。
选择渲染程序必须遵循与常规程序有关几何变换的相同步骤,以使对象位于屏幕上的同一位置。通常,选择渲染程序是常规渲染程序的简化版本,其中仅绘制对象的子集,并且未设置任何图形效果,例如照明。
对象子集包括所有可点击的对象以及相关的遮挡物。这个想法是,如果某些棋子在用户看不见的空间内,则它们不应出现在颜色编码的图像中。这可以通过用与背景相同的颜色绘制遮挡物(例如房间的墙壁)来轻松实现。
void renderSelection(void) {glClearColor(0.0f, 0.0f, 0.0f, 0.0f);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//set matrices to identity...// set camera as in the regular rendering function....// use the selection shaderglUseProgram(selectionProgramID);//perform the geometric transformations to place the first pawn...// set the uniform with the appropriate color codeglProgramUniform1i(selectionProgramID, codeVarLocation, 1);// draw first pawn...// repeat the above steps for the remaining objects, using different codes//don't swap buffers//glutSwapBuffers();// restore clear color if neededglClearColor(1.0f, 1.0f, 1.0f, 1.0f);
}
下载:
- 带有完整源代码和着色器的VS2010项目(ZIP)
该项目需要glew和freeglut 或 glut。
欢迎关注我的公众号 江达小记
OpenGL3.3鼠标拾取物体相关推荐
- Unity3D 入门小技巧——鼠标拾取并移动物体
一.鼠标拾取物体的原理 在Unity3D当中,想要在观察面(Aspect)中拾取物体(有碰撞属性)的方法一般如下: 1.声明一个观察的摄像机.一个从摄像机原点出发的射线Ray以及一个用于检测碰撞的Ra ...
- Unity3D 类似COC的鼠标拾取游戏物体并在限定区域摆放
using UnityEngine; using System.Collections;public class MoveObject : MonoBehaviour {/// <summary ...
- Three.js - 鼠标拾取(射线追踪法)(十九)
射线追踪法 射线追踪法是最常见的方法,因为three.js提供了Raycaster对象来实现它. 原理:从鼠标处发射一条射线,穿透场景的视椎体,通过计算,找出与射线相交的对象. Raycaster 属 ...
- DirectX11进阶5_硬件实例化与视锥体裁剪及鼠标拾取交互
一.硬件实例化(Hardware Instancing) 硬件实例化指的是在场景中绘制同一个物体多次,但是是以不同的位置.旋转.缩放.材质以及纹理来绘制(比如一棵树可能会被多次使用以构建出一片森林). ...
- 鼠标拾取(光线拾取)
作者:桑榆 QQ:934440653 有问题,评论留言,或qq联系 案例效果 鼠标拾取 主要代码 1.创建矩形 (1)6-8行限制随机产生的矩形的长.宽.纵深不超过20: (2)14-16行限制随机产 ...
- Unity鼠标拖动物体、按下鼠标左键旋转观察物体、鼠标滚轮缩放视野
如题目所示,本文实现这三个效果.所有代码都在pc端成功运行,移植到手机端改变相应的判断条件即可,核心算法没有问题. 一. 鼠标拖拽移动物体 效果演示 源代码 public class mousedra ...
- 鼠标实现物体拖动带拖尾的效果
今天,小编为大家分享一下,用鼠标拖动物体,还带一个小尾巴效果哈![+V:Anime__King] 1.新建一个unity项目,新建一个测试场景.一个MoveTo.cs类附加在GameObject(命名 ...
- 3d 数学(叉乘、四元素、四元素旋转、四元素和四元素相乘、鼠标控制物体旋转、发射子弹、环形发射子弹、子弹缓冲池)
目录 1.叉乘 2.四元素 3.四元素旋转 4.四元素和四元素相乘 5.鼠标控制物体旋转 6.发射子弹 7.环形发射子弹 8.子弹缓冲池 1.叉乘 两个向量叉乘,得到一个新的向量,新向量跟原始两个向量 ...
- ue4 拾取物体注意问题
拾取物体步骤: 1.创建物体 蓝图类,加上sphere collision和skeletalmesh(骨架网格体)(如果是静态网格体用staticMesh),细节面板skeletalmesh选择附加物 ...
最新文章
- 基于pytorch的模型压缩和模型剪枝Model Prune示例
- 什么是清华大学的“三好”学生?
- Vue2.0 入门 安装Vue-cli
- 利用Maya进行论文中网格动画数据的渲染
- Linux-通过XShell使用sz命令提示找不到
- SAP Spartacus Spinner控件显示原理
- redis将散裂中某个值自增_0基础掌握Django框架(49)Redis
- Oracle实现数据不存在则插入,数据存在则更新(insert or update)
- C#不同操作系统下,界面大小不一的原因
- Python 实现最简单的元胞自动机
- 乐高叉车wedo教案_乐高 WEDO自带12个活动教学参考书.pdf
- java while循环 计算机,Java while和do ... while循环 - 芒果文档
- 合唱队形(最大上升子序列)
- vue 高德地图点击获取坐标与地理位置
- hortonworks_具有在IBM POWER8上运行的Hortonworks Data Platform(HDP)的SAS软件
- cv2 在图片上画线
- Youtube 预装到系统后运行报错
- 调试WebService的一个很好的工具
- DIV和Table的水平、垂直居中
- 89.网络安全渗透测试—[常规漏洞挖掘与利用篇5]—[文件包含漏洞详解实战示例]