当前位置:网站首页>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
边栏推荐
猜你喜欢

Connect diodes in series to improve voltage withstand

MySQL Architecture

Ora-02437 failed to verify the primary key violation

一份假Offer如何盗走了「Axie infinity」5.4亿美元?

关于CH32库函数与STM32库函数的区别

MongoDB快速入门

archery安装测试

Take you hand in hand to build Eureka server with idea

Basic learning of SQL Server -- creating databases and tables with the mouse

C - linear table
随机推荐
Gorm Association summary
Wechat applet development beginner 1
Solutions to problems in sqlserver deleting data in tables
Chisel tutorial - 04 Control flow in chisel
Flash download setup
FFA and ICGA angiography
C - linear table
HDU - 1260 tickets (linear DP)
Data Lake (XV): spark and iceberg integrate write operations
Dependency injection
企业应用需求导向开发之人力部门,员工考勤记录和实发工资业务程序案例
Is it safe for tongdaxin to buy funds?
@Configuration注解的详细介绍
An example analysis of MP4 file format parsing
【实验分享】通过Console口登录到Cisco设备
webflux - webclient Connect reset by peer Error
[path planning] use the vertical distance limit method and Bessel to optimize the path of a star
ASP. Net query implementation
Alibaba cloud MySQL cannot connect
用语雀写文章了,功能真心强大!