MrShoor
> Если чуть-чуть увеличить радиус у препятствий, то луч начнет пересекать то, что
> раньше не пересекал. Как этот момент обходится?
цель увеличения радиуса — именно сгенерить новые пересечения. представь себе эти две окружности увеличиваются, когда ты шагаешь малыми шагами по лучу.
arprog
> Демка будет?
в новой лиге path of exile предположительно будет много этой технологии
Suslik
> цель увеличения радиуса — именно сгенерить новые пересечения. представь себе
> эти две окружности увеличиваются, когда ты шагаешь малыми шагами по лучу.
Это я представляю. Я не понимаю как именно ты увеличиваешь этот радиус. Вот у тебя в текстуре XY - начало луча, Z - угол. В пикселе в R хранится дистанция на луче и в GBA нормаль - это единственное предрассчитанное пересечение. Откуда берутся эти самые новые пересечения?
MrShoor
> Откуда берутся эти самые новые пересечения?
пересечение хранится одно. но во время его расчёта радиус волокон увеличивается. короче, так:
float Grass::CastRay(vec3 origin, vec3 dir) { float extraRadius = 0.0f; for( float dist = 0; dist < 100.0f; dist += step) { extraRadius += spikiness; for( auto fiber : this->fibers) { float dist; if( length( origin + dir * dist - fiber.center) < fiber.radius + extraRadius) { return dist; } } } }
Suslik
> пересечение хранится одно. но во время его расчёта радиус волокон
> увеличивается. короче, так:
Погоди, так это не семплинг с 3д текстуры. Ты просто перебираешь все fibers чтоль? Тогда откуда O(1) тут?
Тогда откуда O(1) тут?
Ну так же два for-a :)
MrShoor
> Погоди, так это не семплинг с 3д текстуры.
Это предрасчет этой 3D текстуры.
Только там должно быть vec2 вместо vec3.
}:+()___ [Smile]
> Это предрасчет этой 3D текстуры.
> Только там должно быть vec2 вместо vec3.
да, так
}:+()___ [Smile]
> Это предрасчет этой 3D текстуры.
Оу, теперь я понял, спс. Интересный трюк.
Интересно.
Попробовал реализовать методику, и упёрся в несколько вопросов.
1) В какую сторону копать для устранения шума вокруг выдавленной геометрии? Если включить линейную фильтрацию для текстуры, выдавленные примитивы получаются окружёнными разноцветным контуром. Я попробовал написать свою фильтрацию: выбираю по 8 текстурным координатам, декодирую дальность и нормали, и уже декодированные значения фильтрую линейно. Получилось вот так:
Уже лучше, но всё равно очень плохо. При уменьшении диаметра травинок получается что-то подобное:
и шумит сильнее с отдалением от камеры.
То есть добиться тонких, ровных травинок, как в заглавном видео в статье, у меня пока не получилось.
2)
> там гораздо интереснее, как обходить ограничения алгоритма на паралелльные волокна, например.
Можно в общих чертах, как это сделано?
Я попробовал просто добавить смещение и увеличение радиуса с каждым шагом, и получилось что-то подобное:
Смещение приводит к очень сильным артефактам, и мне пока не понятно как с ними бороться.
Поигрался с увеличением радиуса без смещения, получил максимум вот такое:
Считаю, что скорость увеличения радиуса надо делать нелинейной. Однако независимо от скорости увеличения, я не могу получить тонкие травинки из-за обводов и разрывов.
3) Как покрасить травинки в разные цвета? Или у вас цвет один, но наложено SSAO?
Я покрасил в разные цвета, пробросив "номер" травинки через четвёртую компоненту текстуры, но тем самым оставил нормаль двухкомпонентной. По номеру уже выбираю цвет из палитры, поданной в юниформу.
Ещё есть мысль сделать "мультисемплинг", как делают в сглаженных демках на Shadertoy.
Но расчёт текстурных координат и прочего интерполированного для соседних фрагментов будет выглядеть тяжёлым и неуклюжим, а из-за низкого разрешения текстуры краевые эффекты вряд ли исчезнут.
VirtualVoid
> линейную фильтрацию для текстуры, выдавленные примитивы получаются окружёнными
> разноцветным контуром.
это обычная выборка чисто по UV, и текстура с мипмапами? не пробовал tex2Dgrad/SampleGrad/textureGrad? производные для него брать от неискажённых UV.
VirtualVoid
anti-aliasing можно запекать прямо в текстуру, для этого в предрасчёте я считаю не один луч на тексель, а, например, 16, при этом лучи выходят из точек, равномерно распределённых по текселю. проблем с такими контурами как у тебя у меня почему-то не было, так что я не знаю, как тебе это удалось. тебе надо определить, откуда именно приходит шум: это будет либо шум из-за нормали, либо из-за твоего способа окраски, так как он не интерполируется. я использую отдельную текстуру с запечённым albedo в точке пересечения, поэтому такой проблемы нет, так как она тоже интерполируется.
отдельную фильтрацию вместо линейной я делал только для координаты по углу, но в итоге и от неё отказался, так как линейная интерполяция поддерживается аппаратно.
на мипмапы я тоже забил, потому что направление по углу мипмаппится плохо и хотелось бы мипмаппить только пространственные направления. возможно, это проще всего сделать через массив двумерных текстур с мипами, а интерпооляцию между ними (слоями) делать вручную, но мне это не понадобилось, так как у нас камера фиксирована и можно настроить так, чтобы всегда был только один мип задействован (основной).
я также в итоге отказался от идеи с процедурной генерацией волокон, так как больно муторно к ним параметры руками подбирать. в итоге я сделал просто запекалку мешей: художники мне дают меш, я его запекаю примерно таким же алгоритмом.
пожалуй, самый значительный вклад в улучшение картинки дал алгоритм, который позволяет избавиться от тайлинга. я использую запечённую текстуру достаточно маленького размера и просто применяю этот алгоритм, чтобы избавиться от повторяемости: https://www.shadertoy.com/view/tsVGRd
вот так выглядит без него:
вот так с ним:
Suslik
охохо, с пофикшенным тайлингом просто отпадно
пара скриншотов текущей версии:
Тема в архиве.