Форум программистов, компьютерный форум, киберфорум
OpenGL
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.86/29: Рейтинг темы: голосов - 29, средняя оценка - 4.86
0 / 0 / 0
Регистрация: 07.11.2014
Сообщений: 18

Поиск местонахождения объектов в opengl. Qt

07.11.2014, 18:55. Показов 7039. Ответов 58
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток!

Делаю программу в Кьюте, которая строит множество объектов на экране с помощью OpenGL. Эти объекты я одновременно могу масштабировать, изменяя размеры окна с помощью glOrtho(), поворачивать с помощью функции glRotate*().

Проблема заключается в том, что мне нужно при наведении курсора выяснить, на какой объект он был наведён. Не могу понять, как это реализовать. Нужно, чтобы определялась хотя бы координата этого объекта, по которой он строился. Дальше, естественно, легко определить будет, что за объект.
То есть нужно, чтобы я навёл курсор, и волшебство мне выдало координаты объекта в x, y, z. Есть у кого какие соображения?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
07.11.2014, 18:55
Ответы с готовыми решениями:

Поиск заданного символа и определение его местонахождения
Программа с цепочечными командами. Сформировать массив данных и найти заданный символ, определив его местонахождение.

Вращение объектов OpenGL
Недавно начала изучать OpenGl.Создала объекты(2 треугольника и прямоугольник) и наложила на объекты вращение,но почему-то вращается только...

Удаление объектов в OpenGL
Доброго дня! Подскажите как можно реализовть удаление объектов в opengl? Скажем у меня есть черный фон на нем нарисована зеленая решетка, а...

58
9036 / 2937 / 493
Регистрация: 05.10.2013
Сообщений: 7,960
Записей в блоге: 216
11.04.2024, 12:04
Студворк — интернет-сервис помощи студентам
Удивительно то, что touchEvent() не нужен для Android'а, если не нужно отслеживать несколько касаний. В примере выше достаточно одного метода mousePressEvent(), который и так есть для Desktop и WASM, а touchEvent() нужно убрать:

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void OpenGLWindow::mousePressEvent(QMouseEvent *event)
{
    m_isMouseClicked = true;
    m_mousePosX = event->pos().x() * devicePixelRatio();
    m_mousePosY = (height() - event->pos().y() - 1) * devicePixelRatio();
    update();
}
 
// void OpenGLWindow::touchEvent(QTouchEvent *event)
// {
//     switch (event->type())
//     {
//         case QEvent::TouchBegin:
//         {
//             m_isMouseClicked = true;
//             m_mousePosX = event->points()[0].position().x() * devicePixelRatio();
//             m_mousePosY = (height() - event->points()[0].position().y() - 1) * devicePixelRatio();
//             event->accept();
//             update();
//             break;
//         }
//     }
// }
0
9036 / 2937 / 493
Регистрация: 05.10.2013
Сообщений: 7,960
Записей в блоге: 216
11.04.2024, 13:26
Написал очень короткий пример, где выводится простейший треугольник (без model/view/projection матриц) с выводом цвета полученным с помощью glReadPixels. Протестировал пример на реальном смартфоне и на эмуляторе. Записал gif-анимацию с эмулятора. Здесь движно, что когда происходит касание с треугольников, то выводится красный цвет в консоль (1, 0, 0), а если по фону, то выводится серый цвет (0.2, 0.2, 0.2). Важно использовать QWindow::devicePixelRatio(). Это отношение размера физического пикселя к "независимому" размеру пикселя устройства. В документации написано, что:

Common values are 1.0 on normal displays and 2.0 on Apple "retina" displays
Обычно значение 1.0, как на Windows (скорее всего на Linux тоже 1.0), а на Apple на "retina" экранах (не знаю, что это такое), там 2.0. На Android точно 2.0, я проверял. А если учитывать devicePixelRatio() то координата клика будет там где надо.

Важно помнить, что glReadPixels считает, что начало координат в нижнем левом углу, а mousePressEvent - в верхнем левом углу, поэтому по Y координата по Y переворачивается:

C++ (Qt)
1
2
3
4
5
6
7
    void mousePressEvent(QMouseEvent *event) override
    {
        m_mouseX = event->pos().x() * devicePixelRatio();
        m_mouseY = (height() - event->pos().y() - 1) * devicePixelRatio();
        m_mouseClicked = true;
        update();
    }
Не забыть вызвать update(), чтобы вызвать перерисовку, где уже анализируется флаг m_mouseClicked и используются пересчитанные m_mouseX и m_mouseY. В данном примере не GameLoop, поэтому надо вызвать update(), а можно его вызывать и когда есть GameLoop - ничего страшного. Мне нравится, что в Qt поумолчанию нет бесконечных циклов, как в GLFW, SDL, SFML, которые тратят ресурсы процессора впустую и следовательно заряд телефона. А ещё то что Qt для Android и WebAssembly собирает из коробки. Я собирал SFML3 для Android - это долго. Собрал, запустил страндартный пример (без OpenGL), но у SFML нет нормального API для Android, там напрямую вызываются функции Java. А вот с OpenGL не запускается на Android ни SFML3 ни SDL3. На SDL3 работает стандартный пример на WASM, без OpenGL, на OpenGL ни на WASM ни на Android не работает. Я создавал issues, но морчок: Android issue и WASM issue. На WASM на SFML3 пока не планируется. Писал разработчикам SFML в Discord, что мол того SDL3 поддерживает WebAssembly (хоть и без OpenGL), а у вас когда будет, а они говорят, что SDL спонсирует команда Valve, так как используется его в своём игровом движке, а у разработчиков SFML нет таких спонсоров, поэтому WASM будет далеко не скоро. Но это ладно, я отвлёкся. В общем, Qt лучший, по крейней мере в C++ мире, для использования OpenGL на Android и WebAssembly.



Исходники в одном файле:

main.cpp

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <QtGui/QMouseEvent>
#include <QtGui/QOpenGLFunctions>
#include <QtOpenGL/QOpenGLBuffer>
#include <QtOpenGL/QOpenGLShaderProgram>
#include <QtOpenGL/QOpenGLWindow>
#include <QtWidgets/QApplication>
 
class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions
{
public:
    OpenGLWindow()
    {
        setTitle("OpenGL ES 2.0, Qt6, C++");
        resize(380, 380);
    }
 
private:
    void initializeGL() override
    {
        initializeOpenGLFunctions();
        glClearColor(0.2f, 0.2f, 0.2f, 1.f);
        qDebug() << "Device pixel ratio:" << devicePixelRatio();
 
        QString vertexShaderSource =
            "attribute vec2 aPosition;\n"
            "void main()\n"
            "{\n"
            "    gl_Position = vec4(aPosition, 0.0, 1.0);\n"
            "}\n";
 
        QString fragmentShaderSource =
            "#ifdef GL_ES\n"
            "precision mediump float;\n"
            "#endif\n"
            "void main()\n"
            "{\n"
            "    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
            "}\n";
 
        m_program.create();
        m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex,
                                          vertexShaderSource);
        m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment,
                                          fragmentShaderSource);
        m_program.link();
        m_program.bind();
 
        float vertPositions[] = {
            -0.5f, -0.5f,
            0.5f, -0.5f,
            0.f, 0.5f
        };
        m_vertPosBuffer.create();
        m_vertPosBuffer.bind();
        m_vertPosBuffer.allocate(vertPositions, sizeof(vertPositions));
 
        m_program.setAttributeBuffer("aPosition", GL_FLOAT, 0, 2);
        m_program.enableAttributeArray("aPosition");
    }
 
    void paintGL() override
    {
        glClear(GL_COLOR_BUFFER_BIT);
        glDrawArrays(GL_TRIANGLES, 0, 3);
 
        if (m_mouseClicked)
        {
            // Read the pixel
            GLubyte pixel[4];
            glReadPixels(m_mouseX, m_mouseY, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
            // qDebug() << glGetError() << "\n";
            qDebug() << pixel[0] / 255.f << pixel[1] / 255.f << pixel[2] / 255.f;
            m_mouseClicked = false;
        }
    }
 
    void mousePressEvent(QMouseEvent *event) override
    {
        m_mouseX = event->pos().x() * devicePixelRatio();
        m_mouseY = (height() - event->pos().y() - 1) * devicePixelRatio();
        m_mouseClicked = true;
        update();
    }
 
private:
    int m_mouseX;
    int m_mouseY;
    bool m_mouseClicked = false;
    QOpenGLBuffer m_vertPosBuffer;
    QOpenGLShaderProgram m_program;
};
 
int main(int argc, char *argv[])
{
    QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
    QApplication app(argc, argv);
    OpenGLWindow w;
    w.show();
    return app.exec();
}
pick-a-simple-triangle-opengles2-qt6-cpp

Code
1
2
3
4
5
6
7
8
QT += core gui opengl widgets
 
win32: LIBS += -lopengl32
 
CONFIG += c++17
 
SOURCES += \
    main.cpp
Миниатюры
Вложения
Тип файла: zip pick-a-simple-triangle-opengles2-qt6-cpp.zip (37.7 Кб, 0 просмотров)
0
1962 / 818 / 114
Регистрация: 01.10.2012
Сообщений: 4,756
Записей в блоге: 2
11.04.2024, 14:48
В общем случае команды рисования (glDrawArrays и др) не гарантируют "готовности" пикселей, нужно юзать glFinish/glFlush

Если "вот так все просто" (glReadPixels) - это должно насторожить. Покрутите в уме разные варианты выборки. Напр если примитивов много - нужно дать возможность выбрать их "рамкой" (которую еще надо подсвечивать). Конечно "это уже другая задача", но если Вы заявляете "я умею выбирать.." - ее тоже придется делать. В общем, с упоением рисовать красный треугольник - дело хорошее, но..
0
9036 / 2937 / 493
Регистрация: 05.10.2013
Сообщений: 7,960
Записей в блоге: 216
24.05.2024, 15:04
Цитата Сообщение от Igor3D Посмотреть сообщение
В общем случае команды рисования (glDrawArrays и др) не гарантируют "готовности" пикселей, нужно юзать glFinish/glFlush
Попробовал вызвать glFinish перед glReadPixels - задержка вывода цвета в консоль 5 секунд на Desktop, а на WebAssembly в браузере выводится сразу без задержки, как и на Android. А вот с glFlush задержки нет.

В коротком примере ниже выводится красный треугольник. По клику выводится цвет пикселя в месте клика. В данным момент значение цвета выводится в консоль с задержкой в 5 секунд для glFinish, а если заменить glFinish на glFlush, то задержки нет. Можете скачать пример и потестить:



pro

Code
1
2
3
4
5
6
QT += core gui openglwidgets
 
CONFIG += c++17
 
SOURCES += \
    main.cpp
main.cpp

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include <QtGui/QMouseEvent>
#include <QtGui/QOpenGLFunctions>
#include <QtOpenGL/QOpenGLBuffer>
#include <QtOpenGL/QOpenGLShaderProgram>
#include <QtOpenGL/QOpenGLWindow>
#include <QtWidgets/QApplication>
 
class OpenGLWindow : public QOpenGLWindow, private QOpenGLFunctions
{
public:
    OpenGLWindow()
    {
        setTitle("OpenGL ES 2.0, Qt6, C++");
        resize(380, 380);
    }
 
private:
    void initializeGL() override
    {
        initializeOpenGLFunctions();
        glClearColor(0.2f, 0.2f, 0.2f, 1.f);
        qDebug() << "Device pixel ratio:" << devicePixelRatio();
 
        QString vertexShaderSource =
            "attribute vec2 aPosition;\n"
            "void main()\n"
            "{\n"
            "    gl_Position = vec4(aPosition, 0.0, 1.0);\n"
            "}\n";
 
        QString fragmentShaderSource =
            "#ifdef GL_ES\n"
            "precision mediump float;\n"
            "#endif\n"
            "void main()\n"
            "{\n"
            "    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
            "}\n";
 
        m_program.create();
        m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Vertex,
                                          vertexShaderSource);
        m_program.addShaderFromSourceCode(QOpenGLShader::ShaderTypeBit::Fragment,
                                          fragmentShaderSource);
        m_program.link();
        m_program.bind();
 
        float vertPositions[] = {
            -0.5f, -0.5f,
            0.5f, -0.5f,
            0.f, 0.5f
        };
        m_vertPosBuffer.create();
        m_vertPosBuffer.bind();
        m_vertPosBuffer.allocate(vertPositions, sizeof(vertPositions));
 
        m_program.setAttributeBuffer("aPosition", GL_FLOAT, 0, 2);
        m_program.enableAttributeArray("aPosition");
    }
 
    void paintGL() override
    {
        glClear(GL_COLOR_BUFFER_BIT);
        glDrawArrays(GL_TRIANGLES, 0, 3);
 
        if (m_mouseClicked)
        {
            // Read the pixel
            GLubyte pixel[4];
            glFinish();
            // glFlush();
            glReadPixels(m_mouseX, m_mouseY, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
            // Print a color
            qDebug() << pixel[0] / 255.f << pixel[1] / 255.f << pixel[2] / 255.f;
            m_mouseClicked = false;
        }
    }
 
    void mousePressEvent(QMouseEvent *event) override
    {
        m_mouseX = event->pos().x() * devicePixelRatio();
        m_mouseY = (height() - event->pos().y() - 1) * devicePixelRatio();
        m_mouseClicked = true;
        update();
    }
 
private:
    int m_mouseX;
    int m_mouseY;
    bool m_mouseClicked = false;
    QOpenGLBuffer m_vertPosBuffer;
    QOpenGLShaderProgram m_program;
};
 
int main(int argc, char *argv[])
{
    QApplication::setAttribute(Qt::ApplicationAttribute::AA_UseDesktopOpenGL);
    QApplication app(argc, argv);
    OpenGLWindow w;
    w.show();
    return app.exec();
}
Миниатюры
0
9036 / 2937 / 493
Регистрация: 05.10.2013
Сообщений: 7,960
Записей в блоге: 216
24.05.2024, 15:26
Забыл прикрепить пример выше в архиве. Чтобы появилась задержка в выводе значения цвета в консоль нужно раскомментировать glFinish и закомментировать glFlush перед glReadPixels, вот так:

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    void paintGL() override
    {
        glClear(GL_COLOR_BUFFER_BIT);
        glDrawArrays(GL_TRIANGLES, 0, 3);
 
        if (m_mouseClicked)
        {
            // Read the pixel
            GLubyte pixel[4];
            glFinish();
            // glFlush();
            glReadPixels(m_mouseX, m_mouseY, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
            // Print a color
            qDebug() << pixel[0] / 255.f << pixel[1] / 255.f << pixel[2] / 255.f;
            m_mouseClicked = false;
        }
    }
Вложения
Тип файла: zip pick-color-with-mouse-opengles2-qt6-cpp.zip (1.8 Кб, 2 просмотров)
0
1962 / 818 / 114
Регистрация: 01.10.2012
Сообщений: 4,756
Записей в блоге: 2
25.05.2024, 09:04
Цитата Сообщение от 8Observer8 Посмотреть сообщение
Можете скачать пример и потестить:
Не тот пример чтобы тестить По своему опыту особых задержек glFinish не замечал, не говоря уже о 5 сек, ну это всего лишь "моя машина/карта". Ситуации когда glFinish необходим ("не успело отрисовать") были при массивном рисовании. Если можно прочитать цвет после swapBuffers, то glFinish не нужен. В Вашем примере это решается напр сигналом с QueuedConnection.

Ваши примеры так перегибают палку с "простотой" что теряется всякий смысл. Показать glReadPixels - слишком мало, к тому же читать надо не этой ф-цией. Решили выбирать цветом - ладно. Но тогда рендерите в текстуру, кодируйте ID объекта + ID примитива. Заодно освоите геометрические шейдеры. Передрать пример должно быть выгодно/заманчиво, иначе нафиг он нужен
0
 Аватар для COKPOWEHEU
4079 / 2677 / 432
Регистрация: 09.09.2017
Сообщений: 11,888
27.05.2024, 10:06
Цитата Сообщение от Igor3D Посмотреть сообщение
По своему опыту особых задержек glFinish не замечал, не говоря уже о 5 сек
Наоборот: 5 секунд без glFlush, а с ним - мгновенно. Очевидно, OpenGL не понимает, когда юзер уже закончил рисование и можно отображать его творчество на экране. А glFlush как раз об этом говорит "рисование закончено, отображай". Хотя мне казалось, что *SwapBuffers тоже работает аналогично glFlush. Впрочем, у 8Observer8 я его что-то не увидел.
Цитата Сообщение от Igor3D Посмотреть сообщение
Ваши примеры так перегибают палку с "простотой" что теряется всякий смысл. Показать glReadPixels - слишком мало, к тому же читать надо не этой ф-цией. Решили выбирать цветом - ладно. Но тогда рендерите в текстуру, кодируйте ID объекта + ID примитива. Заодно освоите геометрические шейдеры. Передрать пример должно быть выгодно/заманчиво, иначе нафиг он нужен
Тогда возникнет обратная проблема: пример будет слишком запутанным и заточенным под конкретную задачу, и разобраться в нем будет гораздо сложнее.
1
9036 / 2937 / 493
Регистрация: 05.10.2013
Сообщений: 7,960
Записей в блоге: 216
27.05.2024, 11:44
Цитата Сообщение от Igor3D Посмотреть сообщение
Не тот пример чтобы тестить
Если скачать мой архив выше вашего сообщения, то есть ли задержка? Конкретно в моём примере, а не в прошлом опыте. Пример максимально минимален, чтобы был только код демонстрирующий проблему.

Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Наоборот: 5 секунд без glFlush, а с ним - мгновенно.
У меня работает мгновенное без glFinish и glFlush, если обе команды закомментить:
C++ (Qt)
1
2
3
// glFinish();
// glFlush();
glReadPixels(m_mouseX, m_mouseY, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
Так же мгновенно работает с glFlush вместо glFinish. Задержка в 5 секунд возникает только c glFinish. Скорее всего, это баг Qt. Но я не могу создать "bug report" потому что использую Qt 6.6.3, а сколько-то месяцев назад вышла версия Qt 6.7.0. Просто 6.6.3 требует только один NDK версии 25, который весит 1.36 GB, а 6.7.0 требует два NDK - 25 и 26, причём 26 весит 1.95 GB. Потребуют тестирования на новой версии. Я решил пока это отложить. Я думаю, можно не вызывать и glFlush. Не нашёл нигде информации, что на Qt нужно обязательно вызывать glFlush перед glReadPixel при клике мышкой для определения клика по объекту. А так же не нашёл информации, что нужно обязательно вызывать swapBuffers самому. Может его Qt вызывает - скорее всего это так, иначе были бы мерцания, как на GLUT если если не вызывать swapBuffers.
0
1962 / 818 / 114
Регистрация: 01.10.2012
Сообщений: 4,756
Записей в блоге: 2
27.05.2024, 22:07
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Наоборот: 5 секунд без glFlush, а с ним - мгновенно. Очевидно, OpenGL не понимает, когда юзер уже закончил рисование и можно отображать его творчество на экране. А glFlush как раз об этом говорит "рисование закончено, отображай".
Насколько я помню, не совсем так. glFlush гарантирует что все посланные команды рисования будут активированы, ни одна не останется ждать в очереди. Но и только. glFinish гарантирует что все команды рисования будут завершены, про "отображение" речь не идет. А вот swapBuffers гарантирует также и отображение
Цитата Сообщение от 8Observer8 Посмотреть сообщение
У меня работает мгновенное без glFinish и glFlush
Если взялись учить - учите правильно. Такая последовательность
C++
1
2
glDrawArrays
glReadPixels
Некорректна. Команды рисования (такие как glDrawArrays) - это всего лишь "запрос" карте на рисование, когда и как она его выполнит - ее личное дело, и рассчитывать на готовый результат в последующем вызове glReadPixels мы не можем.
Цитата Сообщение от 8Observer8 Посмотреть сообщение
Не нашёл нигде информации, что на Qt нужно обязательно вызывать glFlush перед glReadPixel при клике мышкой для определения клика по объекту. А так же не нашёл информации, что нужно обязательно вызывать swapBuffers самому. Может его Qt вызывает - скорее всего это так, иначе были бы мерцания, как на GLUT если если не вызывать swapBuffers.
Конечно вызывает, Асыстент об этом упоминает. Испускаете сигнал с QueuedConnection, слот получит управление после swapBuffers, когда рисование завершилось, там и читаете. Есть и другой способ: по меньшей мере для QOpenGLWindow можно рисовать когда хотим (а не только в paintGL). Правда тогда надо самому вызывать swapBuffers в конце (и makeCurrent в начале). Такое есть в примерах Qt
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Тогда возникнет обратная проблема: пример будет слишком запутанным и заточенным под конкретную задачу, и разобраться в нем будет гораздо сложнее.
Ну а что плохого в такой "заточенности"? Все хорошо в меру, излишняя упрощённость столь же плоха. Ну, блин, что это за красный тр-к, дите учится рисовать солнышко?
0
Модератор
Эксперт Java
 Аватар для alecss131
2835 / 1344 / 403
Регистрация: 11.08.2017
Сообщений: 4,297
Записей в блоге: 2
27.05.2024, 22:15
По сути ведь не обязательно же ждать завершения рисования. Можно брать значения предыдущих кадров до очистки экрана. Только с 2 буферами задержка будет если не ошибаюсь в 2 кадра, но даже при 30 кадрах это очень мало и не заметно человеческому глазу, а на экране все не успеет кардинально измениться, да и обычно где есть выбор нету ничего динамического.
0
1962 / 818 / 114
Регистрация: 01.10.2012
Сообщений: 4,756
Записей в блоге: 2
27.05.2024, 22:26
Цитата Сообщение от alecss131 Посмотреть сообщение
Можно брать значения предыдущих кадров до очистки экрана.
Да вообще связываться с экраном - плохая идея. Хотя бы потому что цвета там "нечистые" из-за самплинга. Ясно что надо рендерить в текстуру.

Не по теме:

Сейчас опять начнется

ой, это ж как сложно!
нет-нет, в списке моих приоритетов...
Короче - сачок

0
Модератор
Эксперт Java
 Аватар для alecss131
2835 / 1344 / 403
Регистрация: 11.08.2017
Сообщений: 4,297
Записей в блоге: 2
27.05.2024, 22:44
Цитата Сообщение от Igor3D Посмотреть сообщение
Ясно что надо рендерить в текстуру.
Это лишний проход рендера, лишние дравколлы, а еще создание фреймбуфера.
Я у себя выбор обычно делаю через тест трафарета, тоже glReadPixels, но с GL_STENCIL_INDEX и GL_INT, диапазон сильно меньше чем в цветах, но тоже имеет место быть.
0
9036 / 2937 / 493
Регистрация: 05.10.2013
Сообщений: 7,960
Записей в блоге: 216
27.05.2024, 23:06
Цитата Сообщение от Igor3D Посмотреть сообщение
Команды рисования (такие как glDrawArrays) - это всего лишь "запрос" карте на рисование, когда и как она его выполнит - ее личное дело, и рассчитывать на готовый результат в последующем вызове glReadPixels мы не можем.
У меня в примере выше нет "game loop". paintGL срабатывает один раз после клика мышкой после вызова update():

C++ (Qt)
1
2
3
4
5
6
7
    void mousePressEvent(QMouseEvent *event) override
    {
        m_mouseX = event->pos().x() * devicePixelRatio();
        m_mouseY = (height() - event->pos().y() - 1) * devicePixelRatio();
        m_mouseClicked = true;
        update();
    }
Если я в одном кадре вызываю glDrawArrays и сразу же в этом же кадре вызываю glReadPixels, то если у меня работает, это не значит, что у других будет работать и у кого-то может не работать совсем? Или будет работать через раз?

Цитата Сообщение от Igor3D Посмотреть сообщение
Хотя бы потому что цвета там "нечистые" из-за самплинга.
Это только на границах, допустим, кнопки. Это будет выглядеть, что пользователь нажал чуть рядом с кнопкой, то есть промахнулся. Обычно нажимают на кнопки с запасом от границы.
0
1962 / 818 / 114
Регистрация: 01.10.2012
Сообщений: 4,756
Записей в блоге: 2
27.05.2024, 23:41
Цитата Сообщение от 8Observer8 Посмотреть сообщение
Если я в одном кадре вызываю glDrawArrays и сразу же в этом же кадре вызываю glReadPixels, то если у меня работает, это не значит, что у других будет работать и у кого-то может не работать совсем? Или будет работать через раз?
Полагаю что Ваш красный тр-к будет работать железно А вот массивное рисование - очень может быть что и нет, в зависимости от объема геометрии и мощности карты. Не стоит терять время на выяснение "а когда же это случится", лучше пресечь сразу.
Цитата Сообщение от 8Observer8 Посмотреть сообщение
Это только на границах, допустим, кнопки. Это будет выглядеть, что пользователь нажал чуть рядом с кнопкой, то есть промахнулся. Обычно нажимают на кнопки с запасом от границы.
Не только, напр линии/точки могут быть "достаточно тонкими" и "чистого" цвета на экране не получить. Ну и разве у рисования нет других задач/целей кроме как раскрашивать объекты? Это должно делаться автоматом (в геометрическом шейдере) и "за кадром" (в текстуре). Это нетрудно и интересно
1
 Аватар для COKPOWEHEU
4079 / 2677 / 432
Регистрация: 09.09.2017
Сообщений: 11,888
28.05.2024, 09:20
Цитата Сообщение от Igor3D Посмотреть сообщение
А вот swapBuffers
А вот swapBuffers платформо-зависимая штука, и что она там гарантирует ведомо только ее авторам. Например, она может не вызывать glFlush, glFinish.
Цитата Сообщение от Igor3D Посмотреть сообщение
Ну а что плохого в такой "заточенности"?
То, что становится еще более непонятно как адаптировать этот "рулон 54 метра" кода к своей задаче. Какие функции там нужны, а какие нет, как все это подготовить.
Цитата Сообщение от alecss131 Посмотреть сообщение
По сути ведь не обязательно же ждать завершения рисования. Можно брать значения предыдущих кадров до очистки экрана.
По-хорошему определение объекта вообще не должно отображаться на переднем буфере. Чтобы экран не мерцал между нормальной картинкой и набором психоделичных пятен. В этом смысле тут правильно намекнули на рендер в текстуру.
Цитата Сообщение от 8Observer8 Посмотреть сообщение
Если я в одном кадре вызываю glDrawArrays и сразу же в этом же кадре вызываю glReadPixels, то если у меня работает, это не значит, что у других будет работать и у кого-то может не работать совсем? Или будет работать через раз?
Не забывайте, что OpenGL - клиент-серверная штука. При каких-нибудь экзотичских настройках сжатия потока без glFlush может и не работать. Впрочем, я, например, не знаю что там вызывает Qt.
1
9036 / 2937 / 493
Регистрация: 05.10.2013
Сообщений: 7,960
Записей в блоге: 216
28.05.2024, 13:27
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
По-хорошему определение объекта вообще не должно отображаться на переднем буфере. Чтобы экран не мерцал между нормальной картинкой и набором психоделичных пятен.
А у меня вообще в примере с нивой и каркасом для дома в следующем кадре невозможно будет прочитать цветовой ID объекта, потому что в следующем кадре будет тогда прочитан цвет текстуры. Дело в том, что я в одном кадре сначала рисую объекты с их цветовыми ID, определяю цвет в месте клика, смотрю, что за объект по анализу прочитанного цветового ID, и в этом же кадре делаю ещё один glClear и тут же рисую объекты с текстурами. Вот что удивительно получается. Я ведь рисую на заднем буфере, а glReadPixel получается читает из заднего буфера. Ведь swapBuffers вызывается в конце paintGL. Не может же swapBuffers вызываться сразу после каждого glDrawArrays в одном кадре.
1
827 / 244 / 47
Регистрация: 24.01.2013
Сообщений: 750
28.05.2024, 22:11
8Observer8, glReadPixels читает из текущего glReadBuffer, который по умолчанию
mode is initially GL_FRONT in single-buffered configurations and GL_BACK in double-buffered configurations.
задний буфер при двойной буферизации, так что swapBuffers тут не нужен.
1
1962 / 818 / 114
Регистрация: 01.10.2012
Сообщений: 4,756
Записей в блоге: 2
29.05.2024, 14:04
Цитата Сообщение от 8Observer8 Посмотреть сообщение
Вот что удивительно получается. Я ведь рисую на заднем буфере, а glReadPixel получается..
Вспомните старый анекдот
Да кому он с двадцатью сантиметрами нужен?
Чего Вы вцепились в glReadPixel? Там максимум 4 байта на точку, а с текстурой/FBO можно иметь гораздо больше, как показал zayats80888. Вообще Вы заметили что опытные люди частенько упоминают рендер в текстуру и охотно его юзают? Вы им не пользовались? Ничего страшного, я тоже (или уже успел забыть). Ну вот и хорошая возможность освоить его, с Qt это легко и приятно. Наверняка есть класс-обертка, использование просто bind/release. Делаем объект FBO членом класса и в mousePressEvent его биндим, вызываем painGL и читаем текстуру. Это полчаса чтения Qt букваря и 10-15 строк нового кода. По сути надо "сожрать Qt плюшку". Но вместо этого Вы пререкаетесь, спорите, доказываете - это непродуктивно и непрофессионально (не побоюсь этого слова)

Добавлено через 25 минут
----
Да, и хочу предложить маленькую "викторину" Какие ID надо сохранять в пикcеле?

1) ID объекта/модели
2) ID примитива (напр тр-ка)
3) ID ???

Не путать с др данными, напр глубина Z, барицентрик и.т.д., именно номер/ID
0
 Аватар для COKPOWEHEU
4079 / 2677 / 432
Регистрация: 09.09.2017
Сообщений: 11,888
29.05.2024, 15:16
Цитата Сообщение от Igor3D Посмотреть сообщение
glReadPixel? Там максимум 4 байта на точку
А сколько вам надо? Если речь о поиске объектов, то 4 миллиарда осмысленных объектов вы все равно не наплодите.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
29.05.2024, 15:16
Помогаю со студенческими работами здесь

OpenGL поворот объектов
Есть горизонтальные жалюзи, выполненные в виде прямоугольников (прямоугольники созданы в цикле - это обязательное условие проекта) с...

файлы 3д объектов существуют в OpenGL?
файлы 3д объектов существуют в OpenGL? Чтоб сразу загрузить а не создавать самому. Такие, как X-файлы в directX.?! Ну..дабы понятей...

Как в OpenGL обнаруживать столкновения объектов
Здраствуйте. Подскажите пожалуйста как в OpenGL обнаруживать столкновения объектов или дайте сылку на примеры на си или с++.

Создание теней для объектов в OpenGL
Прошу помочь или хотя бы подсказать. Во вложении программа, которая рисует комнату с зеркалом (отражения реализовал) и несколькими...

Как сделать движение нескольких объектов. OpenGL
Я взял следующий код, но в этом случае движется вся сцена. А моя цель сделать приложение в котором пара объектов (кругов или шаров) будут...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
59
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru