import { BlurPostProcess, PassPostProcess, Vector2 } from '../loader/babylonjs-import';
import { SSAOApplier } from './SSAOApplier';
import { SSAOCalculator } from './SSAOCalculator';
import { telemetry } from '../Telemetry';
import { SeverityLevel } from '@microsoft/applicationinsights-web';
const DEFAULT_SAMPLE_KERNEL_SIZE_COUNT = 16;
const DEFAULT_STRENGTH = 0.0513;
const DEFAULT_RADIUS = 0.85;
const DEFAULT_BLUR_SIZE = 16.0;
const DEFAULT_RENDER_SCALE = 1.0;
const SAMPLES_COUNT_NAME = 'Samples count';
const STRENGTH_NAME = 'Strength';
const RADIUS_NAME = 'Samples count';
const BLUR_NAME = 'Blur size';
const RENDER_SCALE_NAME = 'Render scale';
const ensureNotNegative = function (value, name) {
    if (value < 0.0) {
        console.warn(name + ' for SSAO was less than zero, set to 0 instead');
        value = 0;
    }
    return value;
};
const ensureValueIsSet = function (value, defaultFallBack) {
    if (!value) {
        value = defaultFallBack;
    }
    return value;
};
const ensureValueIsWholeNumber = function (value, name) {
    if (value % 1 !== 0) {
        value = Math.floor(value);
        console.warn(name + ' size for SSAO was given as a decimal number, rounding down to a whole number');
    }
    return value;
};
/**
 * This class sets up the postprocess pipeline for achieving the SSAO effect
 * First, the current screen is written to a buffer (screenBlit)
 * Secondly, SSAO for the current screen is calculated using the depth buffer
 * Thirdly, the contents of the SSAO post process, which is what is currently bound to the screen is blurred first horizontally and then the blurred result is further blurred vertically
 * Lastly the SSAO buffer is used to darken the color of the screen buffer
 */
export class SSAOPipeline {
    _ssaoCalculator;
    _ssaoApplier;
    _horizontalBlur;
    _verticalBlur;
    _screenBlit;
    attach(camera) {
        this._screenBlit = new PassPostProcess('screen blit', 1.0, camera);
        this._ssaoCalculator = new SSAOCalculator(this._settings.samplesCount, this._settings.strength, this._settings.radius, this._settings.renderScale);
        const ssaoAttached = this._ssaoCalculator.attach(camera);
        // Create two blur post processes to blur the SSAO (one going horizontally and one vertically which blurs the already horizontally blurred texture)
        // Scale the blur with the renderscale
        const blurSize = this._settings.blurSize;
        this._horizontalBlur = new BlurPostProcess('Horizontal blur', new Vector2(1.0, 0), blurSize, this._settings.renderScale, camera);
        this._verticalBlur = new BlurPostProcess('Vertical blur', new Vector2(0, 1.0), blurSize, this._settings.renderScale, camera);
        this._ssaoApplier = new SSAOApplier(this._screenBlit, this._settings.renderScale);
        this._ssaoApplier.attach(camera);
        return ssaoAttached;
    }
    detach(camera) {
        this._ssaoApplier.detach(camera);
        this._ssaoCalculator.detach(camera);
        camera.detachPostProcess(this._horizontalBlur);
        camera.detachPostProcess(this._verticalBlur);
        camera.detachPostProcess(this._screenBlit);
        return true;
    }
    _settings;
    constructor(samplesCount, strength, blurSize, radius, renderScale) {
        samplesCount = ensureValueIsSet(samplesCount, DEFAULT_SAMPLE_KERNEL_SIZE_COUNT);
        strength = ensureValueIsSet(strength, DEFAULT_STRENGTH);
        radius = ensureValueIsSet(radius, DEFAULT_RADIUS);
        blurSize = ensureValueIsSet(blurSize, DEFAULT_BLUR_SIZE);
        renderScale = ensureValueIsSet(renderScale, DEFAULT_RENDER_SCALE);
        samplesCount = ensureNotNegative(samplesCount, SAMPLES_COUNT_NAME);
        strength = ensureNotNegative(strength, STRENGTH_NAME);
        radius = ensureNotNegative(radius, RADIUS_NAME);
        blurSize = ensureNotNegative(blurSize, BLUR_NAME);
        renderScale = ensureNotNegative(renderScale, RENDER_SCALE_NAME);
        if (renderScale > 1.0) {
            telemetry.trackTrace({
                message: 'Render scale larger than 1.0, setting it to 1.0',
                severityLevel: SeverityLevel.Warning
            });
            renderScale = 1.0;
        }
        samplesCount = ensureValueIsWholeNumber(samplesCount, SAMPLES_COUNT_NAME);
        blurSize = ensureValueIsWholeNumber(blurSize, BLUR_NAME);
        this._settings = {
            samplesCount: samplesCount,
            strength: strength,
            blurSize: blurSize,
            radius: radius,
            renderScale: renderScale
        };
    }
    set strength(strength) {
        this._settings.strength = strength;
        this._ssaoCalculator.strength = strength;
    }
    get strength() {
        return this._settings.strength;
    }
    set samplesCount(samples) {
        samples = ensureValueIsWholeNumber(samples, SAMPLES_COUNT_NAME);
        this._settings.samplesCount = samples;
        this._ssaoCalculator.samples = samples;
    }
    get samplesCount() {
        return this._settings.samplesCount;
    }
}
//# sourceMappingURL=SSAOPipeline.js.map