ОК, давайте уберем очевидную ошибку:
for(int i = 0; i < lights.numLights; i++)
{
tspace.tangentProperties[index].TangentLightPos.xyz = TBN * lights.properties[index].lightPosition.xyz;
tspace.tangentProperties[index].TangentViewPos.xyz = TBN * camPos;
tspace.tangentProperties[index].TangentFragPos.xyz = TBN * vec3(worldPosition);
memoryBarrierBuffer();
}
index
никогда не меняется в этом цикле, поэтому вы пишете только один свет, ивы пишете только значения last lights.Все остальные источники света будут иметь мусорные / неопределенные значения.
Так что вы, вероятно, имели в виду i
, а не index
.
Но это только начало проблемы.Видите ли, если вы сделаете это изменение, вы получите следующее:
for(int i = 0; i < lights.numLights; i++)
{
tspace.tangentProperties[i].TangentLightPos.xyz = TBN * lights.properties[i].lightPosition.xyz;
tspace.tangentProperties[i].TangentViewPos.xyz = TBN * camPos;
tspace.tangentProperties[i].TangentFragPos.xyz = TBN * vec3(worldPosition);
}
memoryBarrierBuffer();
Обратите внимание, что барьер находится за пределами цикла.
Это создает новую проблему.В этом коде каждый вызов вершинного шейдера будет записываться в один и тот же буфер памяти .В конце концов, SSBO не являются переменными VS output .Выходные переменные хранятся как часть вершины.Затем растеризатор интерполирует эти данные вершин по всему примитиву при растеризации, что обеспечивает входные значения для FS.Таким образом, одна VS не может растоптать выходные переменные другой VS.
Этого не происходит с SSBO.Каждая VS действует на одинаковую память SSBO.Так что, если они пишут с одинаковыми индексами одного и того же массива, они пишут по одному и тому же адресу памяти.Что является условием гонки (поскольку не может быть никакой синхронизации между вызовами родного брата) и, следовательно, неопределенным поведением.
Итак, единственный способ , который вы пытаетесь сделать, может сработать, есливаш буфер содержит numLights
записей для каждой вершины во всей сцене .
Это принципиально неразумное количество места.Даже если бы вы могли сократить его до количества вершин в конкретном вызове отрисовки (что выполнимо, но я не буду говорить, как), вы все равно отставали бы в производительности.Каждый вызов FS должен выполнять чтение 144 байтов данных для каждого источника света (3 записи таблицы, по одному для каждой вершины треугольника), линейно интерполировать эти значения и затем выполнять вычисления освещения.
Для вас было бы быстрее просто передать матрицу TBN в качестве выхода VS и выполнить умножение матрицы в FS.Да, это многократное умножение матриц, но графические процессоры действительно быстры при умножении матриц и очень медленно при чтении памяти.
Кроме того, пересмотрите, нужно ли вам положение фрагмента касательного пространства.Вообще говоря, вы никогда не делаете.