Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Форум / Камрады, нужна помошь! Windows, GDI-Generic OpenGL

Камрады, нужна помошь! Windows, GDI-Generic OpenGL

Advanced: Тема повышенной сложности или важная.
Lion007Постоялецwww7 мар. 201819:16#0
Приветствую!

В нормальной ситуации - честное слово, я последнее, к чему склоняюсь - так это к ошибке в ОС.
сначала - мой косяк. потом - косяк компилятора. потом - условия (в смысле окружения) использования. Косяк в системном компоненте - честное слово, последняя мысль...

Это была преамбула, а теперь будет амбула :)

В мелкомягкой софтверной (СОФТВЕРНОЙ! это важно!) реализации - не работает альфа-тест для линий. ну не работает и  все.

я, конечно, понимаю, что нормальные люди с GENERIC GDI GL не работают - но у меня выбора нет. мне иногда НАДО. и у меня НЕТ возможности получить нормальный контекст.
ну нету, правда...

итого : не работает...

был написан тестовый код -тупой до безумия. рисуем 3 ряда одного и того же квадратика по 3 варианта. просто цветной квадратик, две точки (по диагонали) с alpha = 1, другие две -
с альфа = 0.

1 ряд (нижний) - без альфа-теста
2 ряд (средний) - альфа-тест типа равно 1 (на самом деле >= 0.95)
3 ряд (верхний) - альфа-тест типа < 1 (на самом деле < 0.95)

в каждом ряду : левый квадратик - это glPolygonMoge(GL_FRONT_AND_BACK, GL_FILL); второй - GL_LINE Третий - GL_POINT.
результат - явно неадекватный...
в чем прикол : для FILL и POINT альфа-тест работает адекватно. рисование просто линиями (то есть просто линиями, через glBegin(GL_LINES\GL_LINE_STRIP\GL_LINE_LOOP) картины не меняет).

аппаратно-ускоренные режимы (которые НЕ GDI-GENERIC) работают нормально -честно режуть альфа-тестом все, чо надо.

вопрос - это все-таки GDI-GENERIC кривой, или мои ручки?


кусок кода, который генерит картинку :

//-----------------------------------------------------------------------------
static void drawSample()
{
  glBegin(GL_QUADS);
    glColor4d(1, 0, 0, 1);
    glVertex2d(-0.8, -0.8);

    glColor4d(0, 1, 0, 0);
    glVertex2d(0.8, -0.8);

    glColor4d(0, 0, 1, 1);
    glVertex2d(0.8,  0.8);

    glColor4d(1, 0, 1, 0);
    glVertex2d(-0.8, 0.8);

    glColor4d(1, 0, 0, 1);
    glVertex2d(-0.8, -0.8);
  glEnd();
}

//-----------------------------------------------------------------------------
void testGDI()
{
  HostDIBRasterImage img(NULL, 256, 256, 32, NULL);
  CGraphicsParamsManager gpManager;
  int pf = selectPixelFormat(img.hdc(), 32, false, false, false, false, true, gpManager);
  PIXELFORMATDESCRIPTOR pfd ;
  memset(&pfd,0, sizeof(PIXELFORMATDESCRIPTOR));
  pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
  pfd.nVersion = 1;
  DescribePixelFormat(img.hdc(), pf, sizeof(pfd), &pfd);
  NCGS_VERIFY(::SetPixelFormat(img.hdc(), pf, &pfd));

  HGLRC rc = wglGetCurrentContext();
  HDC   dc = wglGetCurrentDC();

  HGLRC hrc = wglCreateContext(img.hdc());
  NCGS_ASSERT(hrc);
  wglMakeCurrent(img.hdc(), hrc);

  glClearColor(0,0,0,0); // clear with BLACK
  glClearDepth(1.0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  glDepthFunc(GL_LEQUAL);
  glEnable(GL_DEPTH_TEST);
  glShadeModel(GL_SMOOTH);
  glPointSize(4);

  glLoadIdentity();

  glDisable(GL_BLEND);
  glEnable(GL_LINE_SMOOTH);

  // no alpha test
  glDisable(GL_ALPHA_TEST);
  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  glPushMatrix();
    glTranslated(-0.66, -0.66, 0);
    glScaled(0.3, 0.3, 0.3);
    drawSample();
  glPopMatrix();

  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  glPushMatrix();
    glTranslated( 0, -0.66, 0);
    glScaled(0.3, 0.3, 0.3);
    drawSample();
  glPopMatrix();

  glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
  glPushMatrix();
    glTranslated( 0.66, -0.66, 0);
    glScaled(0.3, 0.3, 0.3);
    drawSample();
  glPopMatrix();

  // alpha test GL_EQUAL, 1.0 (GL_GEQUAL, 0.95)
  glAlphaFunc(GL_GEQUAL, 0.95);
  glEnable(GL_ALPHA_TEST);
  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  glPushMatrix();
    glTranslated(-0.66, 0, 0);
    glScaled(0.3, 0.3, 0.3);
    drawSample();
  glPopMatrix();

  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  glPushMatrix();
    glTranslated( 0,  0, 0);
    glScaled(0.3, 0.3, 0.3);
    drawSample();
  glPopMatrix();

  glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
  glPushMatrix();
    glTranslated( 0.66, 0, 0);
    glScaled(0.3, 0.3, 0.3);
    drawSample();
  glPopMatrix();

  // alpha test GL_LESS, 1.0 (GL_LESS, 0.95)
  glAlphaFunc(GL_LESS, 0.95);
  glEnable(GL_ALPHA_TEST);
  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  glPushMatrix();
    glTranslated(-0.66, 0.66, 0);
    glScaled(0.3, 0.3, 0.3);
    drawSample();
  glPopMatrix();

  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  glPushMatrix();
    glTranslated( 0,  0.66, 0);
    glScaled(0.3, 0.3, 0.3);
    drawSample();
  glPopMatrix();

  glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
  glPushMatrix();
    glTranslated( 0.66, 0.66, 0);
    glScaled(0.3, 0.3, 0.3);
    drawSample();
  glPopMatrix();

  // insert white background
  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  glDisable(GL_ALPHA_TEST);
  glDisable(GL_BLEND);
  glColor4d(1, 1, 1, 1);
  glBegin(GL_QUADS);
    glVertex3d(-1, -1, 0.5);
    glVertex3d( 1, -1, 0.5);
    glVertex3d( 1,  1, 0.5);
    glVertex3d(-1,  1, 0.5);
  glEnd();

  wglMakeCurrent(dc, rc);

  img.clipboardCopy();
}
картинка получается такая... вопорс - фигли альфа-тест не работает?
Картинко | Камрады, нужна помошь! Windows, GDI-Generic OpenGL

Lion007Постоялецwww7 мар. 201822:38#2
и? любой человек, который хоть раз запустил GL под виндозой - это видел... В чем сила, брат?
идиотизм ситуации - альфа-тест - это штатно-попиксельная операция. ну, просто по спецификации ГЛ. и оно все так и есть - но для линий - не работает. для точек\треугольников\квадов\полигонов\ - работает. для линий - НЕТ. причем, что характерно, как только я перестаю требовать GDI-GENERIC контекст - все тут же начинает работать нормально. им пофиг, что за примитив я рисую. работает альфа-тест! и это правильно - операция-то пофрагментная! а на генерике - ХРЕНУШКИ...

собственно, вопрос надо, наверное, видоизменить.. как обойти - не вопрос. но, может, кто-то ткнет носом в то, что я сделел неправильно? хотя с GL - это не так и просто...

зы: дамп ошибок - пустой! :)

boolУчастникwww7 мар. 201823:00#3
Lion007
Ну вообще-то кода твоих функций, которые заполняют Pixelformatdescriptor - не видно. Вдруг у тебя ошибка там.
Lion007Постоялецwww7 мар. 201823:13#4
bool
вообще-то ты прав. но... ок :)
//-----------------------------------------------------------------------------
// Choose pixel format replacement - to allow select software formats
//-----------------------------------------------------------------------------
int selectPixelFormat(HDC hDC, int bpp,
                      bool bScreen, bool bDoubleBuffer, bool bAux, bool bAccum, bool bSoftware,
                      const CGraphicsParamsManager& pGraphicsParamsManager)
{
  int iPixelType = PFD_TYPE_RGBA;
  DWORD dwFlags = PFD_SUPPORT_OPENGL;
  if (bScreen)
  {
    dwFlags |= PFD_DRAW_TO_WINDOW;
    if (bDoubleBuffer)
      dwFlags |= PFD_DOUBLEBUFFER;
  } else
  {
    dwFlags |= PFD_DRAW_TO_BITMAP;
  }
  if (bpp < 16)
  {
    dwFlags |= PFD_NEED_PALETTE;
    iPixelType = PFD_TYPE_COLORINDEX;
  }

  bool bUseAA = pGraphicsParamsManager.useAntialiasing();
  if (bUseAA)
  {
    const char * wglARB = wglGetExtensionsStringARB(hDC);
    if (!glexHasExtension(wglARB, "WGL_ARB_multisample") && !glexHasExtension(wglARB, "GL_ARB_multisample"))
      bUseAA = false; // no FSAA pixel format extension
  }

  if (bSoftware)
  {
    bUseAA = false; // NO antialising in software mode

    DWORD dwFlags2 = dwFlags | PFD_GENERIC_FORMAT;
    PIXELFORMATDESCRIPTOR pfd;
    memset(&pfd,0, sizeof(PIXELFORMATDESCRIPTOR));
    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); 
    pfd.nVersion = 1;                        // Version number
    int num = DescribePixelFormat(hDC, 1, sizeof(pfd), &pfd);

    for (int pf = 1; pf <= num; ++pf)
    {
      memset(&pfd,0, sizeof(PIXELFORMATDESCRIPTOR));
      pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); 
      pfd.nVersion = 1;                        // Version number
      if (DescribePixelFormat(hDC, pf, sizeof(pfd), &pfd))
      {
        // check format
        if (pfd.iPixelType != iPixelType)
          continue;
        if ((pfd.dwFlags & dwFlags2) != dwFlags2)
          continue;
        if (pfd.cColorBits < bpp)
          continue;
        if (pfd.cStencilBits < 1) // we need stencil
          continue;
        if (pfd.cDepthBits < 16) // we need z-buffer
          continue;
        if (bAccum && !pfd.cAccumBits)
          continue;
        if (bAux && !pfd.cAuxBuffers)
          continue;

        // wow! acceptable format!
        return pf;
      }
    }
  }

  if (bUseAA)
  {
    int atr[3] = { WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB, 0 };

    ModeMultisampleParams bestModeMS = { 0, 0, 0 };

    DWORD dwFlags2 = dwFlags | PFD_GENERIC_ACCELERATED;
    PIXELFORMATDESCRIPTOR pfd;
    memset(&pfd,0, sizeof(PIXELFORMATDESCRIPTOR));
    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); 
    pfd.nVersion = 1;                        // Version number
    int num = DescribePixelFormat(hDC, 1, sizeof(pfd), &pfd);
    for (int pf = 1; pf <= num; ++pf)
    {
      memset(&pfd,0, sizeof(PIXELFORMATDESCRIPTOR));
      pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); 
      pfd.nVersion = 1;                        // Version number
      if (DescribePixelFormat(hDC, pf, sizeof(pfd), &pfd))
      {
        // check format
        if (pfd.iPixelType != iPixelType)
          continue;
        //if ((pfd.dwFlags & dwFlags) != dwFlags)
        //  continue;
        if ((pfd.dwFlags & (PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER)) != (PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER))
          continue;
        if (pfd.cColorBits < bpp)
          continue;
        if (pfd.cStencilBits < 1) // we need stencil
          continue;
        if (pfd.cDepthBits < 16)  // we need z-buffer
          continue;
        if (bAccum && !pfd.cAccumBits)
          continue;
        if (bAux && !pfd.cAuxBuffers)
          continue;

        //NCGS_ASSERT(wglGetPixelFormatAttribivARB);
        int val[3]= { 0, 0, 0 };
        if (!wglGetPixelFormatAttribivARB(hDC, pf, 0, 2, atr, val))
          continue;
        if (val[0] < 1)          // no sample buffers
          continue;

        ModeMultisampleParams modeMS = { pf, val[1], pfd.dwFlags };

        if (compareModesMS(modeMS, bestModeMS) > 0)
          bestModeMS = modeMS;
      }
    }
    if (bestModeMS.msMode > 0)
      return bestModeMS.msMode; // acceptable mode found
  }

  // use accelerated PF or no appropriate software PF found
  dwFlags |= PFD_GENERIC_ACCELERATED;

  PIXELFORMATDESCRIPTOR pfd;
  memset(&pfd,0, sizeof(PIXELFORMATDESCRIPTOR));
  pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); 
  pfd.nVersion      = 1;                        // Version number
  pfd.dwFlags      =  dwFlags;
  pfd.iPixelType    = (BYTE)iPixelType;
  pfd.cColorBits    = (BYTE)bpp;
  pfd.cDepthBits    = 24;                      // 24-bit depth buffer
  pfd.iLayerType    = PFD_MAIN_PLANE;          // Layer type
  pfd.cStencilBits  = 1;

  if (bAccum)
    pfd.cAccumBits  = 32;
  if (bAux)
    pfd.cAuxBuffers = 1;

  return ChoosePixelFormat(hDC, &pfd);
}

это было неинтересно.... я (ну, как мне казалось) все-таки хотя бы худой идиот..

идея (изначальная - была в чем - вот вам HRC - фигарьте его как хотите).
не переходя на личности... я - с разынми контекстами работал... шутка :)
мне, по большому счету пофиг - я обойдусь. я уже говрил, знаю как - но....
но мелкомягкие облажались. их код работает неправильно. есть пруф.
успокоит меня - пруф что дебил именно я, а не майкрософт...

boolУчастникwww7 мар. 201823:28#5
Lion007
Не знаю, влияет ли то, что у тебя не задано cAlphaBits в PFD. В GL, насколько я помню, достаточно просто PFD_TYPE_RGBA и cColorBits = 32. Но попробуй еще и альфу отдельно, вдруг.

хотя.. вроде, не должно никак влиять и для PPFD_TYPE_RGBA нужно именно cColorBits.

Правка: 7 мар. 2018 23:30

Lion007Постоялецwww7 мар. 201823:48#6
не влияет. ребята, поймите правильно. прежде чем сказать "в виндовсе дыра" - я долго не мог поверить что это так. потом проверил. результат - перед вами. там ДЫРА. как ни странно...
если сходу кидат ругать - обратите внимаение - точки-треугольники пашут как надо, лажают ТОЛЬКО линии. но лажают. я надеюсь - что кто нить мне скажет - а это вот ты идиот, позови glEnable(ВоЛшеБнаяКлюква) -и мне станет хорошо... хи-хик...
gkv311Постоялецwww8 мар. 20180:16#7
Lion007
я, конечно, понимаю, что нормальные люди с GENERIC GDI GL не работают - но у меня выбора нет.
мне иногда НАДО. и у меня НЕТ возможности получить нормальный контекст.
ну нету, правда...

А комментарии почему "надо" не будут?
Нет, я, конечно, не против, но программная реализация OpenGL от Microsoft из прошлого десятилетия (или позапрошлого?) - это просто тупик.
ХаусПостоялецwww8 мар. 20186:33#8
Lion007
> не влияет. ребята, поймите правильно. прежде чем сказать "в виндовсе дыра" - я
> долго не мог поверить что это так. потом проверил. результат - перед вами. там
> ДЫРА.

главное не забухай по этому поводу. :)

Lion007Постоялецwww8 мар. 20187:53#9
забухать - все-таки забухали :) по другому поводу, правда, но важен факт :)

что до прочего... функции, которые заполняют PIXELFORMATDESCRIPTOR - написаны самим майкрософтом :)

  PIXELFORMATDESCRIPTOR pfd ;
  memset(&pfd,0, sizeof(PIXELFORMATDESCRIPTOR));
  pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
  pfd.nVersion = 1;
  DescribePixelFormat(img.hdc(), pf, sizeof(pfd), &pfd);

читает полное описание формата. там заполнено ВСЕ, причем именно так, как есть. оно на то и Describe.

а зачем это все надо... 2 прикола :
1) должно работать по РДП - в ентом случае всегда затравливается GDI-grneric
2) периодически требуется вывалить на печать. дерьмо вопрос, в принципе, можно затравить рендер в текстуру - но см. пункт 1

да и вообще обидно...
видимо, придется вместо линий втыкать заглушку на квады в пиксель шириной :)

Правка: 8 мар. 2018 8:02

*Lain*Пользовательwww8 мар. 201811:58#10
Lion007
Привет, ламер007. Код лучше под спойлеры, а то читать тяжело, сразу расхотелось.
gkv311Постоялецwww11 мар. 20181:02#11
Lion007
1) должно работать по РДП - в ентом случае всегда затравливается GDI-grneric

Нет, только если пользователь выбрал систему, в которой не собирается пользоваться RDP вообще или 3D приложениями через RDP.
Такой проблемы нет с AMD Radeon (даже с непрофессиональными картами) и с Quadro (но не GeForce - NVIDIA хочет стричь деньги за свои профессиональные видеокарты); про Intel не знаю.

Хотя есть топики, которые описывают как запустить OpenGL приложение на GeForce через RDP манипулируя особенностями Windows.

2) периодически требуется вывалить на печать

Жуть... Создавать отдельный OpenGL контекст без фич, только для печати - сомнительное удобство.

А если позарез надо поддерживать software rendering - то для этого есть Mesa 3D; а также Angle, реализующий OpenGL ES 2.0 через Direct3D.
Но это, разумеется, актуально только для современного рендерера.
Если всё, что надо нарисовать, рисуется через glBegin()/glEnd(), то, наверное, это всё не актуально.

Правка: 11 мар. 2018 1:04

Lion007Постоялецwww11 мар. 201812:16#12
о! вот насчет месы - мысль интересная, спасибо!

/ Форум / Программирование игр / Графика

2001—2018 © GameDev.ru — Разработка игр