#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-координатами.
Есть два способа решить эту проблему:
- Вы должны предпочесть использовать функции с компонентом z, потому что opengl некорректно отображается при z = 0. z = 1 соответствует нормализованному экранному пространству
- или вы добавляете a
glTranslatef(0,0,1);
, чтобы перейти к нормализованному экранному пространству
Не забудьте отключить тестирование глубины при рендеринге 2D в пространстве экрана и сбросе матрицы modelview.
Комментарии:
1. Извините, но я не совсем понимаю, что именно мне нужно сделать. После wglMakeCurrent (hDC, context); Я устанавливаю glDisable (GL_DEPTH_TEST); и нарисуйте прямоугольник с помощью glVertex3f (0.0, 0.5, 1); но он все еще мерцает: (