当前位置:网站首页>Opengl3.3 mouse picking up objects
Opengl3.3 mouse picking up objects
2022-07-07 23:53:00 【Raring_ Ringtail】
OpenGL3.3 Pick up objects with the mouse
This article is translated from :http://www.lighthouse3d.com/tutorials/opengl-selection-tutorial/
stay 3D Picking or selecting specific items in a scene may be useful for some applications . You can perform a selection by clicking on an object , This requires a way to determine which object the mouse is placed on .
A simple solution to this is to use color coding , Draw each pickable object in a specific color . Read the pixel where the mouse is located to provide color , So that objects can be recognized .
Rendering in select mode uses very simple shaders , Apply a constant color to pixels . Color is a unified variable , Set each object to a unique value before drawing it .
Vertex shaders can be as follows :
#version 330
uniform mat4 m_pvm;
in vec4 position;
void main()
{
gl_Position = m_pvm * position ;
}
Fragment shaders are simple :
#version 330
uniform int code;
out vec4 outputF;
void main()
{
outputF = vec4(code/255.0, 0, 0, 0);
}
It is important to , We got it code
It's an integer, not a floating-point number . stay RGB In mode , Each component has only 256 Possible values , So when you use floating point numbers to set colors ,OpenGL The closest possible color will be selected , This may not be exactly the same as the value you provided .
Please note that , We will divide by 255.0, Instead of dividing by 255. Using the latter method will be integer division , The result will also be an integer (0 or 1).
If there is more than 255 Objects to choose from , be uniform
Of code
It can be ivec4
type .
Suppose our scenario has 4 A chess piece , As shown in the figure below :
In this example , We have four clickable objects , We will assign it from 1 To 4 Code for . The background of the selected rendering routine can be set to black , So zero means there is no choice . When using the selector , We will get the following image ( The contrast is greatly improved ):
The image will never be presented to the user , Because choosing to render does not swap buffers .
The following routine receives mouse window coordinates , And perform the necessary steps to determine which object is selected . First call the select renderer , Then make a choice . then , It reads pixels from the background buffer and checks the returned color .
To read pixels , We're going to use functions glReadPixels
.void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *data);
Parameters :
x,y
: Coordinates of the first pixel of the rectangular block to be readwidth,height
: The size of the block .format
: Format of pixel data :GL_STENCIL_INDEX, GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL, GL_RED, GL_GREEN, GL_BLUE, GL_RGB, GL_BGR, GL_RGBA, GL_BGRA
type
: Data type of pixel component :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
: Returned pixel 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]);
}
}
To get the right pixels , We must set the mouse window coordinates ( The upper left corner is the origin ) Convert to frame buffer coordinates ( The origin of the lower left corner ). This requires us to know the height of the viewport . function glGetIntegerv
Can be used for this purpose , take GL_VIEWPORT
As the first parameter . Return variable viewport
Is a containing 4 An array of items , This array provides x and y Viewport window coordinates ( The starting point : top left corner ), Then the width and height of the viewport . then , You can read pixels , And decode the retrieved color correctly .
The selection of the renderer must follow the same steps as the regular procedure for geometric transformation , So that the object is in the same position on the screen . Usually , The selected renderer is a simplified version of the regular renderer , Where only a subset of the objects are drawn , And no graphic effect is set , For example, lighting .
The object subset includes all clickable objects and related occlusions . The idea is , If some pieces are in a space invisible to the user , Then they should not appear in color coded images . This can be done by painting the occlusion with the same color as the background ( For example, the wall of the room ) To make it easy .
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 shader
glUseProgram(selectionProgramID);
//perform the geometric transformations to place the first pawn
...
// set the uniform with the appropriate color code
glProgramUniform1i(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 needed
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
}
download :
- With complete source code and shaders VS2010 project (ZIP)
The project needs glew and freeglut or glut.
Welcome to my official account. Notes on Jiangda
边栏推荐
- 一键免费翻译300多页的pdf文档
- BSS 7230 flame retardant performance test of aviation interior materials
- FFA and ICGA angiography
- Chisel tutorial - 00 Ex.scala metals plug-in (vs Code), SBT and coursier exchange endogenous
- HB 5469民用飞机机舱内部非金属材料燃烧试验方法
- postgres timestamp转人眼时间字符串或者毫秒值
- BSS 7230 航空内饰材料阻燃性能测试
- 用语雀写文章了,功能真心强大!
- 【路径规划】使用垂距限值法与贝塞尔优化A星路径
- At the age of 35, I made a decision to face unemployment
猜你喜欢
如何衡量产品是否“刚需、高频、痛点”
【实验分享】通过Console口登录到Cisco设备
postgis学习
Laser slam learning (2d/3d, partial practice)
Benchmarking Detection Transfer Learning with Vision Transformers(2021-11)
Class C design questions
PostGIS learning
35岁那年,我做了一个面临失业的决定
About the difference between ch32 library function and STM32 library function
【路径规划】使用垂距限值法与贝塞尔优化A星路径
随机推荐
Take you hand in hand to build Eureka client with idea
About the difference between ch32 library function and STM32 library function
Is it safe for tongdaxin to buy funds?
Chisel tutorial - 04 Control flow in chisel
Pypharm uses, and the third-party library has errors due to version problems
Pycharm basic settings latest version 2022
Chisel tutorial - 00 Ex.scala metals plug-in (vs Code), SBT and coursier exchange endogenous
One click installation with fishros in blue bridge ROS
Install sqlserver2019
webflux - webclient Connect reset by peer Error
ASP. Net query implementation
Navicat connects Oracle
FFA与ICGA造影
Wechat applet development beginner 1
【实验分享】通过Console口登录到Cisco设备
HDU - 1260 tickets (linear DP)
通达信买基金安全吗?
一键免费翻译300多页的pdf文档
Pycharm essential plug-in, change the background (self use, continuous update) | CSDN creation punch in
BSS 7230 flame retardant performance test of aviation interior materials