VIZ3D Three.js Performance Tuning Guide
Date: 2025-10-25 Version: Phase 2
Overview
This guide helps you optimize Three.js volume rendering performance based on your volume size and hardware capabilities.
Key Parameters
1. Step Size (u_stepSize)
Default: 0.01
Controls the distance between ray samples. Smaller = better quality, slower performance.
| Step Size | Quality | Performance | Use Case |
|---|---|---|---|
| 0.001 | Excellent | Very Slow | High-quality screenshots, small volumes (< 16³) |
| 0.005 | High | Slow | Detailed exploration, medium volumes (32³-64³) |
| 0.01 | Good | Fast | Default, balanced quality/speed |
| 0.02 | Medium | Very Fast | Large volumes (> 128³), real-time interaction |
| 0.05 | Low | Fastest | Initial exploration, huge volumes |
Formula: stepSize ≈ 1.0 / (volumeDim × desiredSamples)
Example for 64³ volume:
- High quality:
1.0 / (64 × 4) = 0.0039 - Medium:
1.0 / (64 × 2) = 0.0078 - Fast:
1.0 / (64 × 1) = 0.0156
2. Max Steps (u_maxSteps)
Default: 256
Maximum number of ray samples per pixel.
| Max Steps | Memory | Performance | Use Case |
|---|---|---|---|
| 64 | Low | Very Fast | Quick previews |
| 128 | Low | Fast | Interactive exploration |
| 256 | Medium | Good | Default balanced setting |
| 512 | High | Slow | High-quality rendering |
Auto-calculation:
maxSteps = ceil(sqrt(3) / stepSize)
This ensures rays can traverse the volume diagonal.
3. Threshold (u_threshold)
Default: 0.1
Filters out low-density voxels.
- Lower (0.0-0.1): Show all data, slower
- Medium (0.1-0.3): Good default, balanced
- Higher (0.3-0.5): Only show dense regions, faster
Performance Impact: Higher thresholds can improve performance by 2-5x by skipping empty space.
4. Lighting (u_enableLighting)
Default: true
Gradient-based Phong lighting.
Performance Cost: ~15-20% FPS reduction Visual Benefit: Much better depth perception and structure visibility
Recommendation:
- Disable for fast interaction
- Enable for final visualization
Recommended Settings by Volume Size
Small Volumes (< 32³, < 32K voxels)
; Optimize for quality
stepSize: 0.005
maxSteps: 512
enableLighting: true
threshold: 0.05
Expected FPS: 60 FPS
Medium Volumes (32³-64³, 32K-262K voxels)
; Balanced quality/performance
stepSize: 0.01
maxSteps: 256
enableLighting: true
threshold: 0.1
Expected FPS: 30-45 FPS
Large Volumes (64³-128³, 262K-2M voxels)
; Optimize for performance
stepSize: 0.015
maxSteps: 192
enableLighting: false
threshold: 0.2
Expected FPS: 15-30 FPS
Huge Volumes (> 128³, > 2M voxels)
; Maximum performance
stepSize: 0.02
maxSteps: 128
enableLighting: false
threshold: 0.3
Expected FPS: 5-15 FPS
Hardware Considerations
GPU Performance Tiers
High-End (e.g., NVIDIA RTX 4080, Apple M3 Max)
- Can handle large volumes at default settings
- Increase maxSteps to 512 for better quality
- Reduce stepSize to 0.005 for maximum detail
Mid-Range (e.g., NVIDIA GTX 1660, Apple M1)
- Use recommended settings above
- May need to reduce quality for volumes > 64³
Low-End (e.g., Integrated graphics)
- Reduce stepSize to 0.02
- Reduce maxSteps to 128
- Disable lighting
- Increase threshold to 0.3+
Browser Performance
Chrome/Edge (Chromium)
- Best WebGL performance
- Use default settings
Firefox
- ~10-15% slower than Chrome
- Reduce maxSteps by 25% if needed
Safari
- ~20-30% slower than Chrome
- Use more aggressive performance settings
Optimization Techniques
1. Adaptive Quality
Start with low quality for interaction, increase for final view:
// In GUI controller
params.interacting = false;
controls.addEventListener('start', () => {
params.interacting = true;
material.uniforms.u_stepSize.value = 0.02; // Fast
material.uniforms.u_maxSteps.value = 128;
});
controls.addEventListener('end', () => {
params.interacting = false;
material.uniforms.u_stepSize.value = 0.01; // Quality
material.uniforms.u_maxSteps.value = 256;
});
2. Level of Detail (LOD)
Use lower resolution volumes for distant views:
; Create LOD hierarchy
volume_high = CONGRID(volume, 128, 128, 128) ; Full detail
volume_med = CONGRID(volume, 64, 64, 64) ; 1/8 voxels
volume_low = CONGRID(volume, 32, 32, 32) ; 1/64 voxels
; Switch based on zoom level
3. Empty Space Skipping
Increase threshold to skip transparent regions:
// Automatically adjust threshold based on histogram
const histogram = computeHistogram(volumeData);
const cumulativeSum = computeCumulativeSum(histogram);
const threshold = findPercentile(cumulativeSum, 0.05); // Skip bottom 5%
Profiling
Browser DevTools
Open Chrome DevTools (F12) → Performance tab:
- Start recording
- Interact with volume
- Stop recording
- Look for:
- GPU utilization: Should be > 80%
- Frame time: < 16ms for 60 FPS
- JavaScript time: Should be minimal (< 1ms)
Performance Metrics
Add FPS counter to GUI:
const stats = {
fps: 0,
frameCount: 0,
lastTime: performance.now(),
};
function animate() {
const now = performance.now();
stats.frameCount++;
if (now - stats.lastTime > 1000) {
stats.fps = Math.round(stats.frameCount / ((now - stats.lastTime) / 1000));
stats.frameCount = 0;
stats.lastTime = now;
console.log(`FPS: ${stats.fps}`);
}
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
Troubleshooting
Problem: Low FPS (< 15)
Solutions:
- Increase stepSize to 0.02
- Reduce maxSteps to 128
- Disable lighting
- Increase threshold
- Close other GPU-intensive applications
Problem: Blocky/Pixelated Appearance
Solutions:
- Reduce stepSize (more samples)
- Increase maxSteps
- Enable lighting for better structure
- Check volume data quality
Problem: Empty/Black Window
Solutions:
- Lower threshold to 0.0
- Check volume data range (normalize to [0, 1])
- Increase opacity
- Verify colormap is loading
Problem: Browser Crashes
Solutions:
- Reduce volume size
- Reduce maxSteps significantly (< 128)
- Check available GPU memory
- Try a different browser (Chrome recommended)
Best Practices
- Start with defaults - Adjust only if needed
- Profile first - Use DevTools to identify bottlenecks
- Test incrementally - Change one parameter at a time
- Cache volumes - Don’t regenerate data unnecessarily
- Use appropriate data types - Float32 for volume data
- Normalize data - Keep values in [0, 1] range
- Monitor GPU memory - Large volumes can exhaust VRAM
Example Configurations
High-Quality Screenshot
params.stepSize = 0.003;
params.maxSteps = 512;
params.enableLighting = true;
params.threshold = 0.02;
params.ambient = 0.2;
params.diffuse = 0.7;
params.specular = 0.4;
params.shininess = 64.0;
Real-Time Interaction
params.stepSize = 0.015;
params.maxSteps = 192;
params.enableLighting = false;
params.threshold = 0.15;
Balanced Default
params.stepSize = 0.01;
params.maxSteps = 256;
params.enableLighting = true;
params.threshold = 0.1;
params.ambient = 0.3;
params.diffuse = 0.6;
params.specular = 0.3;
params.shininess = 32.0;
Performance Checklist
- Volume size appropriate for hardware?
- Step size optimized for volume dimensions?
- Max steps set based on quality needs?
- Threshold adjusted to skip empty space?
- Lighting disabled if not needed?
- Browser using GPU acceleration?
- No other GPU-intensive apps running?
- Volume data normalized to [0, 1]?
- FPS monitoring enabled?
- Tested in target browser?
Status: Phase 2 Complete Last Updated: 2025-10-25