TIM-1EARCHIVE TERMINAL // 2026

PROJECT · 项目研发

SPCBPT 渲染器工程化与 Blender 接入

参与 SPCBPT 渲染器的工程重构,并开发 Aurelia Blender 前端,将研究渲染代码接入 Blender,支持最终渲染与渐进式视口预览。

  • C++
  • CUDA
  • OptiX
  • Python
  • Blender
SECTION01

Exhibit

展示

SPCBPT 渲染器工程化与 Blender 接入 的效果图
SECTION02

Access Ports

访问入口

SECTION03

Repositories

代码仓库

ssufujia /

SPCBPT-OptiX7 ↗

An OptiX 7 implementation of SPCBPT: Subspace-based Probabilistic Connections for Bidirectional Path Tracing

STARS
15
FORKS
3
PUSHED
2026.08.08
  • C++64.5%
  • Cuda20.4%
  • Python7.5%
  • PowerShell3.4%
  • Other4.2%

SPCBPT-OptiX7

基于 OptiX 9 / CUDA 的验证性双向路径追踪渲染器。当前默认配置为 LVCBPT + Path Guiding + Proxy (Experimental),Optimal-E 使用 CUDA mirror descent,初始学习率为 1.0。

实验脚本和回归测试随仓库提交;约 3.49 GiB 的原始 snapshot、候选矩阵和日志 仅保存在本地 ignored build/experiments/,不上传 GitHub。

本仓库是论文 SPCBPT:基于子空间概率连接的双向路径追踪 的 OptiX 实验实现。当前实现以验证渲染流程、数据结构和 Blender 接入为主, 不以完整复现论文全部算法为目标。

在 11 个场景真实 snapshot 上补做的 33 组同口径计时中,CUDA mirror lr=1.0 平均耗时 0.277850 s,旧 CUDA Adam lr=0.05 为 0.280028 s。两者速度和 loss 降幅都接近,没有为了速度切换算法的依据, 因此生产端保留实现更简单的 mirror。

环境要求

已验证的基线环境为 OptiX 9.1、CUDA 12.2、MSVC x64、Ninja 和 CMake 3.27 以上版本;全新构建另使用 CMake 4.4.0 验证通过。仓库内第三方 依赖版本见 third_party/README.md。

构建

仓库根目录是唯一支持的 CMake 源码入口,项目会拒绝源码内构建。

  1. 将 CMakeUserPresets.json.example 复制为 CMakeUserPresets.json。
  2. 填写本机的 OptiX_ROOT 和 Ninja 路径。
  3. 打开 x64 Visual Studio Developer PowerShell。
  4. 执行:
cmake --fresh --preset release-optix9-local
cmake --build --preset release-optix9-local

可执行文件位于 build/release-optix9/bin/optixPathTracer.exe;原生 OptiX-IR 文件会部署到同级的 bin/optix-ir/。

普通运行不需要传参数:先把 renderer_config.json.example 复制为 renderer_config.json,然后在仓库根目录直接启动:

.\build\release-optix9\bin\optixPathTracer.exe

程序默认读取当前目录的 renderer_config.json,并在启动时打印实际配置 来源、场景、算法、尺寸、路径模式、path guiding 与 Optimal-E 训练参数。 --config、--scene、--dim 只用于临时覆盖;完整字段说明见 docs/operation.md。

构建目标

  • spcbpt_renderer:OptiX 场景、pipeline、算法和原生 CUDA;不依赖 GLFW、glad、ImGui 或 OpenGL。
  • spcbpt_viewer:窗口、输入、显示与界面。
  • optixPathTracer:应用入口和 CLI 组装。
  • spcbpt_optix_ir:由 CMake 原生编译的两个 OptiX shader。

嵌入 Blender 等只需要渲染核心的宿主可设置 -DSPCBPT_BUILD_VIEWER=OFF -DBUILD_TESTING=OFF。此模式不配置 GLFW、 Dear ImGui、glad 或 OpenGL,只生成 spcbpt_renderer 与 OptiX-IR 相关目标; 如需核心测试,可单独保留 BUILD_TESTING=ON。

场景资源位于 assets/,第三方依赖位于 third_party/,运行与界面操作见 docs/operation.md。

许可证

项目原创代码按 BSD-3-Clause 许可;源文件中已有的 NVIDIA 等版权声明及 third_party/ 自带许可证继续有效。assets/ 不属于可再分发的 renderer-core 源码快照;除非单个资产明确附带许可证,本项目不授予其再分发权。 完整边界见 LICENSE 与 NOTICE.md。

与论文版本的差异

  • 当前禁用 t=1 策略,即光源子路径直接连接相机的策略,因为它通常效率较低。
  • 跨迭代复用光源子路径、环境贴图和透明材质尚未完整实现。
  • 子空间分类暂不考虑方向;多数场景中位置和法线更重要。
  • 子空间采样矩阵从对应子空间对路径完整贡献积分构造的初始矩阵开始训练, 以加快收敛。
  • 训练路径由带 NEE 的简单单向路径追踪器生成。
  • 过亮 firefly 仍比论文版本略多,后续再处理。

Tim-1e /

Blender-SPCBPT ↗

Aurelia Blender 5.2 frontend for SPCBPT-OptiX7

STARS
0
FORKS
0
PUSHED
2026.08.08
  • C++56.2%
  • Python22.8%
  • Cuda16.9%
  • C2.7%
  • Other1.5%

Blender-SPCBPT

Aurelia is a Blender 5.2 render-engine front end for SPCBPT-OptiX7. It supports F12 rendering and Blender's Rendered viewport. The default Native backend owns a persistent CUDA/OptiX session inside the Blender process; Bridge Process remains an isolated compatibility fallback.

中文说明 · Release history · License

Architecture

Module Responsibility Boundary
aurelia_spcbpt/__init__.py bpy.types.RenderEngine, settings, panels, F12 and viewport callbacks Blender main thread
aurelia_spcbpt/scene.py Evaluated current-frame validation, GLB export, camera/light/World sidecar Blender Python
aurelia_spcbpt/gltf_export_worker.py Official glTF export for restricted interactive F12 jobs Background Blender CLI
aurelia_spcbpt/native_session.py Native loading, process-wide session, camera/resize hot updates and progressive batches Blender worker thread
aurelia_spcbpt/protocol.py Versioned JSON and little-endian scene-linear RGBA32F validation Process contract
aurelia_spcbpt/bridge.py Child process, progress, timeout, cancellation and Native failure fallback Isolated process boundary
aurelia_spcbpt/viewport.py Generations, navigation/settled policy and single-GPU worker Scheduling boundary
native/python_module.cpp CPython 3.13 interface exported by aurelia_native.pyd In-process C++ boundary
native/session.cpp Persistent RendererSession and RGBA32F batch readback C++/CUDA/OptiX
native/main.cpp One-shot aurelia_bridge.exe fallback C++/CUDA/OptiX child process
renderer/SPCBPT-OptiX7 PT, LVCBPT and LVCBPT + Proxy core Vendored build-time snapshot
flowchart LR
    subgraph BL["Blender 5.2"]
        RE["bpy.types.RenderEngine<br/>F12 / view_update / view_draw"]
        VC["ViewportPolicy + Controller<br/>generation / debounce"]
        OUT["Combined / GPUTexture"]
    end

    SCENE["Evaluated Scene<br/>GLB + sidecar"]

    subgraph NATIVE["Default: in-process Native"]
        NS["NativeSessionRunner"]
        PYD["aurelia_native.pyd"]
        SESSION["persistent RendererSession"]
    end

    subgraph FALLBACK["Fallback: isolated Bridge"]
        BRIDGE["aurelia_bridge.exe"]
    end

    CORE["RendererRuntime + Workflow<br/>PT / LVCBPT / Proxy + OptiX"]

    RE --> VC
    RE --> SCENE
    SCENE --> NS
    VC --> NS
    NS --> PYD --> SESSION --> CORE
    VC -. "AUTO failure or explicit selection" .-> BRIDGE --> CORE
    CORE --> OUT --> RE
Loading

Native and Bridge link the same renderer core; they are not separate algorithms. Native camera updates reuse scene and OptiX state. Each Bridge request owns an isolated temporary directory containing its scene, result, status and cancellation paths. The viewport sequence below shows the complete navigation and settled-render handoff.

Build the native bridge

Requirements: Windows x64, CUDA, OptiX 8+, Visual Studio C++/CUDA support, CMake 3.27+, CPython 3.13 development files, and a supported NVIDIA GPU. The tested release toolchain is CUDA 12.2 with OptiX 9.1.

The required renderer core is already vendored at renderer/SPCBPT-OptiX7; no sibling checkout or compatibility patch is required. AURELIA_SPCBPT_ROOT remains an optional override for renderer-core development. The snapshot source and exact upstream commit are recorded in UPSTREAM.md.

Then open an x64 Visual Studio developer PowerShell and configure the bridge. Replace the OptiX SDK path and CUDA architecture for your machine:

$repoRoot = (Resolve-Path '.').Path
$optixRoot = 'C:\path\to\NVIDIA OptiX SDK'
$pythonRoot = 'C:\path\to\cpython-3.13'

cmake `
  -S (Join-Path $repoRoot 'native') `
  -B (Join-Path $repoRoot 'build\native') `
  -G Ninja `
  "-DOptiX_ROOT=$optixRoot" `
  "-DAURELIA_PYTHON_ROOT=$pythonRoot" `
  -DCMAKE_BUILD_TYPE=Release `
  -DSPCBPT_CUDA_ARCHITECTURES=89 `
  -DSPCBPT_OPTIX_INPUT_ARCH=sm_89

cmake `
  --build (Join-Path $repoRoot 'build\native') `
  --target aurelia_bridge aurelia_native `
  --parallel 8

The Bridge and OptiX IR are written to build/native/bin/; the Blender 5.2 native module is written to build/native/python/.

The vendored renderer is a build-time dependency: CMake compiles and links its runtime into both native backends. It is not an installed-Extension dependency.

Build environment hygiene

Aurelia does not use AI-service credentials. CMake, NVCC, and their child processes still inherit the parent shell environment, and verbose compiler diagnostics may echo inherited values. Build from a clean developer shell and do not keep unrelated secrets in that environment.

Development installation

For live development, link the Python package into Blender's local Extension repository:

$repoRoot = (Resolve-Path '.').Path
$extensionRoot = Join-Path $env:APPDATA 'Blender Foundation\Blender\5.2\extensions\user_default'
New-Item -ItemType Directory -Force -Path $extensionRoot
New-Item -ItemType Junction `
  -Path (Join-Path $extensionRoot 'aurelia_spcbpt') `
  -Target (Join-Path $repoRoot 'aurelia_spcbpt')

Restart Blender, open Preferences > Extensions, and enable Aurelia SPCBPT. A packaged release can instead be installed with Install from Disk.

The same source remains compatible with Blender's legacy add-on directory:

%APPDATA%\Blender Foundation\Blender\5.2\scripts\addons\aurelia_spcbpt

That entry is shown as Aurelia SPCBPT (Legacy). Do not install or enable both entry paths at the same time.

In Blender:

  1. Select Aurelia from Render Properties > Render Engine.
  2. Leave Backend at Native (Auto Fallback). Select Bridge Process to force the compatibility process.
  3. Choose PT, LVCBPT, or LVCBPT + Proxy and set samples.
  4. Press F12, or switch a 3D Viewport to Rendered.

The Render, Output, material Surface, World Surface, camera lens and supported light controls remain visible while Aurelia is selected.

Interactive F12 runs the official glTF exporter in an isolated blender --background child because Blender removes UI context members from the active RenderEngine.render() job. This avoids loading a second UI window, but adds Blender process startup time to F12.

Build the Extension ZIP

With Blender closed and the native bridge already built, create the installable Windows x64 ZIP using Blender 5.2:

$blender = 'C:\path\to\Blender 5.2\blender.exe'
.\build_extension.ps1 -Blender $blender

The release script stages the Python front end, native module, CUDA runtime, Bridge fallback, and OptiX IR, then delegates ZIP creation to Blender's Extension command. No renderer source tree or build directory is required. The destination computer does not need CMake, the CUDA Toolkit, the OptiX SDK, or a separate renderer checkout. It still needs Blender 5.2, a compatible NVIDIA driver/GPU, and the Microsoft Visual C++ 2015-2022 x64 runtime.

Viewport behavior

  • Camera navigation uses plain PT while the GLB, scene, GAS/IAS, SBT, materials, textures and native Session remain resident.
  • A camera change only uploads camera parameters and resets accumulation. Old camera samples are never accumulated into the new camera.
  • This edit-time PT is plain path tracing: path guiding and LVC/Optimal-E preprocessing are disabled. World HDR sampling state is still initialized.
  • After Idle Restore Delay, it automatically returns to the selected LVCBPT or Proxy integrator and rebuilds preprocessing. The default delay is 1 second and can be raised to avoid accidental advanced rebuilds.
  • Editing during LVCBPT/Proxy preprocessing requests native cooperative cancellation. The renderer exits at the next CUDA synchronization or major CPU-stage boundary, cleans the partial state, and runs the latest-camera PT request next. The previous PT texture stays visible during the handoff.
  • F12 is a separate final-render job. Viewport edits do not cancel it. Cancellation is scoped to the exact viewport-job owner, even though both paths share the process-wide Native runner.
  • The most recently completed texture remains visible; only the latest generation can become the final Current result.
  • The latest export, scene-build, preprocessing, render and first-pixel timings are shown in Render Properties.

Continuous navigation now uses Cycles-style delayed cancellation and latest-camera coalescing. The active 1-spp navigation batch may finish and display as Navigation/Stale; intervening input retains only the latest camera, which starts immediately afterward. A running settled PT or advanced pass is cancelled as soon as navigation begins. Idle then starts final PT or restores LVCBPT/Proxy once. Navigation samples default to 1 and remain exposed in Render Properties.

sequenceDiagram
    participant UI as Blender input
    participant C as ViewportController
    participant R as persistent Native PT
    participant D as GPUTexture

    UI->>C: camera G1
    C->>R: G1, 1 spp
    UI->>C: camera G2 / G3 / G4
    Note over C: coalesce pending to G4
    R-->>C: G1 navigation frame
    C-->>D: show as Navigation/Stale
    C->>R: latest G4, 1 spp
    R-->>D: show G4
    Note over UI,C: Idle Restore Delay
    C->>R: final PT or one advanced restore
    UI->>C: edit while advanced preprocessing runs
    C-->>R: cancel at native safe point
    C->>R: latest-camera PT preview
Loading

Blender data access and GLB export run on Blender's main thread; rendering uses one process-wide Native Session. Scene-data edits rebuild the scene package. Auto retries through Bridge when native loading, GPU/OptiX initialization or rendering fails.

Supported scene subset

Blender data Supported Explicitly rejected for now
Geometry Evaluated render-visible triangle meshes, transforms, instances exported by Blender GLB Curves, volumes, hair, Grease Pencil and other non-mesh objects
Camera Perspective, active scene camera and perspective viewport camera Orthographic, panorama, DOF and motion blur
Material Direct Principled BSDF; base color, metallic/mirror, roughness, image textures, Normal Map image, emission, constant Transmission + IOR, and same-image Alpha cutout Transmission textures, fractional opacity blending, separate opacity maps, subsurface, coat, sheen, anisotropy, Bump/procedural nodes and arbitrary node graphs
Light Square/rectangular Area and Sun, with a calibration multiplier Point, Spot, disk and ellipse Area
World Constant color or a readable Radiance .hdr; HDR strength must be 1 Procedural World graphs and non-HDR environment files

Unsupported content fails with the relevant Blender object, material, light, camera or World name instead of being silently approximated.

Transmission and Alpha are intentionally separate. Principled Transmission is physical BSDF transmission and is exercised by PT, LVCBPT and Proxy. A linked Alpha output from the same Base Color image is binary coverage with a 0.5 threshold; it is not fractional glass or volume absorption. Emissive surfaces are visible in PT, but are not yet registered as importance-sampled mesh lights for the advanced integrators; use Blender Area or Sun lights for illumination.

BlenderKit and external assets

Aurelia does not call the BlenderKit service API. Once an asset is downloaded or appended, it is ordinary evaluated Blender data and follows the same supported-subset table above. Complex material graphs may need an explicit direct-Principled conversion. Third-party scenes and assets used for local compatibility checks are not redistributed by this repository; their original licenses still apply.

The validation matrix is deliberately small and varied:

Asset Coverage Local compatibility copy Current PT validation
Dorm Room Setup Packed textures, many materials, glass, Area lights Orthographic camera converted to perspective; Spot lights hidden; unsupported Bump/specular links and fractional/separate opacity made explicit fallbacks 64x64 / 1 spp Native PT complete and non-black
Bundled simple.blend Seven simple mesh fixtures, standard Principled materials, Area lighting, 16:9 camera No compatibility conversion required 64x64 / 1 spp Native PT complete and non-black
Millennial Retro Desk Setup 68 mesh instances, 48 materials, three Area lights, glass and Alpha cutout Eight curves converted to mesh; one procedural wood material flattened; one Bump link disabled 64x64 / 1 spp Native PT complete and non-black

The project-created scenes/simple.blend is included for installation and rendering checks and is distributed under the repository's GPL-3.0-or-later license. The two linked BlenderKit assets remain external and retain their source licenses. A successful row means scene export, native renderer loading, OptiX build and one-sample PT all completed with the exact-size RGBA32F result; it is not a claim of pixel equality with Cycles. Like Cycles, Aurelia fills the complete 3D View Region in both Camera View and free perspective; the area inside Blender's Camera Frame keeps the final-camera composition. Blender composites viewport overlays after the renderer, as it does for Cycles; floor grids, axes, selected outlines and helper objects can therefore remain visible. Use Blender's Show Overlays switch (Shift+Alt+Z) or disable the individual grid/axis options when a clean preview is required. Protocol completion is necessary but not sufficient; final scene acceptance also requires visual inspection in Blender.

Known 0.3.0 limits

  • PT successfully loads the validated 1.9-million-triangle bedroom scene. LVCBPT and LVCBPT + Proxy remain experimental; that complex scene still triggers an algorithm-side CUDA error during advanced preprocessing.
  • Camera-only navigation reuses the loaded scene. Geometry, material, texture, light, and World edits still perform a full GLB export and scene reload.
  • Cooperative cancellation normally reaches a warm-cache safe point quickly, but the first OptiX JIT compilation call cannot be interrupted from the Extension.
  • Alpha BLEND is currently binary cutout, not accumulated fractional opacity; transmission textures and importance-sampled emissive mesh lights remain future work.
  • The packaged release is Blender 5.2 / Windows x64 / NVIDIA only.

Verification

The automated suite covers protocol/process ownership, Blender conversion, fake and native F12, PT, LVCBPT, Proxy, SUN/World, textured normal materials, mirror/transmission/IOR, Alpha cutout, emissive textures, viewport policy, Blender 5.2 UI compatibility, and a real interactive GPU texture/draw callback. The main entry points are:

$repoRoot = (Resolve-Path '.').Path
$blender = 'C:\path\to\Blender 5.2\blender.exe'
$bridge = Join-Path $repoRoot 'build\native\bin\aurelia_bridge.exe'

& $blender `
  --background --factory-startup --python-exit-code 1 `
  --python (Join-Path $repoRoot 'tests\run_unittests.py') `
  -- $repoRoot

& $blender `
  --background --factory-startup --python-exit-code 1 `
  --python (Join-Path $repoRoot 'tests\blender_native_advanced_smoke.py') `
  -- $repoRoot $bridge LVCBPT_PROXY

The navigation acceptance briefly opens a Blender window, moves the viewport 20 times, and verifies multiple frames plus unchanged GLB mtime and Native scene generation:

$sentinel = Join-Path $repoRoot 'build\navigation-smoke.ok'
Remove-Item -LiteralPath $sentinel -ErrorAction SilentlyContinue
& $blender --factory-startup `
  --python (Join-Path $repoRoot 'tests\blender_viewport_camera_interactive_smoke.py') `
  -- $repoRoot $bridge $sentinel
Test-Path -LiteralPath $sentinel

Validate the Extension manifest before publishing:

& $blender --command extension validate aurelia_spcbpt

Isolated scene-package validation

Export the canonical geometry/material fixture once with Blender's headless CLI, then repeat structural checks with ordinary Python only:

$output = Join-Path $repoRoot 'build\validation\module-01-scene-package'
& $blender --background --factory-startup --python-exit-code 1 `
  --python (Join-Path $repoRoot 'tests\blender_scene_package_validation.py') `
  -- $repoRoot $output

python (Join-Path $repoRoot 'tools\validate_scene_package.py') `
  --request (Join-Path $output 'request.json') `
  --expect (Join-Path $output 'expected.json') `
  --report (Join-Path $output 'export_report.cli.json')

The second command does not import bpy, open Blender, or start CUDA. Expected success ends with AURELIA_SCENE_PACKAGE_OK.