Vulkan 光线追踪 - 并非来自任何命中着色器的每个原始 ID

Vulkan Ray Tracing - Not every primitive Id from any hit shader

编辑:我添加了我的项目的 .cpp 文件,它的退出类似于 Sascha Willems 的 repo 中的示例。

我是 Vulkan 的新手,我尝试写一个 Ray/Triangle 交集。可悲的是我没有找到一个例子。也许你知道一个? 我需要这些交点来计算光线的衰减。 所以我做了一个像这样的射线生成着色器:

#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 进行测试),我也只是找到了所有表面三角形,最接近源。

有没有人有同样的问题,或者有一个例子也给出了任何回击的 primitivesId?

我刚找到一个任意命中着色器的示例。 any-hit 着色器这么少用吗? 感谢您的帮助!

如果您想让任意命中着色器为场景中的所有三角形注册交点,您应该在任意命中着色器中调用 ignoreIntersectionNV(参见 GLSL_NV_ray_tracing specs)。

这样,您的任意命中着色器将在不修改 gl_RayTmaxNVgl_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 将增加 1,通过点击计数用颜色编码将其可视化将产生如下内容: