samrrr
> https://learnopengl.com/Advanced-Lighting/SSAO смотри.
ssao — это вообще фейк, который не может дать правильного результата в общем случае, так как не учитывает окклюжена от тонких фич. например, если двугранный угол образован тонкой стенкой, то SSAO её вообще не "заметит", хотя свет эта стенка должна блокировать и HBAO в этом случае отработает корректно. однако, SSAO проще реализуется, проще настраивается и не даёт false occlusion артефактов.
> А может не надо? Смысла сэмплить больше 5% от размера экрана вообще мало.
продвинутые алгоритмы вроде LSAO и SSGI семплят вообще весь экран. семплинг 5% экрана даёт типичный вид дешёвого SSAO.
> Коэффициенты чтобы преобразовать 0.5 на плоскости и 0.25 в углу в 1 и 0.5 соответственно.
это надо исправлять нормально, а не подгоночными коэффициентами.
> Это правильный результат, при неправильной реализации. Просто случайно получилось как надо.
я не вижу с ходу, что в ней неправильное
samrrr
SSAO очень грубый. И плохо работает с объемами. Может съесть целиком маленький объект. Совсем не рабочий вариант.
Всем привет!
Suslik
Вот и я проснулся =)))
Засиделся вчера до утра, потом начал читать как делается атмосферик скаттеринг, сошел с ума и уснул )))
Но это позже. Друзья, цель не получить АО, я не пишу игру, не делаю мегапроект, цель разобраться как работает и реализовать самому, понятно что в ассет сторе уже давно всё есть. Очень признателен всем, кто подсказывает.
Очень хочется избавиться от двух циклов и убрать странные коэффициенты, добавить учёт нормали.
Блин, а я то вчера полночи просидел и пытался понять почему именно такие коэффициенты (((
Господа, вы не могли бы пожалуйста объяснить, как работает вот эта строчка:
float angle= atan2(-sampleDirVS.z, length(sampleDirVS.xy));
Не понимаю, что это значит.
Пробовал даже нарисовать, но всё равно непонятно.
sampleDirVS это же по сути трёхмерный вектор между текущей точкой (в VS) и точкой откуда семплим.
Никак не получается добить и получить корректный результат.
Убрал второй цикл, убрал стремные коэффициенты. Пока результат получается какой-то пересвеченный.
float occlusion = 0.0; for (int i = 0; i < directionsCount; i++) { deltaUV = mul(deltaRotationMatrix, deltaUV); float horizonAngle = -2.0; for (int j = 0; j < stepsCount; j++) { float2 sampleUV = uv + j * deltaUV; float3 sampleVS = screenToView(sampleUV); float3 sampleDirVS = sampleVS - pointVS; float angle= atan2(-sampleDirVS.z, length(sampleDirVS.xy)); if (angle > horizonAngle) { horizonAngle = angle; } horizonAngle = max(horizonAngle , angle); } occlusion += sin(horizonAngle) * attenuation; } occlusion = 1 - occlusion / directionsCount;
KaronatoR
> float angle= atan2(-sampleDirVS.z, length(sampleDirVS.xy));
Чем бы не был sampleDirVS, после этой строчки в angle отложится угол между вектором и плоскостью xy, причём со знаком - отклонение в сторону +z даст отрицательный угол, в сторону -z даст положительный.
Delfigamer
Огромное спасибо!
Блин ещё чертёж крутой такой, вау.
То есть в моём случае у нас плоскость XY это плоскость экрана.
Но мы всё считаем во вью спейсе. По идее у нас картинка тогда будет меняться при движении камеры.
Что-то не то.
KaronatoR
> То есть в моём случае у нас плоскость XY это плоскость экрана.
по идее результат никак не должен зависеть от того, относительно какой плоскости ты считаешь горизонт. потому что задача корректного AO — посчитать приближённое решение уравнение рендеринга, а то, что для этого интеграл представляется как сумма по направлениям с горизонтами — это всего лишь средство, которым он считается. то есть от выбора горизонта разницы быть не должно. по идее плоскостью горизонта можно считать как локальную нормаль поверхности так и направление взгляда — если остальные формулы правильные, то разницы быть не должно. но это надо очень аккуратно считать, чтобы плотность направлений по лучам тоже равномерная была итп. обычно в реализациях не парятся и просто берут в качестве плоскости горизонта направление взгляда (плоскость xy твоего sample dir), тогда высота будет в z.
KaronatoR
> По идее у нас картинка тогда будет меняться при движении камеры.
по идее если всё рассчитано правильно, то наоборот результат не должен меняться при движении камеры, потому что сам AO аппроксимирует ту часть уравнения рендеринга, которая не зависит от направления взгляда. однако, в скринспейсе из-за false occlusion'а как минимум будет немного разный результат. но если falso occlusion'а нету (то есть никакие объекты друг друга не загораживают и в экран попадает вся сцена), то при движении камеры абсолютно никакого движения AO не должно быть. на самом деле, правда, создать сцену, для которой выполнялись бы эти условия — само по себе не так-то просто. но оно работает, например, для достаточно гладких ландшафтов.
KaronatoR
> Очень хочется избавиться от двух циклов и убрать странные коэффициенты,
> добавить учёт нормали.
я так и не понял, от каких двух циклов ты хочешь избавиться. циклы по углу луча и по точкам на луче всё равно оба нужны, без них ты ничего не посчитаешь. а нормали в правильном AO быть не должно, потому что вся информация о геометрии хранится в глубине. ты по идее можешь инициализировать горизонт не нулём, а плоскостью нормалмапы, если она отличается от нормали глубины, но это только микрорельеф AO добавит, если он есть. в твоём случае с кубами и flat shading'ом нормаль фигурировать не должна.
KaronatoR
>Убрал второй цикл, убрал стремные коэффициенты. Пока результат получается какой-то пересвеченный.
Если значение цвета (при ограниченном самплинге малого радиуса) на боковой и задней грани разный, то это неправильный AO.
Suslik
>это надо исправлять нормально, а не подгоночными коэффициентами.
Исправлять надо такие вещи которые реально раздражают в игре: Например в POE босс призывает 100 мобов, игра судорожно прогружает модельки, повисает на 3 сек, за это время босс уже тебя успел чем-то убить. Асинхронная загрузка? Она вроде как есть, но босс серавно тебя уже убил.
Есть ещё много примеров того, что реально НАДО исправлять, но никак не исправляется годами.
С помощью этих коэффицентов получается картинка идентичная, а кое в чём и лучшая, чем в варианте с полусферой. Как минимум теперь есть хоть какой-то рабочий вариант, и известно в чём проблема.
>продвинутые алгоритмы вроде LSAO и SSGI семплят вообще весь экран. семплинг 5% экрана даёт типичный вид дешёвого SSAO.
Только вот прямоугольник в котором рисует рендер ограничен и не даёт адекватно отразить AO.
И при семплинге на весь экран это начинает проявляться не только у края, а и далеко от него. Получается, что цвет поверхности меняется при повороте камеры, что выглядит крайне странно. Вдобавок сэмплить на весь экран это не слишком быстро а в постпроцессинге вряд ли только AO.
Не правильные AO: #95 #106 #110 #112
То каким должен быть результат: #123 #130
Тестить лучше при радиусе AO примерно в радиус сферы. Потом, когда будет готов правильный результат, уже менять параметры.
lookid
>SSAO очень грубый.
Зато простой, и прочитав о нём можно понять, что не так с вроде бы хорошими вариантами AO. Я же не предлагаю его реализовывать.
Про HBAO у меня ссылки нет, а про SSAO есть.
samrrr
> Исправлять надо такие вещи которые реально раздражают
вроде зарплат учителям, системы образования в стране и произвола чиновников. лол, только какое это всё отношение имеет к треду-то? да и ко мне лично, я как бы графику программирую, а не работу с ресурсами и не эффекты.
> С помощью этих коэффицентов получается картинка идентичная, а кое в чём и лучшая, чем в варианте с полусферой
в технических эффектах вроде модели освещения картинка не может быть лучше или хуже. она может быть правильной или неправильной. так вот шлёпанье каких попало коэффициентов 100% сделает её неправильной. особенно отстойно, если ты долго работаешь с таким рендером, привыкаешь к нему и он начинает тебе казаться корректным, а ещё художники начинают под него адаптировать ассеты и потом, когда кто-то такой левый коэффициент, наконец, где-то заметит, выпиливать его уже будет слишком поздно и больно, потому что все ассеты уже сделаны с его учётом.
> Не правильные AO: #95 #106 #110 #112
> То каким должен быть результат: #123 #130
единственный скриншот AO в этом треде, близкий к правильному (я не могу сказать, правильный ли он, без тестов) — это https://gamedev.ru/code/forum/?id=251828&page=7&m=5176838#m92
Suslik
samrrr
Очень благодарен вам обоим за помощь, тред не забросил, работаю, тестирую.
samrrr
То о чём ты говоришь - это достичь результат любой ценой и не париться. У меня совершенно другая задача: разобраться, понять. Делаю для души - не по работе, не на продажу.
Просто так два цикла я оставить не могу, это значит что я не справился и не разобрался с темой.
Suslik
Ты прав, та картинка максимально близка к нужному результату, но есть два вопроса:
1. Там никак не учитывается направление нормали, как бы это добавить?
2. Она "недосвечена". Боуовые и задняя грани не белые. Это не дело.
UPD: и ещё важный момент, про который говорил samrrr, на этой картинке разная освещённость у задней и передней стенок, что указывает на ошибку в алгоритме.
> я так и не понял, от каких двух циклов ты хочешь избавиться
Результат https://gamedev.ru/code/forum/?id=251828&page=9&m=5176883#m129 был получен с использованием кода отсюда: https://gamedev.ru/code/forum/?id=251828&page=9&m=5176898#m130. Обрати внимание, там два цикла семплирования.
Сейчас я вернулся к коду с синусами, код выглядит примерно вот так:
float occlusion = 0.0; float dist = 0; for (int i = 0; i < directionsCount; i++) { deltaUV = mul(deltaRotationMatrix, deltaUV); float horizonAngle = -2.0; for (int j = 0; j < stepsCount; j++) { float2 sampleUV = uv + j * deltaUV; float3 sampleVS = screenToView(sampleUV); float3 sampleDirVS = sampleVS - pointVS; float angle = (PI / 2.0) - acos(dot(normalVS, normalize(sampleDirVS))); if (horizonAngle < angle) { horizonAngle = angle; dist = length(sampleDirVS); } horizonAngle = max(horizonAngle , angle); } occlusion += max(0, sin(horizonAngle)) / (0.5 * exp(dist / 2.0) + 0.1); }
С функцией затухания пока играюсь, но результат получается почему-то пересвеченный. Не хватает темноты в щелях и на углах.
К этому коду вернулся потому что его хотя бы понимаю.
Текущий результат:
Вообще алгоритм не такой сложный, крайне удивлён что я так буксую на ровном месте ((
KaronatoR
> 1. Там никак не учитывается направление нормали, как бы это добавить?
я уже писал об этом в предыдущем посте, ты уверен, что его читал?
> 2. Она "недосвечена". Боуовые и задняя грани не белые. Это не дело.
они не белые, потому что ты находишься внутри бокса. там вообще нет открытых плоскостей, все поверхности затенены стенками куба, поэтому никакая поверхность быть белой не должна. тестируй на открытой сцене, где фон бесконечно удалён.
> UPD: и ещё важный момент, про который говорил samrrr, на этой картинке разная
> освещённость у задней и передней стенок, что указывает на ошибку в алгоритме.
это свидетельствует о том, что задняя стенка затенена четырьмя непосредственно прилегающими гранями, а боковые стенки — тремя. правильное (не скринспейс) решение в твоей сцене внутри куба с бесконечным радиусом и без falloff — вообще чёрная сцена, потому что внутрь куба свет попадать не должен. но тут скринспейс нам играет на руку и свет всегда попадает хотя бы из-за камеры.
я не понимаю, чего ты пытаешься добиться, потому что все результаты после https://gamedev.ru/code/forum/?id=251828&page=7&m=5176838#m92 стали хуже. я так и не вижу, что именно ты в нём пытаешься исправить. я проверил в том скриншоте пипеткой значения в углах и на рёбрах, они примерно совпадают с тем, что должно быть, но чтобы сказать более точно, надо делать более "тепличные" условия, когда в кадр не попадает ничего кроме той фичи, которую ты исследуешь — то есть камера ставится так, чтобы в ней не было ничего кроме угла, например, и вместо цвета выводится величина по типу:
outColor = (abs( occlusion - 0.25) < 0.01f) ? vec4( 0.0f, 1.0f, 0.0f, 1.0f) : vec4( occlusion);
таким образом ровно в углу должна появиться малюсенькая зелёная область, которая там должна устойчиво находиться, если вращать камеру итп.
Если за 3 дня не смог сделать. То тупа выучи готовое и двигайся дальше. Ты не сможешь переломить кривую забывания.
https://github.com/search?q=hbao
https://github.com/Kryptexas/UE4-GameWorks-4.19.2
Suslik
>единственный скриншот AO в этом треде, близкий к правильному (я не могу сказать, правильный ли он, без тестов) — это https://gamedev.ru/code/forum/?id=251828&page=7&m=5176838#m92
Это уже финальный результат, код создавший его не правильный, но выяснится это только если куб на плоскость заменить. Дабы не делать десяток сцен, легче ограничить радиус сэмплов чтобы видеть сразу несколько нужных использований.
>они не белые, потому что ты находишься внутри бокса.
Нифига не от этого. Неправильность потому, что полусфера направлена не туда. Не удивительно, ведь нормаль не используется.
>в технических эффектах вроде модели освещения картинка не может быть лучше или хуже. она может быть правильной или неправильной. так вот шлёпанье каких попало коэффициентов 100% сделает её неправильной. особенно отстойно, если ты долго работаешь с таким рендером, привыкаешь к нему и он начинает тебе казаться корректным, а ещё художники начинают под него адаптировать ассеты и потом, когда кто-то такой левый коэффициент, наконец, где-то заметит, выпиливать его уже будет слишком поздно и больно, потому что все ассеты уже сделаны с его учётом.
Коэффициенты взяты не с потолка, а так, чтобы выдавать тот-же эффект что и при использовании полусферы. Предложенный мной вариант выдаёт тот-же результат, что и 100% корректный HBAO.
И тут не создание HBAO для комманды в 100 человек, тут просто создание HBAO.
Тема в архиве.