n8ao

repository·master·Indexed 19 days ago

https://github.com/n8python/n8ao

An efficient Screen Space Ambient Occlusion (SSAO) implementation for three.js, version 2.0.0. It focuses on temporal stability through neural denoising and artist-friendly controls. The library provides N8AOPass for standard three.js setups and N8AOPostPass for use with the pmndrs/postprocessing library. Key features include various quality presets (from Performance to Neural-High), half-resolution mode for optimization, transparency support, and customizable visual parameters like aoRadius and intensity.

Tokens
5.9K
Snippets
27
Records
28
Agent score
64%

What's inside n8ao

  1. Use a custom Render Target with N8AO

    master

    To use a pre-existing render target with a depth buffer instead of letting N8AO generate a new one:

    1. Assign your target to n8aopass.beautyRenderTarget.
    2. Set n8aopass.configuration.autoRenderBeauty = false.
    3. Ensure your target has a depthTexture attached, otherwise N8AO may fail silently.
    const renderTarget = new THREE.WebGLRenderTarget(width, height);
    // Attach depth texture
    renderTarget.depthTexture = new THREE.DepthTexture(width, height, THREE.UnsignedIntType);
    renderTarget.depthTexture.format = THREE.DepthFormat;
    
    // Configure pass
    n8aopass.beautyRenderTarget = renderTarget;
    n8aopass.configuration.autoRenderBeauty = false;
  2. Use N8AOPostPass with pmndrs/postprocessing

    master

    If you are using the pmndrs/postprocessing library, use N8AOPostPass. Unlike the standard pass, N8AOPostPass requires a RenderPass to be added to the composer before it.

    import { N8AOPostPass } from "n8ao";
    import { EffectComposer, RenderPass } from "postprocessing";
    
    const composer = new EffectComposer(renderer);
    /* N8AOPostPass requires a RenderPass before it */
    composer.addPass(new RenderPass(scene, camera));
    const n8aopass = new N8AOPostPass(
        scene,
        camera,
        width,
        height
    );
    composer.addPass(n8aopass);
  3. Install N8AO

    master

    You can install N8AO via npm or use it directly from a CDN. Note that three and postprocessing must be available in your environment.

    npm install n8ao
    // npm import
    import { N8AOPass } from "n8ao";
    
    // CDN import
    import { N8AOPass } from "https://unpkg.com/n8ao@latest/dist/N8AO.js";
  4. Use N8AOPass with standard three.js

    master

    In a standard three.js setup, N8AOPass acts as a replacement for the RenderPass within an EffectComposer. It works out of the box as long as the depth buffer is being written to.

    const composer = new EffectComposer(renderer);
    // N8AOPass replaces RenderPass
    const n8aopass = new N8AOPass(
            scene,
            camera,
            width,
            height
        );
    composer.addPass(n8aopass);
  5. Enable Transparency Awareness

    master

    By default, AO only considers opaque geometry. If your scene contains transparent objects that should interact with or be affected by AO, you must enable transparencyAware in the configuration.

    When enabled, the pass performs additional rendering steps to capture transparent geometry and its depth, ensuring they are correctly integrated into the AO calculation.

    // Enable AO for transparent objects
    aoPass.configuration.transparencyAware = true;
  6. Adjust AO Bias and Tones

    master

    If you encounter artifacts, you can manually adjust the bias or the quantization of the AO effect:

    • Bias Adjustment: Use configuration.biasOffset and configuration.biasMultiplier. The in-shader calculation is bias = biasOffset + biasMultiplier * bias. Only adjust these if you are experiencing specific artifacts.
    • AO Tones: Use configuration.aoTones to quantize the AO effect into a specific number of tones (useful for toon shading or bevel effects). A value of 0 (default) results in a continuous AO effect.
    n8aopass.configuration.biasOffset = 0.01;
    n8aopass.configuration.biasMultiplier = 1.0;
    n8aopass.configuration.aoTones = 4; // Quantize into 4 tones
  7. Enable temporal accumulation for still cameras

    master

    When the camera is stationary, you can enable sample accumulation across frames to reduce noise and improve quality by setting configuration.accumulate = true.

    Best Practices:

    • For the best results (purely temporal accumulation without blurring), set denoiseRadius to 0 and denoiseSamples to 1.
    • Limitation: Accumulation only works when the camera is still. If the camera moves, accumulation is automatically disabled. If an object moves while the camera is still, the AO on that object will appear blurred.
    n8aopass.configuration.accumulate = true;
    // Recommended settings for pure temporal accumulation:
    n8aopass.configuration.denoiseRadius = 0;
    n8aopass.configuration.denoiseSamples = 1;
  8. Configure Transparency support

    master

    N8AO supports transparency by using an auxiliary render target to store accumulated alpha. This requires transparent objects to be rendered twice, which can impact performance if many transparent objects are present.

    • Automatic Detection: Enabled by default. Set configuration.transparencyAware = true to enable or false to disable automatic detection.
    • Treat as Opaque: To force a transparent object to be treated as opaque (e.g., for ShadowMesh), set mesh.userData.treatAsOpaque = true.
    • Disable AO for Object: To prevent an object from receiving any AO, set mesh.userData.cannotReceiveAO = true (Note: this also requires rendering the object twice).
    n8aopass.configuration.transparencyAware = true;
    
    // Per-object control
    mesh.userData.treatAsOpaque = true;
    mesh.userData.cannotReceiveAO = true;
  9. Use Neural Denoising in N8AO

    master

    Neural denoising is a high-quality denoising mode in N8AOPostPass. However, it has strict requirements. If these requirements are not met, the pass will automatically fallback to standard Poisson blur denoising and issue a console warning.

    Requirements for Neural Denoising:

    1. neuralDenoise must be true.
    2. aoSamples must be exactly 16.
    3. denoiseSamples must be one of [4, 8, 16].
    4. denoiseRadius must be exactly 12.
    5. denoiseIterations must be exactly 2.
    6. halfRes must be false (full resolution is required).
  10. Optimize performance with half-resolution mode

    master

    To improve performance in critical applications, you can enable halfRes mode. This calculates Ambient Occlusion at half the screen resolution and then upscales it. This typically provides a 2x-4x performance boost at the cost of fine detail and temporal stability.

    By default, it uses depth-aware upscaling. If performance is extremely critical, you can disable depth-aware upscaling by setting depthAwareUpsampling to false, though this is not recommended as the effect quality degrades significantly.

    n8aopass.configuration.halfRes = true;
    // Optional: disable depth-aware upscaling if performance is critical
    n8aopass.configuration.depthAwareUpsampling = false;
  11. Configure Screen Space Radius

    master

    If your camera moves across vastly different scales, set configuration.screenSpaceRadius to true.

    When enabled:

    • aoRadius becomes the size in pixels (recommended: 16 to 64).
    • distanceFalloff becomes a ratio representing the percentage of the screen space radius at which AO fades (recommended: 0.2).
    n8aopass.configuration.screenSpaceRadius = true;
    n8aopass.configuration.aoRadius = 32; // 32 pixels
    n8aopass.configuration.distanceFalloff = 0.2;
  12. Enable Stencil Buffer support

    master

    To use stencil buffers with N8AOPass, you must explicitly enable it in the configuration.

    Note for N8AOPostPass users: If using N8AOPostPass with pmndrs/postprocessing, you must configure the EffectComposer to support stencils, as the pass itself does not provide a stencil option.

    n8aopass.configuration.stencil = true;
    
    // If using N8AOPostPass with pmndrs/postprocessing:
    const composer = new EffectComposer(renderer, {
        stencilBuffer: true,
        depthBuffer: true,
        frameBufferType: THREE.HalfFloatType
    });