romanshuvalov
Чёт я не поняла тогда. Ты что, просто конусы на экран рисуешь?
Battle Angel Alita
Какие вар анты?
Battle Angel Alita
Я рисую сцену. Во фрагментном шейдере, как обычно, рассчитывается цвет пикселя: выборка из текстуры, выборка из карты освещенности, то, сё. И после всего этого рассчитывается и применяется "степень влияния" находящихся на сцене параметрических конусов. Сами конусы специально нигде не рисуются.
romanshuvalov
> Я ж пишу, что для коротких полос сойдёт, но длинная неоновая полоса в половину
> комнаты - см. скриншот, их там две зелёных - так не сработает.
ncuxonaT
> а дальше считать вольюмлайт от неё, как от точечного источника
Не понимаю, как этот подход может дать результат как на вашей картинке.
А, просто расстояние до прямой же. И ограничить по длине. Да, это должно сработать, сегодня попробую.
romanshuvalov
по уму нужно находить точку не ближайшую к вью вектору, а дающую наибольшую яркость, иначе
может, у вас лучше выйдет
Обнаружен некоторый успех.
Вкратце: задача сводится к поиску расстояния между скрещивающимися прямыми - той, вдоль на которой расположен источник света, и той, которая проходит через камеру и пиксель.
Но мне в идеале нужно не само расстояние, а точка на светящейся линии, ближайшая к прямой направления взгляда.
Допустим, точка E - камера, вектор S - направление взгляда. Световая линия идёт из точки A в точку B. Я ищу такое k, что A + (B-A)*k будет ближайшей точкой к прямой, проходящей через E и параллельной S.
Воспользовавшись формулой расстояния от точки до прямой и опустив кое-какие ненужные вычисления (например, извлечение корня, я ведь ищу минимум функции, он же будет и минимумом квадрата функции) я внезапно получил относительно k параболу, вершина которой, как известно, лежит в -b/2a, даже не пришлось брать производную. После сворачивания длиннющей формулы получился вот такой удивительно негромоздкий код:
vec3 A; vec3 B; vec3 C = B-A; vec3 E; vec3 S; vec3 eas = cross(E-A, S); vec3 cs = cross( C, S); float k = dot( eas, cs) / dot( cs, cs); k = clamp( k, 0.0, 1.0); vec3 M = A + C*k; // искомая точка
Есть кое-какие артефакты, если залететь камерой внутрь, также не очень красиво выглядит с торца (можно замаскировать, тупо проверив скалярным произведением, не смотрим ли мы с торца, и подменить картинку обычной сферой). Но в целом работает.

Внутри - вот такое. Причину пока не знаю, явно неверно вычисляется М. Такой артефакт есть даже если убрать clamp() на k, т.е. сделать источник бесконечно длинным. Разбираться продолжу уже завтра.

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

Короче, простой способ борьбы с артефактами найти не удалось. Кроме того, даже в текущем виде и без отсечения по глубине шейдер достаточно тяжеловесный, вряд ли удастся поместить на сцену больше двух источников, даже если решить все проблемы. А гиперболоидных и сферических источников можно добавить суммарно 7-9 штук.
Так что обойдусь пока без линий, может, вернусь к этой теме позднее.
P.S. Куда статью написать, если соберусь? habr жив? dtf?
romanshuvalov
GPU Gems?
romanshuvalov
Есть такая техника для полупрозрачных как халфрез и апсемплинг
GLoom
> GPU Gems?
?
innuendo
Да, и это даже может сработать, но надо рендерить в отдельную текстуру + для каждой точки сохранять глубину, чтобы делать софт-depth-test. А значит я смогу сделать только ровно один источник. Максимум два (RG + BA), если их обесцветить. Короче, проблем от такого решения больше, чем пользы. Пробовал. (Но допускаю, что в некоторых случаях такое решение сгодится, например, при множества анимированных полупрозрачных объектов, висящих в воздухе и для которых не нужны трюки с depth test.)
romanshuvalov
ГПУ Джемс это выпуски статей про рендеринг
Тема в архиве.