Приложение отрисовывает D2 картинку с точностью до пикселя (среда Borland C++ Builder 6, ОС Windows 7 на Phenom II). Считаю, что когда делаю в OnPaint отрисовку контура квадрата [-1,1]*[-1,1] Код (Text): glColor3d(1.0, 0.0, 0.0); glBegin(GL_LINE_LOOP); glVertex2d(-1.0, -1.0); glVertex2d( 1.0, -1.0); glVertex2d( 1.0, 1.0); glVertex2d(-1.0, 1.0); glEnd(); , то он должен быть весь виден, но видно только слева и снизу. Экспериментирую дальше: закидываю исполняемый файл в виртуальную машину (чистая Windows XP на VMware 8). Прорисовывается только справа и сверху. В control word FPU только сбрасываю биты генерации исключений (все), как рекомендуется в http://edn.embarcadero.com/article/10528. Получается, что изображения не являются эквивалентными при прочих равных условиях? Это как-то регулируется? Как мне нарисовать всю рамку наверняка? control word в обоих случаях равен 0x137F.
_DEN_ неа. рисую только этот квадрат. glEnable(GL_DEPTH_TEST); нигде нет, даже glDisable(GL_DEPTH_TEST); включил
Вы фрустум не устанавливали, а окно у вас квадратное и 1 и -1 совпадают с краями окна? Так вы будете зависеть от того, как реализована растеризация в конкретной карточке или программной эмуляции OpenGL, а также от того, четного или нечетного размера у вас окно. Имхо, на это не стоит полагаться, и рисовать рамку лучше обычными GUI-функциями. Хотя, можно попробовать установить толщину линий в 2 пикселя. Для четных размеров 1 и -1 должны приходиться строго на границы между пикселями, и при тощине 2 в окно должна попасть строго половина толщины линии.
Фрустум не устанавливал. glViewport(0, 0, ClientWidth, ClientHeight);. Делал glViewport(1, 1, ClientWidth - 2, ClientHeight - 2); - не помогает. От чётности размеров ничего не зависит. Похоже что в одном случае к -\infty а в другом к +\infty округляется. Если вообще там FPU вычисления производит. Программка-то вообще тупо пустая: Код (Text): #include <vcl.h> #pragma hdrstop #include <GL/gl.h> #include <limits.h> #include <float.h> #include <stdio.h> #include "MainWindow.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TFormMain *FormMain; //--------------------------------------------------------------------------- bool TFormMain::SetDCPixelFormat(HDC dc) { PIXELFORMATDESCRIPTOR pfd; memset(&pfd, 0, sizeof(pfd)); pfd.nSize = sizeof(pfd); pfd.nVersion = 1; pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; pfd.iPixelType = PFD_TYPE_RGBA; pfd.cColorBits = 0x10; //pfd.cDepthBits = 0x20; pfd.iLayerType = PFD_MAIN_PLANE; return (SetPixelFormat(dc, ChoosePixelFormat(dc, &pfd), &pfd) != FALSE); } //--------------------------------------------------------------------------- __fastcall TFormMain::TFormMain(TComponent* Owner) : TForm(Owner) { Application->OnIdle = IdleLoop; //_control87(MCW_EM, MCW_EM); } //--------------------------------------------------------------------------- void __fastcall TFormMain::IdleLoop(TObject*, bool& done) { done = false; //RenderGLScene(); //SwapBuffers(dc); } //--------------------------------------------------------------------------- bool TFormMain::SetFont(HDC dc, HFONT & hFont) { LOGFONT lf = { -MulDiv(DEFAULT_FONTSIZE, GetDeviceCaps(dc, LOGPIXELSY), 72), 0, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET, OUT_DEVICE_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, FF_DONTCARE | DEFAULT_PITCH, DEFAULT_FONT }; hFont = CreateFontIndirect(&lf); if (hFont != NULL) { if (SelectObject(dc, hFont) != NULL) { //GetTextMetrics(dc, &tm); return true; } DeleteObject(hFont); } return false; } //--------------------------------------------------------------------------- void __fastcall TFormMain::FormPaint(TObject *Sender) { unsigned __int16 _cw = _control87(MCW_EM, MCW_EM); /*__asm { FNSTCW _cw FNINIT } */ wglMakeCurrent(dc, rc); glViewport(0, 0, ClientWidth, ClientHeight); CONST COLORREF BKCOLOR = ColorToRGB(Color); glClearColor(GetRValue(BKCOLOR) / (GLdouble)UCHAR_MAX, GetGValue(BKCOLOR) / (GLdouble)UCHAR_MAX, GetBValue(BKCOLOR) / (GLdouble)UCHAR_MAX, 1.0); glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // paint glColor3d(1.0, 0.0, 0.0); glBegin(GL_LINE_LOOP); glVertex2d(-1.0, -1.0); glVertex2d( 1.0, -1.0); glVertex2d( 1.0, 1.0); glVertex2d(-1.0, 1.0); glEnd(); SwapBuffers(dc); wglMakeCurrent(IGNORE, NULL); _controlfp(_cw, _cw); } //--------------------------------------------------------------------------- void __fastcall TFormMain::FormDestroy(TObject *Sender) { unsigned __int16 _cw = _control87(MCW_EM, MCW_EM); /*__asm { FNSTCW _cw FNINIT }*/ wglDeleteContext(rc); ReleaseDC(Handle, dc); DeleteObject(hf); _controlfp(_cw, _cw); } //--------------------------------------------------------------------------- void __fastcall TFormMain::FormCreate(TObject *Sender) { dc = GetDC(Handle); if (dc == NULL) { throw Exception("cannot obtain device context"); } if (!SetDCPixelFormat(dc)) { throw Exception("cannot set pixel format"); } unsigned __int16 _cw = _control87(MCW_EM, MCW_EM); /*__asm { FNSTCW _cw FNINIT }*/ rc = wglCreateContext(dc); if (rc == NULL) { throw Exception("cannot create rendering context"); } if (!SetFont(dc, hf)) { throw Exception("cannot set font to device context"); } wglMakeCurrent(dc, rc); glDisable(GL_DEPTH_TEST); // init GLF_STRING_LIST = glGenLists('`'); wglUseFontBitmaps(dc, ' ', '`', GLF_STRING_LIST); wglMakeCurrent(IGNORE, NULL); _controlfp(_cw, _cw); } //--------------------------------------------------------------------------- void __fastcall TFormMain::FormResize(TObject *Sender) { Repaint(); } //---------------------------------------------------------------------------
Там не округление, там карточка растеризацию делает. ПОпробуйте все-таки толщину 2 поставить glLineWidth(2.0), тогда растеризация будет раскидывать линию на два соседних пиксела.
Dukales Способ растаризации нигде не регламинтирован. Более того есть такой совет рисовать не линии, а заменять их треугольники. Перед выходом директх 11 были попытки со стороны майкрософт привести к единому стандарту. Не знаю насколько они в этом продвинулись.
Вот нашёл. http://msdn.microsoft.com/en-us/library/windows/desktop/cc627092(v=vs.85).aspx Если видео карта поддерживает DirectX 10, то думаю что на OpenGL будут такие же эффекты. А да, аккуратно проверь если не путаю то 1 проходит не по центру пикселя, а по его границе.
Pavia Dmitry_Milk Спасибо. Вот как решил проблему (не чисто — остаётся зазор в один пиксель, соответственно с разных сторон в разных случаях): Код (Text): unsigned __int16 _cw = _control87(MCW_EM, MCW_EM); wglMakeCurrent(dc, rc); glViewport(0, 0, ClientWidth, ClientHeight); CONST COLORREF BKCOLOR = ColorToRGB(Color); glClearColor(GetRValue(BKCOLOR) / (GLdouble)UCHAR_MAX, GetGValue(BKCOLOR) / (GLdouble)UCHAR_MAX, GetBValue(BKCOLOR) / (GLdouble)UCHAR_MAX, 1.0); glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, ClientWidth, 0, ClientHeight, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // paint glColor3d(1.0, 0.0, 0.0); glBegin(GL_LINE_LOOP); glVertex2d(1, 1); glVertex2d(1, ClientHeight - 1); glVertex2d(ClientWidth - 1, ClientHeight - 1); glVertex2d(ClientWidth - 1, 1); glEnd(); SwapBuffers(dc); wglMakeCurrent(IGNORE, NULL); _controlfp(_cw, _cw);
Дык, тогда то же самое можно было сделать, используя не Код (Text): glVertex2d( 1.0, 1.0) а Код (Text): glVertex2d( (ClientWidth-1)/ClientWidth, (ClientHeight - 1)/ClientHeight) (ну то есть масштабируя не через glOrtho, а прямо по месту).