当前位置:网站首页>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
边栏推荐
- How did a fake offer steal $540million from "axie infinity"?
- Traduction gratuite en un clic de plus de 300 pages de documents PDF
- Archery installation test
- gorm 关联关系小结
- Binary sort tree [BST] - create, find, delete, output
- 机器人(自动化)等专业课程创新的结果
- 35岁那年,我做了一个面临失业的决定
- FFA and ICGA angiography
- Svn relocation
- P1055 [noip2008 popularization group] ISBN number
猜你喜欢
用語雀寫文章了,功能真心强大!
如何衡量产品是否“刚需、高频、痛点”
Pycharm basic settings latest version 2022
Install sqlserver2019
【实验分享】通过Console口登录到Cisco设备
How did a fake offer steal $540million from "axie infinity"?
FFA and ICGA angiography
二叉排序树【BST】——创建、查找、删除、输出
Ping error: unknown name or service
Benchmarking Detection Transfer Learning with Vision Transformers(2021-11)
随机推荐
解析token的网址
May day d-light
【汇总】看过的一些Panel与视频
C language greedy snake
One click free translation of more than 300 pages of PDF documents
About the difference between ch32 library function and STM32 library function
An example analysis of MP4 file format parsing
[leetcode] 20. Valid brackets
Jisuan Ke - t3104
postgres timestamp转人眼时间字符串或者毫秒值
Laser slam learning (2d/3d, partial practice)
企业应用需求导向开发之人力部门,员工考勤记录和实发工资业务程序案例
C语言学习
如何衡量产品是否“刚需、高频、痛点”
保证接口数据安全的10种方案
Postgres timestamp to human eye time string or millisecond value
How did a fake offer steal $540million from "axie infinity"?
关于CH32库函数与STM32库函数的区别
mysql8.0 ubuntu20.4
【LeetCode】20、有效的括号