Почему мой цвет исчезает, когда я включаю освещение в OpenGL? - PullRequest
25 голосов
/ 13 декабря 2011

Я занимаюсь разработкой графического приложения на C ++ с API OpenGL и GLUT.

Чтобы добавить освещение, я внес следующие изменения в матрицу вида модели:

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);

// Create light components.
GLfloat ambientLight[] = { 0.2f, 0.2f, 0.2f, 1.0f };
GLfloat diffuseLight[] = { 0.8f, 0.8f, 0.8, 1.0f };
GLfloat specularLight[] = { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat position[] = { 0.0f, 0.0f, 0.0f, 1.0f };

// Assign created components to GL_LIGHT0.
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);
glLightfv(GL_LIGHT0, GL_POSITION, position);

Я считаю, что освещение в основном работает, но цвета моих объектов исчезают. Все, что я вижу, это черно-белый силуэт моей общей фигуры.

Мне было интересно, почему это так?

Ответы [ 2 ]

30 голосов
/ 13 декабря 2011

Когда освещение включено, цвет вершины определяется не по цвету, установленному glColor или glColorPointer, а по текущим установленным цветам материала в сочетании с цветами источников света с использованием вычислений освещения.

Таким образом, чтобы изменить цвет объекта, вам нужно изменить настройку материала (который по умолчанию является диффузным серым материалом) перед рендерингом, используя функции glMaterial. По существу, существует соответствующий цвет материала для каждого из различных цветов освещения (GL_DIFFUSE, ...), а также некоторые дополнительные свойства для аппроксимации светоизлучающих материалов (GL_EMISSION) и контроля шероховатости материала (GL_SHININESS). Прочитайте некоторые вводные материалы по функциям освещения OpenGL, чтобы понять их работу.

Что вы можете сделать, чтобы быстро адаптировать ваш код от простого окрашивания к освещению (или включить свойства материала для каждой вершины), это использовать цветной материал. Вызвав glEnable(GL_COLOR_MATERIAL) и установив соответствующее отображение с помощью glColorMaterial, вы можете настроить OpenGL для изменения определенного цвета материала при каждом изменении текущего цвета вершины (с использованием glColor или glColorPointer).

20 голосов
/ 13 декабря 2011

Попробуйте glEnable(GL_COLOR_MATERIAL).

См. Общая ошибка OpenGL # 14 :

Тщательное включение цветного материала

Функция цветового материала OpenGL обеспечивает менее дорогой способ изменения параметров материала.При включенном цвете материала цвета материала отслеживают текущий цвет.Это означает, что вместо использования относительно дорогой процедуры glMaterialfv вы можете использовать процедуру glColor3f.

Ниже приведен пример использования функции цветового материала для изменения диффузного цвета для каждой вершины треугольника:

glColorMaterial(GL_FRONT, GL_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
glBegin(GL_TRIANGLES);
    glColor3f(0.2, 0.5, 0.8);
    glVertex3f(1.0, 0.0, 0.0);
    glColor3f(0.3, 0.5, 0.6);
    glVertex3f(0.0, 0.0, 0.0);
    glColor3f(0.4, 0.2, 0.2);
    glVertex3f(1.0, 1.0, 0.0);
glEnd();

Рассмотрим более дорогую кодовую последовательность, необходимую, если явно используется glMaterialfv:

GLfloat d1[] = { 0.2, 0.5, 0.8, 1.0 };
GLfloat d2[] = { 0.3, 0.5, 0.6, 1.0 };
GLfloat d3[] = { 0.4, 0.2, 0.2, 1.0 };

glBegin(GL_TRIANGLES);
    glMaterialfv(GL_FRONT,GL_DIFFUSE,d1);
    glVertex3f(1.0, 0.0, 0.0);
    glMaterialfv(GL_FRONT,GL_DIFFUSE,d2);
    glVertex3f(0.0, 0.0, 0.0);
    glMaterialfv(GL_FRONT,GL_DIFFUSE,d3);
    glVertex3f(1.0, 1.0, 0.0);
glEnd();

Если вы визуализируете объекты, которые требуют частых простых изменений материала, попробуйте использовать цветматериальный режим.Однако при включении режима цветного материала встречается распространенная ошибка.Когда цветной материал включен, OpenGL немедленно меняет цвета материала, контролируемые состоянием цветного материала.Рассмотрим следующий фрагмент кода для инициализации вновь созданного контекста рендеринга OpenGL:

GLfloat a[] = { 0.1, 0.1, 0.1, 1.0 };
glColor4f(1.0, 1.0, 1.0, 1.0);

glMaterialfv(GL_FRONT, GL_AMBIENT, a);
glEnable(GL_COLOR_MATERIAL); /* WARNING: Ambient and diffuse material latch immediately to the current color. */
glColorMaterial(GL_FRONT, GL_DIFFUSE);
glColor3f(0.3, 0.5, 0.6);

В каком состоянии будут находиться цвета переднего окружающего и рассеянного материала после выполнения фрагмента кода выше?Хотя программист, возможно, предполагал, что состояние окружающего материала будет (0.1, 0.1, 0.1, 1.0), а состояние рассеянного материала - (0.3, 0.5, 0.6, 1.0), это не совсем то, что происходит.

Полученное состояние рассеянного материала - это то, что и задумал программист,но результирующее состояние материала окружающей среды довольно неожиданно (1.0, 1.0, 1.0, 1.0).Как это случилось?Хорошо, помните, что режим цветного материала сразу начинает отслеживать текущий цвет при включении.Начальное значение для параметров цветного материала - GL_FRONT_AND_BACK и GL_AMBIENT_AND_DIFFUSE (возможно, не то, что вы ожидали!).

Поскольку включение режима цветного материала сразу начинает отслеживать текущий цвет, как окружающий, так и рассеянный материалсостояния обновляются до (1.0, 1.0, 1.0, 1.0).Обратите внимание, что эффект начального glMaterialfv потерян.Затем состояние цветного материала обновляется, чтобы просто изменить передний рассеянный материал.Наконец, вызов glColor3f изменяет диффузный материал на (0.3, 0.5, 0.6, 1.0).Состояние окружающего материала в конечном итоге становится (1.0, 1.0, 1.0, 1.0).

Проблема в приведенном выше фрагменте кода состоит в том, что режим цветного материала включен перед вызовом glColorMaterial.Режим цветного материала очень эффективен для эффективных простых изменений материала, но во избежание вышеуказанной ошибки всегда будьте осторожны, установив glColorMaterial, прежде чем включить GL_COLOR_MATERIAL.

...