当前位置:网站首页>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
边栏推荐
- Oracle statistics by time
- Gorm Association summary
- Ora-02437 failed to verify the primary key violation
- Idea automatically generates serialVersionUID
- 如何衡量产品是否“刚需、高频、痛点”
- Pigsty:开箱即用的数据库发行版
- Arbre binaire équilibré [Arbre AVL] - Insérer et supprimer
- 【leetcode】day1
- Rock-paper-scissors
- Data analysis series 3 σ Rule / eliminate outliers according to laida criterion
猜你喜欢
Balanced binary tree [AVL tree] - insert, delete
Svn relocation
95.(cesium篇)cesium动态单体化-3D建筑物(楼栋)
Binary sort tree [BST] - create, find, delete, output
Kubectl's handy command line tool: Oh my Zsh tips and tricks
MongoDB快速入门
Archery installation test
Arbre binaire équilibré [Arbre AVL] - Insérer et supprimer
Rectification characteristics of fast recovery diode
Flash download setup
随机推荐
Basic learning of SQL Server -- creating databases and tables with the mouse
【实验分享】通过Console口登录到Cisco设备
[leetcode] 20. Valid brackets
gorm 关联关系小结
Pycharm essential plug-in, change the background (self use, continuous update) | CSDN creation punch in
P1308 [noip2011 popularity group] count the number of words
c—线性表
Dataguard 主备清理归档设置
Oracle string sorting
BSS 7230 航空内饰材料阻燃性能测试
Installing gradle
Basic learning of SQL Server -- creating databases and tables with code
codeforces每日5题(均1500)-第八天
C - minute number V3
Uic564-2 Appendix 4 - flame retardant fire test: flame diffusion
光流传感器初步测试:GL9306
C language learning
Data analysis series 3 σ Rule / eliminate outliers according to laida criterion
Chisel tutorial - 04 Control flow in chisel
Navicat connects Oracle