import { Effect, PostProcess, Vector2 } from '../loader/babylonjs-import';
import { outlineCalculatorShader } from '../loader/CustomBabylonMaterials/shaders/OutlineCalculatorShader';
import { RESOLUTION } from '../loader/ShaderConstants';
import { TwinfinityPostProcess } from './TwinfinityPostProcess';
const SHADER_NAME_PREFIX = 'outlines';
const OUTLINES_SAMPLER = 'outlinesSampler';
const SAMPLE_KERNEL_SIZE = 'sampleKernelSize';
const SAMPLE_KERNEL = 'sampleKernel';
const OUTLINE_COLOR = 'outlineColor';
const UNIFIED_OUTLINE = 'unifiedOutline';
export class OutlineCalculator extends TwinfinityPostProcess {
    _outlineRenderTargetTexture;
    _renderScale;
    _unifiedOutlines;
    _outlineColor;
    _samples = 4;
    _kernel = [];
    getDefines() {
        const defines = [];
        defines.push(`#define ${SAMPLE_KERNEL_SIZE} ${this._samples}`);
        if (this._unifiedOutlines) {
            defines.push(`#define ${UNIFIED_OUTLINE}`);
        }
        return defines.join('\n');
    }
    getUniforms() {
        const uniforms = [RESOLUTION, OUTLINE_COLOR];
        for (let i = 0; i < this._kernel.length; i++) {
            uniforms.push(SAMPLE_KERNEL + '[' + i + ']');
        }
        return uniforms;
    }
    getSamplers() {
        return [OUTLINES_SAMPLER];
    }
    initialize(camera) {
        const engine = camera.getEngine();
        this._kernel.push(new Vector2(-1.0, 0.0));
        this._kernel.push(new Vector2(1.0, 0.0));
        this._kernel.push(new Vector2(0.0, -1.0));
        this._kernel.push(new Vector2(0.0, 1.0));
        if (this._postProcess === undefined) {
            Effect.ShadersStore[SHADER_NAME_PREFIX + 'FragmentShader'] = outlineCalculatorShader.fragment();
            const newPostProcess = new PostProcess('OUTLINES', SHADER_NAME_PREFIX, this.getUniforms(), this.getSamplers(), {
                // Do not include scale here, because that would mean that the postprocess before this one (this blit) would be resized, because Babylonjs has really weird rules for this
                width: engine.getRenderWidth(true) * this._renderScale,
                height: engine.getRenderHeight(true) * this._renderScale
            }, null, undefined, engine, false, this.getDefines());
            newPostProcess.onApplyObservable.add((effect) => {
                effect.setTexture(OUTLINES_SAMPLER, this._outlineRenderTargetTexture);
                const resolutionX = 1.0 / engine.getRenderWidth(false);
                const resolutionY = 1.0 / engine.getRenderHeight(false);
                effect.setFloat2(RESOLUTION, resolutionX, resolutionY);
                effect.setVector3(OUTLINE_COLOR, this._outlineColor);
                for (let i = 0; i < this._kernel.length; i++) {
                    const kernelSample = this._kernel[i];
                    const sampleKernelUniformName = `${SAMPLE_KERNEL}[${i}]`;
                    effect.setVector2(sampleKernelUniformName, kernelSample);
                }
            });
            this._postProcess = newPostProcess;
            return newPostProcess;
        }
        else
            return this._postProcess;
    }
    constructor(_outlineRenderTargetTexture, _renderScale, _unifiedOutlines, _outlineColor) {
        super();
        this._outlineRenderTargetTexture = _outlineRenderTargetTexture;
        this._renderScale = _renderScale;
        this._unifiedOutlines = _unifiedOutlines;
        this._outlineColor = _outlineColor;
    }
}
//# sourceMappingURL=OutlineCalculator.js.map