Зеркальные огни на кубе в открытых окнах
В некоторых уроках, где вводится освещение, люди начинают с примера сферы, освещаемой всеми тремя типами источников света: рассеянным, рассеянным и зеркальным. Затем можно легко увидеть, например, выключив отдельные источники света, что окружающее излучение отвечает за равномерное освещение объекта, рассеянное излучение идет с определенного направления, и благодаря зеркальному освещению мы можем наблюдать яркое пятно на поверхности,
Я попытался повторить те же шаги на более простом примере - кубе, который пользователь может произвольно вращать. На самом деле я ожидал увидеть похожую картину: я предполагаю, что OpenGL должен в какой-то степени следовать правилам геометрической оптики, и, если указаны положения как источника света, так и камеры, на одном из них должно быть только одно светлое пятно. куб обращен, тот, который отражает источник света непосредственно на камеру.
Тем не менее, я мог получить только равномерно освещенные лица, а не яркое пятно. Итак, мой вопрос, возможно ли это получить? Забыл упомянуть, я использовал простейшую возможную триангуляцию - 2 треугольника на лицо. Другое дело, я использую OpenGL ES 1.1, так что никаких шейдеров.
3 ответа
Расчет освещения в OpenGL вычисляется для каждой вершины, а затем результат линейно интерполируется (возможно, с коррекцией перспективы) по пикселям каждой грани.
Это означает, что если вы моделируете куб с четырьмя вершинами, вы не сможете получить яркое пятно отражения в середине лица. Освещение граней куба всегда будет состоять только из двух градиентов: по одному для каждой из двух треугольных граней.
Для аппроксимации молнии на пиксель необходимо разделить грани на множество маленьких треугольников... или использовать другие методы: например, использовать "пиксельные / фрагментные шейдеры" для вычисления трюков на пикселную молнию или наложения текстуры подражать тому же.
Для объяснения фрагментных шейдеров на OpenGL ES см. http://www.learnopengles.com/android-lesson-three-moving-to-per-fragment-lighting/
Используя трюки с наложением текстур (обычно называемые подходом "наложение окружения"), легко даже эмулировать убедительные блестящие объекты, которые могут отражать окружающую среду, а не только источники света для каждого пикселя.
http://raksy.dyndns.org/torus.html - это демонстрация веб-холста, где блестящее отражение действительно вычисляется с помощью трюка с наложением текстур. На самом деле этот код вообще не зависит от какой-либо поддержки 3d и рисует треугольники, используя только 2d матрицы преобразования, которые предоставляет объект холста html5.
Как вы можете заметить, геометрия объекта очень грубая (каждое пятно на торе - всего 9 вершин), но отражение источника света определено, и вы даже можете увидеть искаженное отражение плиточного пола.
Есть некоторые проблемы с вашим примером.
Вы должны различать точечный источник света и направленный источник света. Вы не указали явно в своем вопросе, который используете (РЕДАКТИРОВАТЬ: вы получаете направленный источник света, если ваша 4-я координата источника света равна 0, в противном случае вы получаете точечный источник света)
Есть хорошая картина, показывающая разницу в этом вопросе
(с okino.com)
Если вы используете направленный источник света, то, конечно, все точки на одной стороне вашего куба будут иметь одинаковый расчет освещения и, следовательно, одинаковый результирующий цвет. Если вместо этого вы используете сферу, вы получите блики.
Если вы используете точечный источник света, то вы столкнетесь с проблемами из-за OpenGL (ES) - фиксированной модели освещения конвейера. Он рассчитал освещение каждой вершины. Так как вы используете только 5 разных вершин на одну сторону куба, вы снова получаете небольшие различия в освещении. Вы можете обойти это, используя шейдер освещения на пиксель или тесселяцию своего куба в меньшие треугольники.
Конечно, есть и ряд незначительных "ловушек", вам нужно убедиться, что ваши различные источники света (источники и типы) не излучают слишком много света, когда объединены, это испортит ваше освещение. Также убедитесь, что нормали установлены правильно.
Освещение сильно зависит от количества вершин, которые у вас есть для каждой стороны вашего куба. Поскольку вы не используете шейдеры, освещение рассчитывается для каждой вершины. Но вычисление зависит от нормали поверхности, которая ориентирована перпендикулярно грани и рассчитывается для каждой грани, означает 3 вершины. Нормы одинаковы для каждой вершины грани, поэтому интенсивность света для каждой вершины также одинакова, так что Вы не можете видеть никакого светового эффекта. Если вы правильно рассчитаете нормали, вы должны увидеть разницу в цвете разных сторон куба. Чтобы достичь некоторого пятна на одной стороне, вам нужно увеличить разрешение сетки каждой стороны куба, и вы должны применить соответствующий угол для конуса прожектора, или вы минимизируете расстояние прожектора до куба.
n1 n2
/ /
/ /
v1 ---------- v2
| /
| /
| n3 /
| / /
|//
|
v3 v4
Посмотрите на этот хороший учебник. Это объясняет основной механизм в очень понятной форме: http://www.opengl-tutorial.org/beginners-tutorials/tutorial-8-basic-shading/