import { Camera, Effect, PostProcess } from '../loader/babylonjs-import';
import { ditherBlurApplierShader } from '../loader/CustomBabylonMaterials/shaders/DitherBlurApplierShader';
import { TwinfinityPostProcess } from './TwinfinityPostProcess';
const SHADER_NAME_PREFIX = 'ditherBlurApplier';
const SCREEN_SAMPLER = 'screenSampler';
const BLURRED_DITHER_SAMPLER = 'blurredDitherSampler';
const DEPTH_SAMPLER = 'depthSampler';
const DEPTH_FAR_PLANE = 'depthFarPlane';
const DEPTH_NEAR_PLANE = 'depthNearPlane';
const IS_PERSPECTIVE_CAMERA = 'isPerspective';
const UNBLUR_AT_DISTANCE = 'unblurAtDistance';
const ORTHO_CAMERA_FRUSTUM_SIZE = 'orthoSize';
const ADAPTIVE_MINZ = 'adaptiveMinZ';
/**
 * DitherBlurApplier is the class that blends the blurred dither with the screen contexnt
 * The variable called blittedscreen is a postprocess that just writes the current scene to a texture buffer
 */
export class DitherBlurApplier extends TwinfinityPostProcess {
    _blitedScreen;
    _shortFrustumDepthRenderer;
    constructor(_blitedScreen) {
        super();
        this._blitedScreen = _blitedScreen;
    }
    initialize(camera) {
        const engine = camera.getEngine();
        const defines = new Array();
        if (this._postProcess === undefined) {
            Effect.ShadersStore[SHADER_NAME_PREFIX + 'FragmentShader'] = ditherBlurApplierShader.fragment();
            const uniforms = [
                DEPTH_NEAR_PLANE,
                DEPTH_FAR_PLANE,
                ORTHO_CAMERA_FRUSTUM_SIZE,
                IS_PERSPECTIVE_CAMERA,
                UNBLUR_AT_DISTANCE,
                ADAPTIVE_MINZ
            ];
            const samplers = [SCREEN_SAMPLER, BLURRED_DITHER_SAMPLER, DEPTH_SAMPLER];
            const newPostProcess = new PostProcess('Dither_blur_applier', SHADER_NAME_PREFIX, uniforms, samplers, 1.0, null, undefined, engine, false, defines.join('\n'));
            const viewer = camera.getScene().twinfinity.viewer;
            if (viewer) {
                newPostProcess.onApplyObservable.add((effect) => {
                    effect.setTextureFromPostProcess(SCREEN_SAMPLER, this._blitedScreen);
                    effect.setTextureFromPostProcess(BLURRED_DITHER_SAMPLER, newPostProcess); // Babylon is trippy in the way that this call will set the texture to the current screen as it was BEFORE newPostProcess is applied
                    effect.setBool(UNBLUR_AT_DISTANCE, camera.twinfinity.viewer.visualSettings.ifc.transparency.ditheringOptions.distanceFade);
                    if (camera.twinfinity.viewer.visualSettings.ifc.transparency.ditheringOptions.distanceFade) {
                        this._shortFrustumDepthRenderer = viewer.enableDepthRenderer(true);
                        effect.setBool(IS_PERSPECTIVE_CAMERA, camera.mode === Camera.PERSPECTIVE_CAMERA);
                        if (camera.mode === Camera.ORTHOGRAPHIC_CAMERA) {
                            const deltaVert = camera.orthoTop - camera.orthoBottom;
                            const deltaHorizontal = camera.orthoRight - camera.orthoLeft;
                            effect.setFloat(ORTHO_CAMERA_FRUSTUM_SIZE, deltaVert + deltaHorizontal);
                        }
                        else {
                            effect.setTexture(DEPTH_SAMPLER, this._shortFrustumDepthRenderer.depthRenderer.getDepthMap());
                            effect.setFloat(ADAPTIVE_MINZ, camera.twinfinity.viewer.adaptiveMinZ
                                ? camera.minZ
                                : camera.twinfinity.viewer._meshDistanceToCamera.minDistanceToCamera);
                            effect.setFloat(DEPTH_NEAR_PLANE, this._shortFrustumDepthRenderer.shortFrustumProjectionMatrixState.depthRenderCameraMinZ);
                            effect.setFloat(DEPTH_FAR_PLANE, this._shortFrustumDepthRenderer.shortFrustumProjectionMatrixState.depthRenderCameraMaxZ);
                        }
                    }
                });
            }
            else {
                throw new Error('No viewer created?');
            }
            return newPostProcess;
        }
        else
            return this._postProcess;
    }
}
//# sourceMappingURL=DitherBlurApplier.js.map