Hello NVIDIA Developer Community,
I would like to share another real-time 3D rendering experiment that I have been developing on the NVIDIA Jetson Orin Nano Super.
This project combines a GLB character, an independently rendered first-person sword, CUDA-generated dynamic combat effects and OpenGL real-time rendering.
The main goal of this experiment is to investigate how increasingly complex GPU-generated attack geometry, particles, energy ribbons and screen-space effects behave on Jetson, especially when several effect layers are active at the same time.
Video Demonstration
The following video shows the current implementation:
The demonstration includes:
- A real-time GLB character
- An independently controlled first-person sword
- Multi-stage sword attack sequences
- GPU-generated particles
- Dynamic energy ribbons
- Circular and spiral attack geometry
- Screen-facing impact effects
- Large emissive combat effects
- Character hit/reaction states
- Combat-status HUD
- Multiple overlapping transparent VFX layers
The video is intended as a technical rendering demonstration rather than a formal performance benchmark.
Rendering Architecture
The current rendering path can be simplified as:
GLB Character Rendering
→ Weapon Transform Update
→ CUDA Combat Geometry Generation
→ CUDA/OpenGL Shared Buffers
→ OpenGL Effect Rendering
→ Transparent VFX Composition
→ Post-Processing / Bloom
The GLB character and sword are maintained as independent scene objects.
This allows the weapon transform and attack trajectory to be updated independently from the character model.
CUDA is mainly responsible for generating or updating dynamic effect data, while OpenGL performs the final rasterization.
CUDA-Generated Dynamic Geometry
Several of the attack effects shown in the video are generated procedurally.
CUDA updates data such as:
- Ribbon vertices
- Attack-path positions
- Particle positions
- Particle lifetime
- Spiral geometry
- Radial effect geometry
- Fragment direction
- Vertex opacity
- Emissive intensity
- Effect scale
- Rotation parameters
The intention is to avoid calculating large amounts of dynamic effect geometry on the CPU.
The resulting geometry can then be transferred directly into OpenGL rendering resources through CUDA–OpenGL interoperability.
CUDA–OpenGL Interoperability
One of the main areas I am currently investigating is synchronization between CUDA-generated geometry and OpenGL rendering.
The current workflow is approximately:
OpenGL VBO
→ CUDA resource mapping
→ CUDA kernel updates vertices
→ CUDA resource unmapping
→ OpenGL rendering
For effects that change every frame, repeated mapping, kernel execution and rendering may introduce synchronization overhead.
I am currently comparing approaches such as:
- Single-buffer rendering
- Double buffering
- Triple buffering
- Explicit OpenGL fences
- Separate CUDA streams
- Preallocated effect buffers
- Reduced synchronization between effect stages
I previously prepared a minimal CUDA–OpenGL sample to isolate this path, and I am now applying the same profiling methodology to the larger 3D scene.
Multi-Stage Combat Effects
The video contains several attack phases with very different GPU workloads.
Some phases contain only:
- A character
- A sword
- A small number of particles
Other phases simultaneously contain:
- Large transparent ribbons
- Radial geometry
- Multiple particle systems
- High-intensity emissive effects
- Full-screen energy structures
- Several overlapping transparent layers
This makes the project useful for observing how GPU load changes as effect complexity increases.
Transparency and Overdraw
One of the biggest performance concerns is transparent overdraw.
During the larger attacks, many translucent or additive surfaces overlap in the same screen area.
This can significantly increase fragment processing even if the actual geometry count is not extremely high.
I am currently investigating:
- Reducing unnecessary transparent pixels
- Culling expired effect geometry
- Limiting full-screen effect coverage
- Reducing particle count dynamically
- Rendering selected effects at reduced resolution
- Optimizing blend operations
- Adjusting effect quality according to GPU load
Emissive Effects and Bloom
The visual style uses high-intensity emissive effects.
During some attack phases, many bright layers overlap simultaneously.
This introduces another challenge: preserving the detail of the character and weapon while maintaining the intended high-energy appearance.
I am currently tuning:
- Emissive intensity
- HDR range
- Bloom threshold
- Exposure
- Tone mapping
- Additive blending
- Highlight preservation
The goal is to avoid losing character detail when very bright attacks fill a large part of the screen.
Performance Profiling
Based on previous feedback from the NVIDIA Developer Forum, I am also profiling the project using:
- tegrastats
- Nsight Systems
- CUDA event timing
- Per-frame CPU/GPU timing
I am particularly interested in determining whether the main bottleneck during the largest attacks comes from:
- CUDA geometry generation
- CUDA–OpenGL synchronization
- OpenGL vertex processing
- Transparent fragment overdraw
- Post-processing
- CPU/GPU synchronization
The visual complexity changes substantially during the approximately one-minute effect sequence, so profiling each attack phase independently may provide more useful information than looking only at average FPS.
Current Development Focus
My current optimization areas are:
- CUDA–OpenGL synchronization
- Dynamic VBO management
- Transparent-effect overdraw
- Particle workload scaling
- Reduced-resolution VFX rendering
- Bloom and exposure stability
- GPU utilization analysis
- Frame-time stability
- Minimizing CPU-side effect generation
- Maintaining stable performance during large multi-layer attacks
Questions for the Community
I would appreciate feedback on several points:
-
For dynamic combat geometry that is regenerated every frame, is CUDA writing directly into registered OpenGL VBOs still a good approach on Jetson Orin Nano?
-
For workloads with many overlapping transparent ribbons and particles, is fragment overdraw likely to become a larger bottleneck than CUDA vertex generation?
-
Would rendering large transparent VFX into a half-resolution or quarter-resolution framebuffer be a reasonable optimization on Jetson?
-
For CUDA–OpenGL interoperability, would triple-buffered VBOs generally help reduce synchronization stalls compared with reusing one buffer every frame?
-
Is there a recommended Nsight Systems workflow for separating CUDA kernel time, CUDA–OpenGL synchronization time and OpenGL rendering stalls?
-
When the GPU is not fully utilized but frame time is still unstable, which synchronization points would you recommend checking first?
If useful, I can also isolate one of the larger sword-effect stages into a smaller reproducible sample for profiling.
Thank you for reading.
Any feedback regarding CUDA–OpenGL interoperability, dynamic GPU geometry, transparent rendering or Jetson-specific graphics optimization would be greatly appreciated.
