Рисование наложения OpenGL с использованием перехвата буферов подкачки

#c #winapi #opengl

#c #winapi #opengl

Вопрос:

Я пытаюсь создать библиотеку, которая позволила бы мне рисовать наложение поверх содержимого игрового окна, использующего OpenGL, путем перехвата вызова функции SwapBuffers . Для перехвата я использую обходные пути Microsoft.

 BOOL WINAPI __SwapBuffers(HDC hDC)
{
    HGLRC oldContext = wglGetCurrentContext();

    if (!context) // Global variable
    {
        context = wglCreateContext(hDC);
    }

    wglMakeCurrent(hDC, context);

    // Drawing

    glRectf(0.1F, 0.5F, 0.2F, 0.6F);

    wglMakeCurrent(hDC, oldContext);

    return _SwapBuffers(hDC); // Call the original SwapBuffers
}
 

Этот код работает, но иногда, когда я двигаю мышью, мое наложение мигает. Почему? На некоторых форумах говорилось, что такая реализация может значительно снизить FPS. Есть ли какая-нибудь лучшая альтернатива? Как мне правильно перевести обычную позицию в позицию OpenGL? Например, ширина = 1366. Получается 1366 = 1, а 0 = -1. Как получить значение, например, для 738? А как насчет роста?

Комментарии:

1. ndc_x = 2.0 * window_x / 1366.0 - 1.0 — NDC (нормализованная координата устройства)

2. Не связанный с вашей непосредственной проблемой, __SwapBuffers это зарезервированный идентификатор («идентификаторы с двойным подчеркиванием в любом месте зарезервированы»).

3. О, я даже не знала. Ну, это вроде как работает с этим.. Я просто не знаю, как лучше назвать реальные SwapBuffers и мои функции SwapBuffers.

Ответ №1:

Чтобы преобразовать координату экрана в нормальную координату, вам необходимо знать ширину экрана и высоту экрана, линейное отображение от [0, screenwidth] до [-1, 1] / [0, screenheight] до [-1, 1]. Это так просто, как показано ниже:

 int screenwidth, screenheight;
//...
screenwidth = 1366;
screenheight = 738;
//...
float screenx, screeny;
float x = (screenx/(float)screenwidth)*2-1;
float y = (screeny/(float)screenheight)*2-1;
 

Задача z=0:
glRect рендерится до z = 0, это проблема, потому что плоскость была бы бесконечно близка. Потому что opengl все еще рассматривает рендеринг в мировом пространстве. Экранное пространство находится в точке (x, y, 1) в не преобразованном мировом пространстве. OpenGL почти всегда работает с 3D-координатами.

Есть два способа решить эту проблему:

  1. Вы должны предпочесть использовать функции с компонентом z, потому что opengl некорректно отображается при z = 0. z = 1 соответствует нормализованному экранному пространству
  2. или вы добавляете a glTranslatef(0,0,1); , чтобы перейти к нормализованному экранному пространству

Не забудьте отключить тестирование глубины при рендеринге 2D в пространстве экрана и сбросе матрицы modelview.

Комментарии:

1. Извините, но я не совсем понимаю, что именно мне нужно сделать. После wglMakeCurrent (hDC, context); Я устанавливаю glDisable (GL_DEPTH_TEST); и нарисуйте прямоугольник с помощью glVertex3f (0.0, 0.5, 1); но он все еще мерцает: (