Vulkan Ray Tracing - Не каждый примитивный идентификатор из любого хит-шейдера - PullRequest
0 голосов
/ 28 февраля 2020

РЕДАКТИРОВАТЬ: я добавил. cpp файл моего проекта, он похож на пример в репозитории от Саша Виллемс.

Я новичок в Vulkan, и я пытаюсь написать луч Пересечение треугольника. К сожалению, я не нашел пример. Может быть, вы знаете один? Мне нужны эти пересечения, чтобы рассчитать затухание лучей. Поэтому я сделал шейдер raygen следующим образом:

#version 460
#extension GL_NV_ray_tracing : require

#define debug 0

layout(binding = 0, set = 0) uniform accelerationStructureNV topLevelAS;
layout(binding = 1, set = 0, rgba8) uniform image2D image;
layout(binding = 2, set = 0) uniform CameraProperties 
{
    mat4 viewInverse;
    mat4 projInverse;
} cam;

layout(binding = 3, set = 0) buffer detectorProperties
{
    double detectorValue[];
} detectors;

//layout(binding = 4, set = 0) buffer outputProperties
//{
//  double outputValues[];  
//} outputData;

layout(binding = 5, set = 0) buffer debugProperties
{
    double debugValues[];   
} debugData;

struct RayPayload {
    uint outputId;
    uint hitCounter;    
};

layout(location = 0) rayPayloadNV RayPayload rayPayload;

void main() 
{   
    rayPayload.outputId = gl_LaunchIDNV.x * 18+ gl_LaunchIDNV.y * gl_LaunchSizeNV.x * 18;
    rayPayload.hitCounter = 0;
    vec3 origin = vec3(cam.viewInverse[0].x, cam.viewInverse[1].y, cam.viewInverse[2].z);
     uint rayId = uint(gl_LaunchIDNV.x + gl_LaunchSizeNV.x * gl_LaunchIDNV.y);
    uint targetXId = rayId;
    uint targetYId = rayId + gl_LaunchSizeNV.x * gl_LaunchSizeNV.y;
    uint targetZId = rayId + gl_LaunchSizeNV.x * gl_LaunchSizeNV.y *2;
    vec3 target = vec3(detectors.detectorValue[targetXId],detectors.detectorValue[targetYId], detectors.detectorValue[targetZId]) ;
    vec3 direction = target.xyz-origin.xyz ;    
    #ifdef debug
    uint debugId = rayPayload.outputId;
    debugData.debugValues[debugId + 0 ] = gl_LaunchSizeNV.x;
    debugData.debugValues[debugId + 1] = gl_LaunchSizeNV.y;
    debugData.debugValues[debugId+ 2 ] = gl_LaunchIDNV.x;
    debugData.debugValues[debugId+ 3 ] = gl_LaunchIDNV.y;
    debugData.debugValues[debugId + 4] = targetXId;
    debugData.debugValues[debugId + 5] = targetYId;
    debugData.debugValues[debugId + 6] = targetZId;
    debugData.debugValues[debugId + 7] = target.x;
    debugData.debugValues[debugId + 8] = target.y;
    debugData.debugValues[debugId + 9] = target.z;
    debugData.debugValues[debugId + 10] = origin.x;
    debugData.debugValues[debugId + 11] = origin.y;
    debugData.debugValues[debugId + 12] = origin.z;
    debugData.debugValues[debugId + 13] = direction.x;
    debugData.debugValues[debugId + 14] = direction.y;
    debugData.debugValues[debugId + 15] = direction.z;
    debugData.debugValues[debugId + 16] = rayId;    
    debugData.debugValues[debugId + 17] = rayPayload.outputId;
    #endif
    uint rayFlags = gl_RayFlagsNoneNV;
    uint cullMask = 0xff;
    float tmin = 0.00001;
    float tmax = 10000.0;

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


//  uint outputId = gl_LaunchIDNV.x * 18+ gl_LaunchIDNV.y * gl_LaunchSizeNV.x *18;
//  outputData.outputValues[outputId + hitCounter] = double(hitValue[hitCounter]);          
    imageStore(image, ivec2(gl_LaunchIDNV.xy), vec4(rayPayload.hitCounter,0,0, 0.0));
}

И с помощью шейдера с любым попаданием я просто хочу вернуть примитивный Id следующим образом:

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

layout(binding = 4, set = 0) buffer outputProperties
{
    float outputValues[];   
} outputData;

struct RayPayload {
    uint outputId;
    uint hitCounter;    
};

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

void main()
{   
//  uint outputIdCurrentTriangle = rayPayload.outputId + rayPayload.hitCounter;
    uint outputIdCurrentTriangle = rayPayload.outputId + rayPayload.hitCounter++;
  outputData.outputValues[outputIdCurrentTriangle] = gl_PrimitiveID;  
//  rayPayload.hitCounter ++;
}

Вы можете увидеть . cpp файл здесь: https://drive.google.com/file/d/1iTX3ATaP3pT7d4CEowo4IVnQxTOerxaD/view?usp=sharing

Моя проблема в том, что я просто нахожу все поверхностные треугольники, ближайшие к источнику, даже если объект не является непрозрачным (это проверено с помощью настройки Rayflag к cullNoOpaques).

Есть ли у кого-то такая же проблема или есть пример, который также дает примитивы любого ответного удара?

Я только что нашел один пример для шейдеров с любым ударом. Шейдер любого удара это менее используется? Спасибо за вашу помощь!

1 Ответ

0 голосов
/ 03 марта 2020

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

При этом любой ваш ударный шейдер будет работать без изменения gl_RayTmaxNV и gl_HitKindNV, вызывая все пересечения лучей.

С простым любым шейдерным ударом, как этот:

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

#include "raypayload.glsl"

layout(binding = 1, set = 0, rgba8) uniform image2D image;

layout(location = 0) rayPayloadInNV RayPayload rayPayload;

void main()
{
    rayPayload.hitcount++;
    ignoreIntersectionNV();
}

hitCount будет увеличено на единицу для каждого пересечения, визуализация этого с помощью цветовой кодировки по Hitcount приведет к примерно так:

Colored intersections

...