Closed richardeakin closed 3 years ago
Hi @richardeakin,
Make sure the hitGroupId
uses the proper Hit Group Shaders for the implicit objects. In createTopLevelAS()
you are setting the value to 0, which in incorrect in this case. Check that all BLAS containing implicit objects are using the Hit Group 1 or the one associated with the Group (Hit, Intersection, AnyHit) you create in the SBT, which I haven't see it done.
Thanks for taking a look at this! I believe I am adding the implicit objects to the TLAS with hit group = 1 here, this is what you're referring to right?
The link is a convenient place to ask you though, the line before seems like it could be the problem - does it make sense that the blasId
for the implicit BLAS is m_gltfScene.m_primMeshes.size()
? I haven't been able to reconcile in my mind how to deal with glTF scenes that have more nodes than meshes. For example taking cornellBox.gltf as used in the tutorial code, there are 9 primMeshes and thus 9 BLAS added in createBottomLevelAS()
, and then in createTopLevelAS()
there are 10 nvvk::RaytracingBuilderKHR::Instance
s added to the TLAS corresponding to the 10 scene nodes (the two spheres reuse the same mesh).
I thought this was the issue as Suzanne.gltf has only one node and one mesh and it worked, but then this was squashed when I tried Box.gltf which as is 1:1 nodes:meshes and it has the same problems as cornellBox.gltf. Thanks again for any tips on solving this, it is driving me a bit nuts!
For convenience I've pasted my updated version of these functions here:
void HelloVulkan::createBottomLevelAS()
{
// BLAS - Storing each primitive in a geometry
std::vector<nvvk::RaytracingBuilderKHR::BlasInput> allBlas;
allBlas.reserve(m_gltfScene.m_primMeshes.size());
for(auto& primMesh : m_gltfScene.m_primMeshes)
{
auto geo = primitiveToGeometry(primMesh);
allBlas.push_back({geo});
}
// Implicits
{
auto blas = sphereToVkGeometryKHR();
allBlas.emplace_back(blas);
}
m_rtBuilder.buildBlas(allBlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
}
void HelloVulkan::createTopLevelAS()
{
std::vector<nvvk::RaytracingBuilderKHR::Instance> tlas;
tlas.reserve(m_gltfScene.m_nodes.size());
uint32_t instID = 0;
for(auto& node : m_gltfScene.m_nodes)
{
nvvk::RaytracingBuilderKHR::Instance rayInst;
rayInst.transform = node.worldMatrix;
rayInst.instanceCustomId = node.primMesh; // gl_InstanceCustomIndexEXT: to find which primitive
rayInst.blasId = node.primMesh;
rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
rayInst.hitGroupId = 0; // We will use the same hit group for all objects
tlas.emplace_back(rayInst);
}
// Add the blas containing all implicits
{
nvvk::RaytracingBuilderKHR::Instance rayInst;
rayInst.transform = m_gltfScene.m_nodes[0].worldMatrix; // Position of the instance
rayInst.instanceCustomId = static_cast<uint32_t>(tlas.size()); // gl_InstanceID
//rayInst.blasId = static_cast<uint32_t>(m_gltfScene.m_nodes.size());
rayInst.blasId = static_cast<uint32_t>(m_gltfScene.m_primMeshes.size()); // TODO: this is hacky, assign blasId from createBottomLevelAS()
rayInst.hitGroupId = 1; // We will use the same hit group for all objects
rayInst.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
tlas.emplace_back(rayInst);
}
m_rtBuilder.buildTlas(tlas, vk::BuildAccelerationStructureFlagBitsKHR::ePreferFastTrace);
}
I think you are not setting the right instance matrix for the implicit surface
Can you try replacing:
rayInst.transform = m_gltfScene.m_nodes[0].worldMatrix; // Position of the instance
with
rayInst.transform = nvmath::mat4(1); // Position of the instance
Hi, I took a bit of time looking into the issue. I was not able to re-use your example, but I have made a similar example starting with the glTF sample and adding the intersection code. I was able to see a similar artifacts when the matrix for the implicit surfaces was not identity. This makes sense, because the hitT is incorrectly calculated in the intersection shader.
Regarding the number of BLAS, it is m_gltfScene.m_primMeshes.size()
. If the implicit surfaces are added after all glTF primitives, the blasId
will be static_cast<uint32_t>(m_gltfScene.m_primMeshes.size())
.
Here is a modified version of the glTF. Sorry, it uses share code that is not yet on GitHub, but it should be easy to adapt. ray_tracing_gltf.zip
Note that this glTF example uses a very simple shading model. For a more complete PBR shading, I have wrote a separated example: https://github.com/nvpro-samples/vk_raytrace
Ah, of course! That's what I get for blindly copying the sample code. I imagine then this line should also be nvmath::mat4(1)
, though it doesn't matter with the objs since their transform was always identity.
After I read your diagnose of the bug, I've been having a go at enabling those TLAS-level transforms since that seems useful for building up larger scenes based on the "Ray Intersection with Transformed Objects" chapter in Suffern's "Ray Tracing from the Ground Up", working well! No transform:
rayInst.transform = nvmath::translation_mat4( nvmath::vec3f( 0, 2, 0 ) ) * nvmath::scale_mat4( nvmath::vec3f( 2 ) );
I'm working toward your vk_raytrace, looking forward to it! But also being able to raytrace some things procedurally was very important to me, so I'm happy that I finally have a solution for this bug I was stuck on. Thanks so much!
Hi,
Starting somewhere around the end of the intersection tutorial, I had a go at switching to gltf support based on the related tutorial and while I got pretty close, have been stuck on a bug for a while now. I've tried just about everything I can think of so thought I'd ask for some suggestions, based on the symptoms. This is my test project.
Basically, the intersection shader's hit values now see completely off. You can see my issue in the following gifs:
The following is a simplified scene, loading the Box.gltf file (red), and then an implicit object to the left and right:
You can see where the implicit objects actually are if I modify the intersection shader to always call
reportIntersectionEXT
with some positive hit distance. Here it is with the bug (hit distance is going negative when it shouldn't):And here it is when I hack it to use
reportIntersectionEXT(abs(tHit), hitKind);
:Some notes:
HelloVulkan::createTopLevelAS()
to account for the gltf scene sometimes having a different number of nodes versus meshes might be the culprit, but I can't find any proof of this yet.nbObj + 1
business going on in the ray_tracing_intersection tutorial that completely went away in the ray_tracing_gltftutorial and as far as I can tell isn't accounted for, this was my best guess at what is going on wrong, although I opted to just remove the material buffers from my raytrace2.rchit and just create them on the fly to simplify things.So, not sure what next to look at. All I know is that the
tHit
value in the intersection shader is reporting < 0 when it shouldn't. Does this ring any bells, or any ideas what I can try?Thanks so much again for the awesome tutorial series!