округление

Тема в разделе "WASM.OpenGL", создана пользователем Dukales, 6 окт 2011.

  1. Dukales

    Dukales New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2009
    Сообщения:
    199
    Приложение отрисовывает D2 картинку с точностью до пикселя (среда Borland C++ Builder 6, ОС Windows 7 на Phenom II). Считаю, что когда делаю в OnPaint отрисовку контура квадрата [-1,1]*[-1,1]
    Код (Text):
    1.   glColor3d(1.0, 0.0, 0.0);
    2.   glBegin(GL_LINE_LOOP);
    3.   glVertex2d(-1.0, -1.0);
    4.   glVertex2d( 1.0, -1.0);
    5.   glVertex2d( 1.0,  1.0);
    6.   glVertex2d(-1.0,  1.0);
    7.   glEnd();
    , то он должен быть весь виден, но видно только слева и снизу. Экспериментирую дальше: закидываю исполняемый файл в виртуальную машину (чистая Windows XP на VMware 8). Прорисовывается только справа и сверху.
    В control word FPU только сбрасываю биты генерации исключений (все), как рекомендуется в http://edn.embarcadero.com/article/10528.
    Получается, что изображения не являются эквивалентными при прочих равных условиях? Это как-то регулируется? Как мне нарисовать всю рамку наверняка? control word в обоих случаях равен 0x137F.
     
  2. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Dukales

    Да небось рисуешь с Z-тестом, вот внешний вид и зависит от случая :)
     
  3. Dukales

    Dukales New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2009
    Сообщения:
    199
    _DEN_
    неа. рисую только этот квадрат. glEnable(GL_DEPTH_TEST); нигде нет, даже glDisable(GL_DEPTH_TEST); включил
     
  4. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    540
    Вы фрустум не устанавливали, а окно у вас квадратное и 1 и -1 совпадают с краями окна?
    Так вы будете зависеть от того, как реализована растеризация в конкретной карточке или программной эмуляции OpenGL, а также от того, четного или нечетного размера у вас окно. Имхо, на это не стоит полагаться, и рисовать рамку лучше обычными GUI-функциями.
    Хотя, можно попробовать установить толщину линий в 2 пикселя. Для четных размеров 1 и -1 должны приходиться строго на границы между пикселями, и при тощине 2 в окно должна попасть строго половина толщины линии.
     
  5. Dukales

    Dukales New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2009
    Сообщения:
    199
    Фрустум не устанавливал. glViewport(0, 0, ClientWidth, ClientHeight);. Делал glViewport(1, 1, ClientWidth - 2, ClientHeight - 2); - не помогает.
    От чётности размеров ничего не зависит. Похоже что в одном случае к -\infty а в другом к +\infty округляется. Если вообще там FPU вычисления производит.
    Программка-то вообще тупо пустая:
    Код (Text):
    1. #include <vcl.h>
    2. #pragma hdrstop
    3. #include <GL/gl.h>
    4. #include <limits.h>
    5. #include <float.h>
    6. #include <stdio.h>
    7.  
    8. #include "MainWindow.h"
    9. //---------------------------------------------------------------------------
    10. #pragma package(smart_init)
    11. #pragma resource "*.dfm"
    12. TFormMain *FormMain;
    13. //---------------------------------------------------------------------------
    14. bool TFormMain::SetDCPixelFormat(HDC dc)
    15. {
    16.   PIXELFORMATDESCRIPTOR pfd;
    17.   memset(&pfd, 0, sizeof(pfd));
    18.   pfd.nSize = sizeof(pfd);
    19.   pfd.nVersion = 1;
    20.   pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    21.   pfd.iPixelType = PFD_TYPE_RGBA;
    22.   pfd.cColorBits = 0x10;
    23.   //pfd.cDepthBits = 0x20;
    24.   pfd.iLayerType = PFD_MAIN_PLANE;
    25.   return (SetPixelFormat(dc, ChoosePixelFormat(dc, &pfd), &pfd) != FALSE);
    26. }
    27. //---------------------------------------------------------------------------
    28. __fastcall TFormMain::TFormMain(TComponent* Owner)
    29.   : TForm(Owner)
    30. {
    31.   Application->OnIdle = IdleLoop;
    32.   //_control87(MCW_EM, MCW_EM);
    33. }    
    34. //---------------------------------------------------------------------------
    35. void __fastcall TFormMain::IdleLoop(TObject*, bool& done)
    36. {
    37.     done = false;
    38.     //RenderGLScene();
    39.     //SwapBuffers(dc);
    40. }
    41. //---------------------------------------------------------------------------
    42. bool TFormMain::SetFont(HDC dc, HFONT & hFont)
    43. {
    44.   LOGFONT lf = {
    45.                 -MulDiv(DEFAULT_FONTSIZE, GetDeviceCaps(dc, LOGPIXELSY), 72),
    46.                 0,
    47.                 0,
    48.                 0,
    49.                 FW_NORMAL,
    50.                 0,
    51.                 0,
    52.                 0,
    53.                 ANSI_CHARSET,
    54.                 OUT_DEVICE_PRECIS,
    55.                 CLIP_DEFAULT_PRECIS,
    56.                 ANTIALIASED_QUALITY,
    57.                 FF_DONTCARE | DEFAULT_PITCH,
    58.                 DEFAULT_FONT
    59.                };
    60.  
    61.   hFont = CreateFontIndirect(&lf);
    62.   if (hFont != NULL) {
    63.     if (SelectObject(dc, hFont) != NULL) {
    64.       //GetTextMetrics(dc, &tm);
    65.       return true;
    66.     }
    67.     DeleteObject(hFont);
    68.   }
    69.   return false;
    70. }
    71. //---------------------------------------------------------------------------
    72. void __fastcall TFormMain::FormPaint(TObject *Sender)
    73. {
    74.   unsigned __int16 _cw = _control87(MCW_EM, MCW_EM);
    75.   /*__asm {
    76.     FNSTCW _cw
    77.     FNINIT
    78.   }
    79.   */
    80.   wglMakeCurrent(dc, rc);
    81.   glViewport(0, 0, ClientWidth, ClientHeight);
    82.   CONST COLORREF BKCOLOR = ColorToRGB(Color);
    83.   glClearColor(GetRValue(BKCOLOR) / (GLdouble)UCHAR_MAX, GetGValue(BKCOLOR) / (GLdouble)UCHAR_MAX, GetBValue(BKCOLOR) / (GLdouble)UCHAR_MAX, 1.0);
    84.   glClear(GL_COLOR_BUFFER_BIT);
    85.   glMatrixMode(GL_MODELVIEW);
    86.   glLoadIdentity();
    87.   // paint
    88.   glColor3d(1.0, 0.0, 0.0);
    89.   glBegin(GL_LINE_LOOP);
    90.   glVertex2d(-1.0, -1.0);
    91.   glVertex2d( 1.0, -1.0);
    92.   glVertex2d( 1.0,  1.0);
    93.   glVertex2d(-1.0,  1.0);
    94.   glEnd();
    95.   SwapBuffers(dc);
    96.   wglMakeCurrent(IGNORE, NULL);
    97.   _controlfp(_cw, _cw);
    98. }
    99. //---------------------------------------------------------------------------
    100.  
    101. void __fastcall TFormMain::FormDestroy(TObject *Sender)
    102. {
    103.   unsigned __int16 _cw = _control87(MCW_EM, MCW_EM);
    104.   /*__asm {
    105.     FNSTCW _cw
    106.     FNINIT
    107.   }*/
    108.   wglDeleteContext(rc);
    109.   ReleaseDC(Handle, dc);
    110.   DeleteObject(hf);
    111.   _controlfp(_cw, _cw);
    112. }
    113. //---------------------------------------------------------------------------
    114.  
    115. void __fastcall TFormMain::FormCreate(TObject *Sender)
    116. {
    117.   dc = GetDC(Handle);
    118.   if (dc == NULL) {
    119.     throw Exception("cannot obtain device context");
    120.   }
    121.   if (!SetDCPixelFormat(dc)) {
    122.     throw Exception("cannot set pixel format");
    123.   }                  
    124.   unsigned __int16 _cw = _control87(MCW_EM, MCW_EM);
    125.   /*__asm {
    126.     FNSTCW _cw
    127.     FNINIT
    128.   }*/
    129.   rc = wglCreateContext(dc);
    130.   if (rc == NULL) {
    131.     throw Exception("cannot create rendering context");
    132.   }
    133.   if (!SetFont(dc, hf)) {
    134.     throw Exception("cannot set font to device context");
    135.   }
    136.   wglMakeCurrent(dc, rc);
    137.   glDisable(GL_DEPTH_TEST);  
    138.   // init
    139.   GLF_STRING_LIST = glGenLists('`');
    140.   wglUseFontBitmaps(dc, ' ', '`', GLF_STRING_LIST);
    141.   wglMakeCurrent(IGNORE, NULL);  
    142.   _controlfp(_cw, _cw);
    143. }
    144. //---------------------------------------------------------------------------
    145. void __fastcall TFormMain::FormResize(TObject *Sender)
    146. {
    147.   Repaint();
    148. }
    149. //---------------------------------------------------------------------------
     
  6. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    540
    Там не округление, там карточка растеризацию делает. ПОпробуйте все-таки толщину 2 поставить glLineWidth(2.0), тогда растеризация будет раскидывать линию на два соседних пиксела.
     
  7. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    Dukales
    Способ растаризации нигде не регламинтирован. Более того есть такой совет рисовать не линии, а заменять их треугольники.
    Перед выходом директх 11 были попытки со стороны майкрософт привести к единому стандарту. Не знаю насколько они в этом продвинулись.
     
  8. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    Вот нашёл.
    http://msdn.microsoft.com/en-us/library/windows/desktop/cc627092(v=vs.85).aspx
    Если видео карта поддерживает DirectX 10, то думаю что на OpenGL будут такие же эффекты.
    А да, аккуратно проверь если не путаю то 1 проходит не по центру пикселя, а по его границе.
     
  9. Dukales

    Dukales New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2009
    Сообщения:
    199
    Pavia
    Dmitry_Milk
    Спасибо.
    Вот как решил проблему (не чисто — остаётся зазор в один пиксель, соответственно с разных сторон в разных случаях):
    Код (Text):
    1.   unsigned __int16 _cw = _control87(MCW_EM, MCW_EM);
    2.   wglMakeCurrent(dc, rc);
    3.   glViewport(0, 0, ClientWidth, ClientHeight);
    4.   CONST COLORREF BKCOLOR = ColorToRGB(Color);
    5.   glClearColor(GetRValue(BKCOLOR) / (GLdouble)UCHAR_MAX, GetGValue(BKCOLOR) / (GLdouble)UCHAR_MAX, GetBValue(BKCOLOR) / (GLdouble)UCHAR_MAX, 1.0);
    6.   glClear(GL_COLOR_BUFFER_BIT);
    7.   glMatrixMode(GL_PROJECTION);
    8.   glLoadIdentity();
    9.   glOrtho(0, ClientWidth, 0, ClientHeight, -1.0, 1.0);
    10.   glMatrixMode(GL_MODELVIEW);
    11.   glLoadIdentity();
    12.  
    13.   // paint
    14.   glColor3d(1.0, 0.0, 0.0);
    15.   glBegin(GL_LINE_LOOP);
    16.   glVertex2d(1, 1);
    17.   glVertex2d(1, ClientHeight - 1);
    18.   glVertex2d(ClientWidth - 1,  ClientHeight - 1);
    19.   glVertex2d(ClientWidth - 1,  1);
    20.   glEnd();
    21.   SwapBuffers(dc);
    22.   wglMakeCurrent(IGNORE, NULL);
    23.   _controlfp(_cw, _cw);
     
  10. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    540
    Дык, тогда то же самое можно было сделать, используя не
    Код (Text):
    1. glVertex2d( 1.0,  1.0)
    а
    Код (Text):
    1. glVertex2d( (ClientWidth-1)/ClientWidth,  (ClientHeight - 1)/ClientHeight)
    (ну то есть масштабируя не через glOrtho, а прямо по месту).
     
  11. Dukales

    Dukales New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2009
    Сообщения:
    199
    Dmitry_Milk
    Тогда надо везде таскать за собой множители или glTranslated, glScaled.