当前位置:网站首页>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_BGRAtype: 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_REVdata: 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
边栏推荐
- ASP. Net query implementation
- Display the server hard disk image to the browser through Servlet
- Les mots ont été écrits, la fonction est vraiment puissante!
- Uic564-2 Appendix 4 - flame retardant fire test: flame diffusion
- SQL connection problem after downloading (2)
- Pycharm essential plug-in, change the background (self use, continuous update) | CSDN creation punch in
- Oracle statistics by time
- Come on, brother
- Redis caching tool class, worth owning~
- Resolve the URL of token
猜你喜欢

Navicat connects Oracle

At the age of 35, I made a decision to face unemployment

Laser slam learning (2d/3d, partial practice)

Rectification characteristics of fast recovery diode

Pypharm uses, and the third-party library has errors due to version problems

Flash download setup

One click free translation of more than 300 pages of PDF documents

Solutions to problems in sqlserver deleting data in tables

Get started with mongodb

快速回复二极管整流特性
随机推荐
Kubectl's handy command line tool: Oh my Zsh tips and tricks
Take you hand in hand to build feign with idea
C语言学习
MP4文件格式解析之结合实例分析
Wechat applet development beginner 1
Chisel tutorial - 05 Sequential logic in chisel (including explicit multi clock, explicit synchronous reset and explicit asynchronous reset)
P1055 [noip2008 popularization group] ISBN number
The file format and extension of XLS do not match
Possible SQL for Oracle table lookup information
C - minute number V3
解析token的网址
webflux - webclient Connect reset by peer Error
Binary sort tree [BST] - create, find, delete, output
Where are you going
Restricted linear table
Database interview questions + analysis
DataGuard active / standby cleanup archive settings
Archery installation test
webflux - webclient Connect reset by peer Error
P1067 [noip2009 popularity group] polynomial output (difficult, pit)