Отложенное освещение | Точечные источники света с помощью кругов

Я реализую механизм отложенного освещения в своем графическом движке OpenGL, следуя этому учебник. Работает нормально, у меня с этим проблем нет.

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

Я сомневаюсь в эффективности этого метода, что приводит меня к моему первому вопросу:

Не лучше ли было бы нарисовать круг, изображающий световую сферу?

Сфера всегда выглядит на экране как круг, независимо от того, с какой точки вы на нее смотрите. Задача состоит в том, чтобы определить позицию на экране и масштаб круга. Этот метод будет иметь 3 преимущества:

  • Нет проблем с cullface
  • Нет проблемы с положением камеры в световой сфере
  • Гораздо эффективнее (количество вершин сильно уменьшено + нет трафаретного теста)

Есть ли у этого метода недостатки?

Мой второй вопрос касается реализации упомянутого метода. Положение центра кругов можно было легко вычислить, как всегда:

vec4 screenpos = modelViewProjectionMatrix * vec4(pos, 1.0);
vec2 centerpoint = vec2(screenpos / screenpos.w);

Но теперь как рассчитать масштаб полученного круга? Он должен зависеть от расстояния (от камеры до источника света) и как-то от вида в перспективе.


person user3234792    schedule 21.02.2014    source источник
comment
сфера не будет выглядеть как идеальный круг, если вы используете перспективную проекцию, кстати. Вы можете сделать быстрый рисунок того, что происходит, когда вы проецируете сферу на поверхность в перспективе, чтобы увидеть, что в большинстве случаев это не будет круг.   -  person Pavel Beliy    schedule 21.02.2014
comment
Ты прав. Тем не менее, при умножении радиуса на 1,2 при угле перспективы 45° этого было бы достаточно.   -  person user3234792    schedule 21.02.2014


Ответы (2)


Я не думаю, что это сработает. Смысл использования сфер в том, что они используются как световые объемы, а не просто круги. Мы хотим применить освещение к тем полигонам сцены, которые находятся внутри светового объема. По мере рендеринга сцены в буфер глубины записывается. Эти данные используются на этапе рендеринга объема света для правильного применения освещения. Если бы это был просто круг, у вас не было бы способа узнать, должны ли А и С быть освещены или нет, даже если бы круг был спроецирован на правильную глубину.

введите здесь описание изображения

person Arttu Peltonen    schedule 21.02.2014
comment
Суть отложенного затенения состоит в том, чтобы сначала визуализировать сцену в несколько текстур, содержащих данные для каждого пикселя (положение, цвет, нормаль...). Затем при постобработке отключается буфер глубины и вычисляются световые компоненты всех пикселей. Круг или сфера, не имеет значения, что использовать, главное, чтобы они покрывали пиксели. - person user3234792; 21.02.2014
comment
Это неверно, буфер глубины запись отключен, но проверка глубины еще активна, например: Configure the stencil operation for the front facing polygons to decrement the value in the stencil buffer when the depth test fails but to keep it unchanged when either depth test or stencil test succeed. Значит буфер глубины читается, но значения не обновляются на шаге светового объема. - person Arttu Peltonen; 21.02.2014
comment
Я знаю, что именно так они делают это в туториале, чтобы решить проблему cullface. Тем не менее, это не так в моей реализации. Я не использую трафаретный тест. Как упомянул Павел Белый, я мог бы с тем же успехом отрендерить плоский четырехугольник, заполняющий экран. Все пиксели, покрытые этим квадратом, проходят через шейдер освещения, глубина не проверяется. - person user3234792; 21.02.2014
comment
Подумайте об этом так: если вы просто освещаете все в области круга экранного пространства, вы, по сути, отбрасываете длинный конус света в сцену и освещаете все, что находится внутри этого конуса. Это не то, что вам нужно, потому что ваши точечные источники света имеют трехмерное положение в сцене, и вы хотите освещать объекты рядом с этой точкой. Если у вас есть просто круг экранного пространства, вы в конечном итоге осветите вещи, которые находятся впереди или позади трехмерного местоположения источника света. - person Arttu Peltonen; 22.02.2014
comment
Ключевое предложение находится в конце вашей первой ссылки (урок 36): The second problem is that the bounding sphere doesn't really bound the light and sometimes objects that are outside of it are also lit because the sphere covers them in screen space so we calculate lighting on them. Это то, с чем вы бы застряли, если бы использовали только круг. - person Arttu Peltonen; 22.02.2014
comment
Если вы посмотрите на первое изображение Урока 36, сферы также применяют освещение к фону, хотя там ничего нет! Вы, вероятно, понимаете, почему это явно неверно — свет должен быть виден только на поверхностях. Это потому, что шаг буфера трафарета, который будет обрабатывать это, еще не реализован там. А с кругом не получится. - person Arttu Peltonen; 22.02.2014
comment
Первая картинка Т. 36 — это всего лишь визуализация ограничивающих сфер. Это не фактическое освещение. Однако я должен признать, что вы правы. При реализации трафаретного теста проверяется глубина, и это большое преимущество ограничивающих сфер + трафаретный тест. Теперь я понимаю, почему многие люди используют эту технику. - person user3234792; 22.02.2014

Я не читал все это, но я думаю, что понял общую идею этого метода.

  1. Не сильно поможет. У вас все еще будут проблемы, если вы переместите камеру так, чтобы круг был за ближней плоскостью - в этом случае ни один из фрагментов не будет генерироваться, а свет "исчезнет"

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

  3. Для меня это выглядит как преждевременная оптимизация... Я бы, конечно, просто рендерил весь screenquad и делал затенение почти как обычно, не беспокоясь о каких-то особых случаях. Не забывайте, что все манипуляции с состоянием opengl и дополнительные операции отрисовки также приведут к накладным расходам, и здесь не ясно, какая из них будет превосходить другую.

  4. Вы забыли сделать перспективное деление здесь

  5. Самый простой способ вычислить масштабирование - преобразовать точку на поверхности сферы в экранные координаты и вычислить длину вектора. Очевидно, это должна быть точка на границе экранного пространства.

person Pavel Beliy    schedule 21.02.2014
comment
1. Ты прав, я забыл об этом. В таком случае вам придется визуализировать квадрат экрана. - person user3234792; 21.02.2014
comment
2. Коэффициент затухания на границе световой сферы настолько низок, что близок к нулю. Вы бы этого не увидели. - person user3234792; 21.02.2014
comment
3. Экран-четверка на каждый свет? Скажем, с 20 огнями? звучит экспансивно по отношению к прохождению пикселей, затронутых светом. - person user3234792; 21.02.2014
comment
4. Опять же, вы правы. На самом деле я не знал об этом, так как вершинный шейдер делает это автоматически. я отредактирую это - person user3234792; 21.02.2014
comment
5. Понял. Но как определить точку на границе экранного пространства? - person user3234792; 21.02.2014
comment
3: нет, не для каждого источника света... просто создайте единый массив, скажем, до 20 координат источников света и выполните расчет затенения в цикле for - person Pavel Beliy; 21.02.2014
comment
5: это очень просто и требует немного тригонометрии. Идея состоит в том, чтобы построить треугольник между положением камеры, центром сферы и точкой на поверхности, которую нам нужно найти. Этот треугольник прямоугольный, с углом 90 ° в точке касания (луч глаза в этой точке касается поверхности). Мы знаем 2 стороны треугольника, этого достаточно, чтобы вычислить все его углы. Затем вы строите вектор из центра сферы, который имеет длину радиуса этой сферы и лежит под правильным углом к ​​вектору центра камеры-сферы. - person Pavel Beliy; 21.02.2014
comment
3: Это еще один способ сделать это (передача всех источников света сразу в шейдер). Для кого-то это может быть лучше, в моей ситуации будет лучше отдельное светопропускание. - person user3234792; 21.02.2014
comment
5: Удивительно, это звучит логично. Я бы проголосовал за вашего автора, но мне не хватает реппоинтов. Это еще не фактическое решение. Вы собираетесь редактировать его с помощью этого обсуждения? Каков общий способ сделать это? - person user3234792; 21.02.2014