/A\
>Я ожидал что большее переиспользование индексов и типа мешлеты даст лучший результат.
а что значит мешлеты ? речь про мешь шейдеры?
Andrey
> а что значит мешлеты ?
Как мешлеты, но старым способом.
Проверил на мобилках, так там вершинный кэш всегда почти на максимум используется, а когда доходит до однопиксельных треугольников еще и интерполяция аттрибутов отключается.
Заодно проверил как работает IndirectDraw.
На десктопах все одинаково. На мобилках намного интереснее, на Adreno 505 indirect в 2 раза медленее, на Mali G610 indirect в 1.5 раза быстрее, на Mali T830 и G57 не работает firstInstance в indirect maxDraw=1, на Adreno 660 и PowerVR BXM одинаково.
В целом на свежих мобилках можно сделать GPU-driven подход.
Хочу рисовать квадраты в через фрагментный шейдер, чтоб не через компьют, но треугольниками получается лишние потоки на границе треугольников. Решил обрезать треугольник до квадрата через gl_ClipDistance, а в итоге он отрисовался как квадрат из 2х треугольников с helper invocation посередине, да как так то?
Если обрезать через буфер глубины, то также. Похоже на какую-то оптимизацию от NV, где железо может рисовать только треугольники.
/A\
> Хочу рисовать квадраты в через фрагментный шейдер
А точки большого размера пробовал?
}:+()___ [Smile]
> А точки большого размера пробовал?
Забыл про них)
Точки не разбиваются на треугольки.
А как делают отражения для множества мелких источников света?
Например фонари на мокром асфальте/воде. Нужно проверить что из каждой точки виден источник света и нужно как-то ограничить перебор всех источников света. Для воды это сделать сложно, так как рябь дает всевозможные углы. Reflection probe может потерять мелкие источники.
/A\
> фонари на мокром асфальте/воде
Для плоских отражающих поверхностей рендер в текстуру чем плох?
Mikle
> > фонари на мокром асфальте/воде
> Для плоских отражающих поверхностей рендер в текстуру чем плох?
Я про спекулярные отражения, тут рендер в текстуру не поможет. И где ты видел плоский асфальт? )

/A\
> спекулярные отражения, тут рендер в текстуру не поможет
Отрендеренную текстуру выводить с бампом, причём, чем сильнее бамп, тем меньше заметно отклонение от плоскости, весь асфальт на данной картинке можно будет считать плоским. Можно сделать Френель, зависимый от нормали.
Mikle
Ты про планарные отражения? Они же для зеркал.
Тут даже рендер в текстуру не нужен, по BRDF находится конус в котором могут быть отражения, нужно только получить все источники света в этом конусе и сделать это для каждого пикселя.
В киберпанке над таким долго мучались и только с RTX смогли сделать нешумящие отражения.
Посмотрел еще киберпанк, там от дальних источниках вообще нет спекуляра. А от рекламных щитов аж 2 света - отражение по SSR/RTX и лайт проба как точечный источник.
В RTX отражениях на слишком дифузных поверхностях свет накапливается очень долго, а вдвижении шумный.
В общем думаю смогу сделать намного лучше и быстрее, если заранее пометить большие отражающие поверхности (обычно их 1-2).
innuendo
> Кад делаешь .... Очень интересно
Как здесь (glsl/vulkan) можно грамотно обойтись без while, который, естественно, напрочь всё лочит зараза... Поставил пока что тройную проверку, ну типа если уж с третьего раза не получилось - тогда пока...
uint index = atomicCompSwap(selBuffer[customIndex].counter, 0, 0xffffffff); if( index == 0) { index = atomicAdd( selBuffer[0].counter, 1) + 1; atomicExchange( selBuffer[customIndex].counter, index); } else { //while(index == 0xffffffff) // index = atomicAdd(selBuffer[customIndex].counter, 0); if ( index == 0xffffffff) index = atomicAdd( selBuffer[customIndex].counter, 0); if ( index == 0xffffffff) index = atomicAdd( selBuffer[customIndex].counter, 0); if ( index == 0xffffffff) return; }
смысл в чём, в первой строчке я блокирую поле, выставляя туда что угодно кроме ноля (0xffffffff), потом выставляю этому полю нормальный индекс (если он до этого не был выставлен и был нулём), ну а если он не ноль уже был, тогда пытаюсь его прочитать, но засада в том, что в это время там может быть ещё 0xffffffff...
THE_MASTER
> Как грамотно обойтись без while
uint index = atomicCompSwap(selBuffer[customIndex].counter, 0, 0xffffffff);
if(index == 0) {
// Мы получили блокировку
index = atomicAdd(selBuffer[0].counter, 1) + 1;
atomicExchange(selBuffer[customIndex].counter, index);
} else {
// Читаем значение с барьером
index = atomicAdd(selBuffer[customIndex].counter, 0);
if(index == 0xffffffff) {
// Если всё ещё заблокировано, читаем ещё раз (максимум 3 попытки)
for(int i = 0; i < 2; i++) {
memoryBarrier();
index = atomicAdd(selBuffer[customIndex].counter, 0);
if(index != 0xffffffff) break;
}
if(index == 0xffffffff) return;
}
}