Vulkan Raytracing: расстояния до пораженного треугольника не сортируются - PullRequest
1 голос
/ 03 августа 2020

У меня проблема с шейдерами трассировки лучей, я не могу ее исправить. Использую vulkan и glsl. Расстояния до примитивов не отсортированы. Это означает, что луч, кажется, сначала попадает в ловушку, которая находится дальше, чем другая. Это нормальное поведение или я сделал что-то не так? Я проверяю эти данные с помощью Matlab, что означает, что для каждого пикселя в моем изображении я возвращаю примитивы и расстояния для дальнейших вычислений (максимум 40). Но в результирующих данных (вы можете увидеть это ниже) расстояния не отсортированы, и это требует большого времени вычислений, чтобы переупорядочить их.

Здесь вы можете увидеть шейдер любого попадания:

#version 460
#extension GL_NV_ray_tracing : require
#extension GL_EXT_nonuniform_qualifier : enable

layout(binding = 4, set = 0) buffer primitiveProperties
{
    float ids[];    
} primitives;


layout(binding = 6, set = 0) buffer distanceProperties
{
    float values[]; 
} distances;

struct RayPayload {
    uint outputId;
    uint hitCounter;    
};

layout(location = 0) rayPayloadInNV RayPayload rayPayload;
hitAttributeNV vec3 attribs;

void main()
{   

    uint outputIdCurrentTriangle = rayPayload.outputId + rayPayload.hitCounter++;
  primitives.ids[outputIdCurrentTriangle] = gl_PrimitiveID + 1;  
  distances.values[outputIdCurrentTriangle] = gl_HitTNV;  
  ignoreIntersectionNV();

}

И луч генерируется нормально:

traceNV(topLevelAS, rayFlags, cullMask, 0, 0, 0, origin.xyz, tmin, direction.xyz, tmax, 0); 

Но результат выглядит так: [расстояния в пикселе] [1] [1]: https://i.stack.imgur.com/FCDhl.png

В виде data: 0.83021832 0.83021832 0.84927511 0.84927511 0.94443458 0.94443458 0.94811541 0.94811541 1.0063932 1.0063932 0.97728723 0.97728723 0.98426312 0.98426312

А может и ошибок в нем больше. Итак, мой вопрос еще раз: нормально ли, что это происходит?

Спасибо за каждую помощь!

1 Ответ

3 голосов
/ 03 августа 2020

Это совершенно нормальное и ожидаемое поведение.

Ваш шейдер любого попадания по дизайну предназначен для вызова при прохождении графическим процессором структуры ускорения (что происходит в произвольном порядке, что лучше всего соответствует разметке данных ). Затем (обычно) предполагается, что вы вызовете только один из ignoreIntersectionNV() или reportIntersectionNV(), в зависимости от того, является ли это возможным попаданием или нет. Ожидается, что вы еще не будете считать это действительным попаданием.

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

Единственное исключение, когда вы уже можете сделать что-то значимое в any-hit-shader - в случае тестов видимости на бесконечность (скайбокс, источники света на бесконечном расстоянии). В этом случае может быть принято любое обращение , и вы можете сразу же позвонить terminateRayNV().

Простое использование трассировки лучей через расширение Nvidias Vulkan не подходит для решения проблем, связанных с порядком.

Для этого вы должны запускать лучи итеративным способом (фильтровать при любом попадании или даже VK_GEOMETRY_OPAQUE_BIT, повторно запускать с ближайшим попаданием) или построить старый добрый D-буфер на основе потенциальных попаданий, которые вы записали из вызовов любого попадания.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...