0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何在光线跟踪和碰撞检测上下文中使用NanoVDB 库的示例

星星科技指导员 来源:NVIDIA 作者:NVIDIA 2022-04-28 14:22 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

开放式 VDB 是奥斯卡奖获奖的稀疏动态卷的行业标准库。在整个视觉效果行业中,它被用于模拟和渲染水、火、烟、云和大量其他依赖于稀疏体积数据的效果。该库包括一个分层的、动态的数据结构和一套工具,用于高效地存储和操作三维网格上离散的稀疏体数据。库由 学院软件基金会( ASWF ) 维护。有关详细信息,请参见 VDB :具有动态拓扑的高分辨率稀疏卷 。

尽管 OpenVDB 提供了性能优势,但它的设计并没有考虑到 GPUs 。它对几个外部库的依赖使得利用 GPUs 上的 VDB 数据变得很麻烦,这正是本文主题的动机。我们将向您介绍 NanoVDB 库,并提供一些如何在光线跟踪和碰撞检测上下文中使用它的示例。

NanoVDB 简介

最初在 NVIDIA 开发的 NanoVDB 库是一个 ASWF OpenVDB 项目的新增功能 。它提供了一个与 OpenVDB 的核心数据结构完全兼容的简化表示,具有在 NanoVDB 和 OpenVDB 数据结构之间来回转换、创建和可视化数据的功能。

poYBAGJqMpWAAPy-AAD5OmBKd9k476.png

图 1 OpenVDB 和 NanoVDB 数据结构的图示。

NanoVDB 采用了 VDB 树结构的压缩、线性化、只读表示(图 1 ),这使得它适合于树层次结构的快速传输和快速、无指针遍历。为了提高效率,数据流经过调整,可以在 GPUs 和 CPU 上使用。

创建 NanoVDB 网格

尽管 NanoVDB 网格是一种只读数据结构,但该库包含生成或加载数据的功能。

所有的 OpenVDB 网格类 – LevelSets 、 FogVolumes 、 PointIndexGrids 和 PointDataGrids ——都支持 NanoVDB 表示,并且可以直接从 OpenVDB 文件(即 。 vdb 系统 文件)加载。还可以将数据加载或保存到 NanoVDB 自己的文件格式中或从中保存,该格式本质上是其内存流的一个转储,其中包含用于高效检查的附加元数据。

以下代码示例从 OpenVDB 文件转换:

以下代码示例从 OpenVDB 文件转换:

openvdb::io::File file(fileName);
auto vdbGrid = file.readGrid(gridName);
auto handle = nanovdb::openToNanoVDB(vdbGrid);

虽然从现有的 OpenVDB 数据加载是典型的用例,但是附带的网格生成器工具允许您直接在内存中构建 NanoVDB 网格。提供了一些简单原语的函数来帮助您入门:

// generate a sparse narrow-band level set (i.e. truncated signed distance field) representation of a sphere.
auto handle = nanovdb::createLevelSetSphere(50, nanovdb::Vec3f(0));

下面的示例显示了如何使用 lambda 函数生成小而密集的体积(图 2 ):

nanovdb::GridBuilder builder(0);
auto op = [](const nanovdb::Coord& ijk) -> float { return menger(nanovdb::Vec3f(ijk) * 0.01f);
};
builder(op, nanovdb::CoordBBox(nanovdb::Coord(-100), nanovdb::Coord(100)));
// create a FogVolume grid called "menger" with voxel-size 1
auto handle = builder.getHandle<>(1.0, nanovdb::Vec3d(0), "menger", nanovdb::GridClass::FogVolume);

网格控制柄

网格句柄 是一个简单的类,它拥有它分配的缓冲区的所有权,允许网格的范围划分( RAII )。

它还用于封装不透明的网格数据。尽管网格数据本身是以数据类型(如 浮动 为模板的),但句柄提供了一种方便的方法来访问网格的元数据,而不必知道网格的数据类型 MIG 是什么。这很有用,因为您可以纯粹从句柄确定 GridType 。

下面的代码示例验证是否有包含级别集函数的 32 位浮点网格:

const nanovdb::GridMetaData* metadata = handle.gridMetaData();
if (!metadata->isLevelSet() || !metadata->gridType() == GridType::Float) throw std::runtime_error("Not the right stuff!");

网格缓冲区

NanoVDB 被设计成支持许多不同的平台, CPU , CUDA 甚至图形 api 。为了实现这一点,数据结构被存储在一个平坦的连续内存缓冲区中。

使这个缓冲区驻留在 CUDA 设备上很简单。为了完全控制,您可以使用 CUDA api 分配设备内存,然后将句柄的数据上载到其中。

void* d_gridData;
cudaMalloc(&d_gridData, handle.size());
cudaMemcpy(d_gridData, handle.data(), handle.size(), cudaMemcpyHostToDevice);
const nanovdb::FloatGrid* d_grid = reinterpret_cast(d_gridData);

NanoVDB 的 GridHandle 模板化在缓冲区类型上,缓冲区类型是其内存分配的包装器。它默认为使用主机系统内存的主机缓冲区;然而, NanoVDB 还提供了CUDA 缓冲器,以便轻松创建 CUDA 设备缓冲区。

auto handle = nanovdb::openToNanoVDB<nanovdb::CudaDeviceBuffer>(vdbGrid);
handle->deviceUpload();
const nanovdb::FloatGrid* grid = handle->deviceGrid();

将数据流解释为纳米网格类型后,可以使用这些方法访问网格中的数据。有关更多详细信息,请参阅相关 API 的文档。本质上,它反映了 OpenVDB 中只读方法的基本子集。

auto hostOrDeviceOp = [grid] __host__ __device__ (nanovdb::Coord ijk) -> float {
  // Note that ReadAccessor (see below) should be used for performance.
  return grid->tree().getValue(ijk);
};

可以构造自定义缓冲区来处理不同的内存空间。有关创建可与图形 API 交互操作的缓冲区的示例的更多信息,请参阅存储库中的示例。

致使

由于 NanoVDB 网格提供了一个紧凑的只读 VDB 树,因此它们很适合渲染任务。光线将 VDB 网格跟踪到图像中。使用每线程一条光线,并使用一个自定义的 雷吉诺 functor 生成光线,该函数接受像素偏移并创建世界空间光线。完整的代码在存储库示例中可用。

考虑到沿射线采样具有空间相干性这一事实,可以使用 读写器 来加速采样。当光线向前移动时,这会缓存树遍历堆栈,从而允许自底向上的树遍历,这比传统的自上而下遍历要快得多,后者涉及相对较慢的无界根节点。

auto renderTransmittanceOp = [image, grid, w, h, rayGenOp, imageOp, dt] __host__ __device__ (int i) {
    nanovdb::Ray wRay = rayGenOp(i, w, h);
    // transform the ray to the grid's index-space...
    nanovdb::Ray iRay = wRay.worldToIndexF(*grid);
    // clip to bounds.
    if (iRay.clip(grid->tree().bbox()) == false) {
        imageOp(image, i, w, h, 1.0f);
        return;
    }
    // get an accessor.
    auto acc = grid->tree().getAccessor();
    // integrate along ray interval...
    float transmittance = 1.0f;
    for (float t = iRay.t0(); t < iRay.t1(); t+=dt) {
        float sigma = acc.getValue(nanovdb::Coord::Floor(iRay(t)));
        transmittance *= 1.0f - sigma * dt;
    }
    imageOp(image, i, w, h, transmittance );
};

由于光线与水平集网格相交是一项常见任务, NanoVDB 实现了一个零交叉功能,并使用分层 DDA ( HDDA )作为沿光线的根搜索的一部分来清空空间跳跃(图 5 )。有关 HDDA 的更多信息,请参阅 OpenVDB 中高效光线行进的分层数字微分分析仪 。下面是代码示例:

...
    auto acc = grid->tree().getAccessor();
    // intersect with zero level-set...
    float iT0;
    nanovdb::Coord ijk;
    float v;
    if (nanovdb::ZeroCrossing(iRay, acc, ijk, v, iT0)) { 
        // convert intersection distance (iT0) to world-space
        float wT0 = iT0 * grid->voxelSize();
        imageOp(image, i, w, h, wT0);
    } else {
        imageOp(image, i, w, h, 0.0f);
    }
...

碰撞检测

碰撞检测和解决是 NanoVDB 的另一项任务,因为它们通常需要有效地查找实体碰撞对象的有符号距离值。窄带电平集表示非常理想,因为它们用符号对内部/外部拓扑信息(碰撞检测所需)进行了紧凑编码。此外,最近点变换(冲突解决所需的)很容易从水平集函数的梯度计算。

下面的代码示例是一个用于处理冲突的函数。使用 读写器 是很有用的,因为用于冲突解决的梯度计算涉及到同一空间附近的多个提取。

auto collisionOp = [grid, positions, velocities, dt] __host__ __device__ (int i) {
    nanovdb::Vec3f wPos = positions[i];
    nanovdb::Vec3f wVel = velocities[i];
    nanovdb::Vec3f wNextPos = wPos + wVel * dt;
    // transform the position to a custom space...
    nanovdb::Vec3f iNextPos = grid.worldToIndexF(wNextPos);
    // the grid index coordinate.
    nanovdb::Coord ijk = nanovdb::Coord::Floor(iNextPos);
    // get an accessor.
    auto acc = grid->tree().getAccessor();
    if (tree.isActive(ijk)) { // are you inside the narrow band?
        float wDistance = acc.getValue(ijk);
        if (wDistance <= 0) { // are you inside the levelset?
            // get the normal for collision resolution.
            nanovdb::Vec3f normal(wDistance);
            ijk[0] += 1;
            normal[0] += acc.getValue(ijk);
            ijk[0] -= 1;
            ijk[1] += 1;
            normal[1] += acc.getValue(ijk);
            ijk[1] -= 1;
            ijk[2] += 1;
            normal[2] += acc.getValue(ijk);
            normal.normalize();
            
            // handle collision response with the surface.
            collisionResponse(wPos, wNextPos, normal, wDistance, wNextPos, wNextVel);
        }
    }
    positions[i] = wNextPos;
    velocities[i] = wNextVel;
};

同样,完整的代码可以在存储库中找到。

基准

NanoVDB 被开发成在主机和设备上同样运行良好。使用 modernCUDA 中的扩展 lambda 支持,您可以轻松地在两个平台上运行相同的代码。

本节包括比较英特尔线程构建块和 CPU CUDA 上光线跟踪和碰撞检测性能的基准测试。计时以毫秒为单位,与 NVIDIA NVIDIA 8000 相比,是在 Xeon E5-2696 v4 x2 –( 88 个 CPU 线程)上生成的。使用的 FogVolume 是兔子云, LevelSet 是 dragon 数据集。两者都可以从 OpenVDB 网站下载。渲染的分辨率为 1024×1024 。这次碰撞试验模拟了一亿颗弹道粒子。

虽然基准测试(图 6 和下表)显示了 NanoVDB 高效表示加速 CPU 上 OpenVDB 的好处,但它真正突出了使用 GPU 对 VDB 数据进行只读访问以进行碰撞检测和光线跟踪的好处。

图 6 Intel TBB 与 CUDA 的比较(越小越好)。

结论

NanoVDB 是一个小而强大的库,它通过使用 GPUs 来加速某些 OpenVDB 应用程序。开源存储库现在可用了!要下载源代码、构建示例

关于作者

Wil Braithwaite 在伦敦和洛杉矶的工作室工作了 15 年的视觉特效。他的职位包括研究、技术指导、合成、 CG 监督和 MOCAP 监督。他开创了图形硬件在 VFX 管道中的应用,在 NVIDIA 担任高级应用工程师,专门从事咨询、培训和使用 NVIDIA 技术协助 VFX 工作室项目的开发。

Ken Museth 是模拟技术的高级主管,并于 2020 年初加入 NVIDIA ,当时他发起了 NanoVDB 的开发。他以前在开发虚拟现实技术的时候,一直致力于虚拟现实的开发。他是 VDB 的创建者和 OpenVDB 的首席架构师,也是其技术指导委员会的主席。此外,肯在 SpaceX 公司工作了六年,对新的猛禽火箭发动机进行大规模流体动力学模拟。在 2017 年加入 Weta 之前,他在梦工厂动画和数字领域工作了 10 年,在此之前,他曾在加州理工学院和林科平大学担任研究员和全职教授。他拥有哥本哈根大学量子动力学博士学位,并获得电影艺术与科学学院颁发的技术成就奖。肯是 SIGGRAPH 2020 技术论文委员会成员。

审核编辑:郭婷

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • NVIDIA
    +关注

    关注

    14

    文章

    5510

    浏览量

    109154
  • gpu
    gpu
    +关注

    关注

    28

    文章

    5110

    浏览量

    134512
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    大语言模型如何处理上下文窗口中的输入

    本博客介绍了五个基本概念,阐述了大语言模型如何处理上下文窗口中的输入。通过明确的例子和实践中获得的见解,本文介绍了多个与上下文窗口有关的基本概念,如词元化、序列长度和注意力等。
    的头像 发表于 12-03 13:48 251次阅读
    大语言模型如何处理<b class='flag-5'>上下文</b>窗口中的输入

    执行脱离上下文的威胁分析与风险评估

    作为WITTENSTEIN high integrity system(WHIS)公司的核心产品,SAFERTOS专为安全关键型嵌入式系统设计,使其成为确保联网车辆环境可靠防护的理想选择。在本文中
    的头像 发表于 11-28 09:11 300次阅读
    执行脱离<b class='flag-5'>上下文</b>的威胁分析与风险评估

    在CW32F030 MCU上设置外部中断和RTC唤醒条件的示例

    (void) { // 在这里添加进入DeepSleep模式前的准备工作,比如保存上下文、禁用不必要的时钟等 // 请求进入DeepSleep模式(具体实现可能依赖于你的MCU和HAL
    发表于 11-25 08:00

    请问riscv中断还需要软件保存上下文和恢复吗?

    以下是我拷贝的文档里的说明,这个中断处理还需要软件来写上下文保存和恢复,在使用ARM核的单片机都不需要考虑这些的,使用过的小伙伴能解答吗? 3.8. 进出中断的上下文保存和恢复 RISC-V架构
    发表于 10-20 09:56

    HarmonyOSAI编程智能问答

    多线程? 指定上下文问答 在对话框中输入@符号,或点击上方@Add Context按钮,可指定对单个或多个代码文件进行分析。点击图标开启光标上下文功能,该功能可识别光标位置和选中的代码片段,让CodeGenie分析指定文件和选中的代码片段。 本文主要从参考引用自Har
    发表于 09-03 16:17

    HarmonyOS AI辅助编程工具(CodeGenie)智能问答

    DeepSeek-R1智能体,快速体验智能问答能力。 一、对话示例 在对话区域输入需要查询的问题,开始问答。示例如下: ArkTS如何实现多线程? 二、指定上下文问答 在对话框中输入@符号,或点击上方@Add
    发表于 08-15 11:07

    鸿蒙NEXT-API19获取上下文,在class中和ability中获取上下文,API迁移示例-解决无法在EntryAbility中无法使用最新版

    摘要:随着鸿蒙系统API升级至16版本(modelVersion5.1.1),多项API已废弃。获取上下文需使用UIContext,具体方法包括:在组件中使用getUIContext(),在类中使
    的头像 发表于 07-01 10:57 619次阅读
    鸿蒙NEXT-API19获取<b class='flag-5'>上下文</b>,在class中和ability中获取<b class='flag-5'>上下文</b>,API迁移<b class='flag-5'>示例</b>-解决无法在EntryAbility中无法使用最新版

    Transformer架构中编码器的工作流程

    编码器是Transformer体系结构的基本组件。编码器的主要功能是将输入标记转换为上下文表示。与早期独立处理token的模型不同,Transformer编码器根据整个序列捕获每个token的上下文
    的头像 发表于 06-10 14:27 846次阅读
    Transformer架构中编码器的工作流程

    S32K在AUTOSAR中使用CAT1 ISR,是否需要执行上下文切换?

    如果我们在 AUTOSAR 中使用 CAT1 ISR,是否需要执行上下文切换?另外,是否需要返回指令才能跳回到作系统?您有没有带有 CAT1 ISR 的 S32K3x4 微控制器的示例
    发表于 03-27 07:34

    在mimxrt1170_evk调试hello_world出现硬件传输错误怎么解决?

    错误 硬件传输错误 调试上下文:evkmimxrt1170_hello_world_cm4 LinkServer Debug 请指教,非常感谢!
    发表于 03-25 07:31

    为什么深度学习中的Frame per Second高于OpenVINO™演示推理脚本?

    在 DL Workbench 上使用 Microsoft 通用对象上下文 (MS COCO) 数据集运行 YOLOv4 对象检测模型,并获得 50 - 60 FPS。 OpenVINO™演示推理脚本运行,并获得更高的 FPS。
    发表于 03-06 07:27

    DeepSeek推出NSA机制,加速长上下文训练与推理

    的特性,专为超快速的长上下文训练和推理而设计。 NSA通过针对现代硬件的优化设计,显著加快了推理速度,并大幅度降低了预训练成本,同时保持了卓越的性能表现。这一机制在确保效率的同时,并未牺牲模型的准确性或功能。 在广泛的基准测试、涉及长上下文的任务以及基于指令的推理场景中,
    的头像 发表于 02-19 14:01 938次阅读

    何在MATLAB中使用DeepSeek模型

    在 DeepSeek-R1(https://github.com/deepseek-ai/DeepSeek-R1) AI 模型横空出世后,人们几乎就立马开始询问如何在 MATLAB 中使用这些模型
    的头像 发表于 02-13 09:20 4102次阅读
    如<b class='flag-5'>何在</b>MATLAB<b class='flag-5'>中使</b>用DeepSeek模型

    dbForge Studio for PostgreSQL:PostgreSQL数据多功能集成开发环境

    数据模式和表数据的比较和同步 高效便捷地生成针对特定列的智能测试数据 支持14种格式的数据导入和导出 数据透视表中的数据汇总和值得关注的数据报告 多功能数据检索、存储和管理 从命令行自动化重复操作 dbForge Studio的重要功能 SQL编码辅助 Studio的集成编码辅助工具包括
    的头像 发表于 01-16 17:26 892次阅读

    何在Windows中使用MTP协议

    、图片等)的通信协议,它被广泛用于Android设备。以下是如何在Windows中使用MTP协议的详细步骤: 1. 确保设备支持MTP 首先,你需要确认你的设备支持MTP协议。大多数现代Android
    的头像 发表于 01-03 10:26 4503次阅读