glBindTexture не работает

#c #opengl #mfc

#c #opengl #mfc

Вопрос:

Я пытаюсь нарисовать несколько простых трехмерных прямоугольных призм, но glBindTexture, похоже, не работает должным образом.

У меня есть N количество «фрагментов», у каждого из которых есть имя материала.

Я перебираю каждый фрагмент, нахожу его текстуру на основе названия материала, вызываю glBindTexture, затем рисую фрагмент. Однако, похоже, что если у меня есть несколько фрагментов с одинаковым названием материала, только первый из них рисуется текстурой, а остальные просто белые.

Буду признателен за любую помощь.

Вот код:

Инициализация OpenGL:

 static PIXELFORMATDESCRIPTOR pfd =
{
    sizeof(PIXELFORMATDESCRIPTOR),
    1,
    PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
    PFD_TYPE_RGBA,
    32, // bit depth
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    16, // z-buffer depth
    0, 0, 0, 0, 0, 0, 0,
};

GLfloat light_pos1[] = {0.0f, 0.0f, 15.0f, 1.0f};
GLfloat light_ambient[] = {1.0f, 1.0f, 1.0f, 1.0f};

// Get device context only once.
hdc = GetDC()->m_hDC;

// Pixel format.
m_nPixelFormat = ChoosePixelFormat(hdc, amp;pfd);
SetPixelFormat(hdc, m_nPixelFormat, amp;pfd);

// Create the OpenGL Rendering Context.
hrc = wglCreateContext(hdc);
wglMakeCurrent(hdc, hrc);

//texture
glEnable(GL_TEXTURE_2D);

//Setup:
glClearColor(0.5f, 0.5f, 0.5f, 0.0f);
glClearDepth(1.0f);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

//lighting
glLightfv(GL_LIGHT0, GL_POSITION, light_pos1);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);

// Send draw request
OnDraw(NULL);
  

загрузка текстуры

 glGenTextures(1, amp;texture);
glBindTexture(GL_TEXTURE_2D, t.texture);

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 256, 256, GL_RGB, GL_UNSIGNED_BYTE, data);
  

Затем код чертежа:

 glPolygonMode(GL_FRONT_AND_BACK, GL_FLAT);

for(int i = 0; i < mPieces.GetCount(); i  )
{
    C3DPiece p = mPieces.GetAt(mPieces.FindIndex(i));

    if(p.visible)
    {
        //GetTextureForMaterial finds the texture id based on the "piece"'s material name
        //have checked this and it is always returning a valid id (>0)

        GLuint tex = GetTextureForMaterial(p.material);

        glBindTexture(GL_TEXTURE_2D, tex);

        glBegin(GL_QUADS);
        glNormal3f(..., ..., ...);
        glTextCoord2f(..., ...);
        glVertex3F(..., ..., ...);
        glTextCoord2f(..., ...);
        glVertex3F(..., ..., ...);
        glTextCoord2f(..., ...);
        glVertex3F(..., ..., ...);
        glTextCoord2f(..., ...);
        glVertex3F(..., ..., ...);
        glEnd();
    }
}
  

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

1. Я действительно не могу вам помочь, не зная, какой код составляет «…»

2. The … это просто параметры, указывающие, какого размера рисовать фрагменты. Блок между glBegin() и glEnd() фактически повторяется 6 раз, чтобы нарисовать 6 разных граней призм. Я опустил остальные 5, чтобы упростить задачу.

3. Вы проверяли значение «tex» в каждом цикле? Не могу придумать никакой другой возможной проблемы прямо сейчас.

Ответ №1:

Нет такой вещи, как инициализация OpenGL (кроме настройки контекста). Все, что вы делаете в коде «инициализации», относится либо к функции рендеринга, либо к коду загрузки текстуры:

Все следующее семантически относится к пути визуализации. OpenGL — это конечный автомат, и, как и все конечные автоматы, вы приводите его в надлежащее начальное состояние перед выполнением какой-либо работы.

 //texture
glEnable(GL_TEXTURE_2D);

//Setup:
glClearColor(0.5f, 0.5f, 0.5f, 0.0f);
glClearDepth(1.0f);
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

//lighting
glLightfv(GL_LIGHT0, GL_POSITION, light_pos1);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
  

В вашем загрузчике текстур у вас есть это:

 glGenTextures(1, amp;texture);
glBindTexture(GL_TEXTURE_2D, t.texture);
  

Либо это опечатка, либо сгенерированное имя текстуры не попадает в текстуру ‘t.’.

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

1. Я думаю, что настройка модели тени, настройка функции глубины… на самом деле это относится не к пути визуализации, а к процедуре инициализации. Хотя (или потому, что) GL является конечным автоматом, вы можете предположить, что состояния останутся их значениями, если вы сами их не измените. Не обучайте новичков настраивать весь конвейер каждый раз, когда они рисуют объект.

2. @Christian: В любом современном пути визуализации функция глубины будет изменяться довольно часто. Например, при выполнении раннего Z-прохода вы сначала отрисовываете сцену в буфер глубины только в glDepthFunc(GL_LESS); затем все последующие проходы отрисовки выполняются с отключенной записью глубины и glDepthFunc (GL_EQUAL). Также не забывайте, что ваша программа может предоставлять какой-то механизм плагинов или скриптовый доступ к OpenGL (просто взгляните на Blender). В этом случае плагины / скрипты могут оставить контекст OpenGL в состоянии, неизвестном вашей программе. Единственный способ справиться с этим — всегда устанавливать нужное вам состояние!

3. @datenwolf Вот почему я сказал «если вы их не измените», имея в виду любую функцию доступа к OpenGL в вашей программе. Конечно, вы всегда должны быть в курсе частей вашей программы, которые изменяют состояние GL (включая плагины и т.п.), и я предполагаю, что в своем приложении он знает об этом.

4. @Christian: И да, я обучаю новичков настраивать весь конвейер для каждой итерации рендеринга. В долгосрочной перспективе это единственный правильный способ использовать OpenGL. Как только вы вводите HUD, преобразование в текстуры, методы многопроходного рендеринга и т.д., Вам неизбежно придется это делать в любом случае. Попытка установить определенные состояния на выделенной фазе инициализации практически бесполезна.

5. @datenwolf Хорошо, я вижу долгосрочный смысл в вашей идее, вы, вероятно, правы.

Ответ №2:

Я думаю, что я это исправил.

Кажется, была реальная проблема с файлом текстуры (.RAW images), и он отображался белым вместо цвета / рисунка, который он должен был иметь.

Я снова протестировал с меньшим количеством материалов (3 вместо 3663), и, похоже, все работает нормально.