UNPKG

@babylonjs/core

Version:

Getting started? Play directly with the Babylon.js API using our [playground](https://playground.babylonjs.com/). It also contains a lot of samples to learn how to use it.

464 lines (463 loc) 17.6 kB
import { Texture } from "../../../Materials/Textures/texture.js"; import { PostProcess } from "../../../PostProcesses/postProcess.js"; import { PostProcessRenderPipeline } from "../../../PostProcesses/RenderPipeline/postProcessRenderPipeline.js"; import { PostProcessRenderEffect } from "../../../PostProcesses/RenderPipeline/postProcessRenderEffect.js"; import { RawTexture } from "../../../Materials/Textures/rawTexture.js"; import "../../../PostProcesses/RenderPipeline/postProcessRenderPipelineManagerSceneComponent.js"; import "../../../Shaders/chromaticAberration.fragment.js"; import "../../../Shaders/lensHighlights.fragment.js"; import "../../../Shaders/depthOfField.fragment.js"; import { RandomRange } from "../../../Maths/math.scalar.functions.js"; /** * BABYLON.JS Chromatic Aberration GLSL Shader * Author: Olivier Guyot * Separates very slightly R, G and B colors on the edges of the screen * Inspired by Francois Tarlier & Martins Upitis */ export class LensRenderingPipeline extends PostProcessRenderPipeline { /** * @constructor * * Effect parameters are as follow: * { * chromatic_aberration: number; // from 0 to x (1 for realism) * edge_blur: number; // from 0 to x (1 for realism) * distortion: number; // from 0 to x (1 for realism), note that this will effect the pointer position precision * grain_amount: number; // from 0 to 1 * grain_texture: BABYLON.Texture; // texture to use for grain effect; if unset, use random B&W noise * dof_focus_distance: number; // depth-of-field: focus distance; unset to disable (disabled by default) * dof_aperture: number; // depth-of-field: focus blur bias (default: 1) * dof_darken: number; // depth-of-field: darken that which is out of focus (from 0 to 1, disabled by default) * dof_pentagon: boolean; // depth-of-field: makes a pentagon-like "bokeh" effect * dof_gain: number; // depth-of-field: highlights gain; unset to disable (disabled by default) * dof_threshold: number; // depth-of-field: highlights threshold (default: 1) * blur_noise: boolean; // add a little bit of noise to the blur (default: true) * } * Note: if an effect parameter is unset, effect is disabled * * @param name The rendering pipeline name * @param parameters - An object containing all parameters (see above) * @param scene The scene linked to this pipeline * @param ratio The size of the postprocesses (0.5 means that your postprocess will have a width = canvas.width 0.5 and a height = canvas.height 0.5) * @param cameras The array of cameras that the rendering pipeline will be attached to */ constructor(name, parameters, scene, ratio = 1.0, cameras) { super(scene.getEngine(), name); // Lens effects can be of the following: // - chromatic aberration (slight shift of RGB colors) // - blur on the edge of the lens // - lens distortion // - depth-of-field blur & highlights enhancing // - depth-of-field 'bokeh' effect (shapes appearing in blurred areas) // - grain effect (noise or custom texture) // Two additional texture samplers are needed: // - depth map (for depth-of-field) // - grain texture /** * @ignore * The chromatic aberration PostProcess id in the pipeline */ this.LensChromaticAberrationEffect = "LensChromaticAberrationEffect"; /** * @ignore * The highlights enhancing PostProcess id in the pipeline */ this.HighlightsEnhancingEffect = "HighlightsEnhancingEffect"; /** * @ignore * The depth-of-field PostProcess id in the pipeline */ this.LensDepthOfFieldEffect = "LensDepthOfFieldEffect"; this._pentagonBokehIsEnabled = false; this._scene = scene; // Fetch texture samplers this._depthTexture = scene.enableDepthRenderer().getDepthMap(); // Force depth renderer "on" if (parameters.grain_texture) { this._grainTexture = parameters.grain_texture; } else { this._createGrainTexture(); } // save parameters this._edgeBlur = parameters.edge_blur ? parameters.edge_blur : 0; this._grainAmount = parameters.grain_amount ? parameters.grain_amount : 0; this._chromaticAberration = parameters.chromatic_aberration ? parameters.chromatic_aberration : 0; this._distortion = parameters.distortion ? parameters.distortion : 0; this._highlightsGain = parameters.dof_gain !== undefined ? parameters.dof_gain : -1; this._highlightsThreshold = parameters.dof_threshold ? parameters.dof_threshold : 1; this._dofDistance = parameters.dof_focus_distance !== undefined ? parameters.dof_focus_distance : -1; this._dofAperture = parameters.dof_aperture ? parameters.dof_aperture : 1; this._dofDarken = parameters.dof_darken ? parameters.dof_darken : 0; this._dofPentagon = parameters.dof_pentagon !== undefined ? parameters.dof_pentagon : true; this._blurNoise = parameters.blur_noise !== undefined ? parameters.blur_noise : true; // Create effects this._createChromaticAberrationPostProcess(ratio); this._createHighlightsPostProcess(ratio); this._createDepthOfFieldPostProcess(ratio / 4); // Set up pipeline this.addEffect(new PostProcessRenderEffect(scene.getEngine(), this.LensChromaticAberrationEffect, () => { return this._chromaticAberrationPostProcess; }, true)); this.addEffect(new PostProcessRenderEffect(scene.getEngine(), this.HighlightsEnhancingEffect, () => { return this._highlightsPostProcess; }, true)); this.addEffect(new PostProcessRenderEffect(scene.getEngine(), this.LensDepthOfFieldEffect, () => { return this._depthOfFieldPostProcess; }, true)); if (this._highlightsGain === -1) { this._disableEffect(this.HighlightsEnhancingEffect, null); } // Finish scene.postProcessRenderPipelineManager.addPipeline(this); if (cameras) { scene.postProcessRenderPipelineManager.attachCamerasToRenderPipeline(name, cameras); } } /** * Get the class name * @returns "LensRenderingPipeline" */ getClassName() { return "LensRenderingPipeline"; } // Properties /** * Gets associated scene */ get scene() { return this._scene; } /** * Gets or sets the edge blur */ get edgeBlur() { return this._edgeBlur; } set edgeBlur(value) { this.setEdgeBlur(value); } /** * Gets or sets the grain amount */ get grainAmount() { return this._grainAmount; } set grainAmount(value) { this.setGrainAmount(value); } /** * Gets or sets the chromatic aberration amount */ get chromaticAberration() { return this._chromaticAberration; } set chromaticAberration(value) { this.setChromaticAberration(value); } /** * Gets or sets the depth of field aperture */ get dofAperture() { return this._dofAperture; } set dofAperture(value) { this.setAperture(value); } /** * Gets or sets the edge distortion */ get edgeDistortion() { return this._distortion; } set edgeDistortion(value) { this.setEdgeDistortion(value); } /** * Gets or sets the depth of field distortion */ get dofDistortion() { return this._dofDistance; } set dofDistortion(value) { this.setFocusDistance(value); } /** * Gets or sets the darken out of focus amount */ get darkenOutOfFocus() { return this._dofDarken; } set darkenOutOfFocus(value) { this.setDarkenOutOfFocus(value); } /** * Gets or sets a boolean indicating if blur noise is enabled */ get blurNoise() { return this._blurNoise; } set blurNoise(value) { this._blurNoise = value; } /** * Gets or sets a boolean indicating if pentagon bokeh is enabled */ get pentagonBokeh() { return this._pentagonBokehIsEnabled; } set pentagonBokeh(value) { if (value) { this.enablePentagonBokeh(); } else { this.disablePentagonBokeh(); } } /** * Gets or sets the highlight grain amount */ get highlightsGain() { return this._highlightsGain; } set highlightsGain(value) { this.setHighlightsGain(value); } /** * Gets or sets the highlight threshold */ get highlightsThreshold() { return this._highlightsThreshold; } set highlightsThreshold(value) { this.setHighlightsThreshold(value); } // public methods (self explanatory) /** * Sets the amount of blur at the edges * @param amount blur amount */ setEdgeBlur(amount) { this._edgeBlur = amount; } /** * Sets edge blur to 0 */ disableEdgeBlur() { this._edgeBlur = 0; } /** * Sets the amount of grain * @param amount Amount of grain */ setGrainAmount(amount) { this._grainAmount = amount; } /** * Set grain amount to 0 */ disableGrain() { this._grainAmount = 0; } /** * Sets the chromatic aberration amount * @param amount amount of chromatic aberration */ setChromaticAberration(amount) { this._chromaticAberration = amount; } /** * Sets chromatic aberration amount to 0 */ disableChromaticAberration() { this._chromaticAberration = 0; } /** * Sets the EdgeDistortion amount * @param amount amount of EdgeDistortion */ setEdgeDistortion(amount) { this._distortion = amount; } /** * Sets edge distortion to 0 */ disableEdgeDistortion() { this._distortion = 0; } /** * Sets the FocusDistance amount * @param amount amount of FocusDistance */ setFocusDistance(amount) { this._dofDistance = amount; } /** * Disables depth of field */ disableDepthOfField() { this._dofDistance = -1; } /** * Sets the Aperture amount * @param amount amount of Aperture */ setAperture(amount) { this._dofAperture = amount; } /** * Sets the DarkenOutOfFocus amount * @param amount amount of DarkenOutOfFocus */ setDarkenOutOfFocus(amount) { this._dofDarken = amount; } /** * Creates a pentagon bokeh effect */ enablePentagonBokeh() { this._highlightsPostProcess.updateEffect("#define PENTAGON\n"); this._pentagonBokehIsEnabled = true; } /** * Disables the pentagon bokeh effect */ disablePentagonBokeh() { this._pentagonBokehIsEnabled = false; this._highlightsPostProcess.updateEffect(); } /** * Enables noise blur */ enableNoiseBlur() { this._blurNoise = true; } /** * Disables noise blur */ disableNoiseBlur() { this._blurNoise = false; } /** * Sets the HighlightsGain amount * @param amount amount of HighlightsGain */ setHighlightsGain(amount) { this._highlightsGain = amount; } /** * Sets the HighlightsThreshold amount * @param amount amount of HighlightsThreshold */ setHighlightsThreshold(amount) { if (this._highlightsGain === -1) { this._highlightsGain = 1.0; } this._highlightsThreshold = amount; } /** * Disables highlights */ disableHighlights() { this._highlightsGain = -1; } /** * Removes the internal pipeline assets and detaches the pipeline from the scene cameras * @param disableDepthRender If the scene's depth rendering should be disabled (default: false) */ dispose(disableDepthRender = false) { this._scene.postProcessRenderPipelineManager.detachCamerasFromRenderPipeline(this._name, this._scene.cameras); this._chromaticAberrationPostProcess = null; this._highlightsPostProcess = null; this._depthOfFieldPostProcess = null; this._grainTexture.dispose(); if (disableDepthRender) { this._scene.disableDepthRenderer(); } } // colors shifting and distortion _createChromaticAberrationPostProcess(ratio) { this._chromaticAberrationPostProcess = new PostProcess("LensChromaticAberration", "chromaticAberration", ["chromatic_aberration", "screen_width", "screen_height", "direction", "radialIntensity", "centerPosition"], // uniforms [], // samplers ratio, null, Texture.TRILINEAR_SAMPLINGMODE, this._scene.getEngine(), false); this._chromaticAberrationPostProcess.onApply = (effect) => { effect.setFloat("chromatic_aberration", this._chromaticAberration); effect.setFloat("screen_width", this._scene.getEngine().getRenderWidth()); effect.setFloat("screen_height", this._scene.getEngine().getRenderHeight()); effect.setFloat("radialIntensity", 1); effect.setFloat2("direction", 17, 17); effect.setFloat2("centerPosition", 0.5, 0.5); }; } // highlights enhancing _createHighlightsPostProcess(ratio) { this._highlightsPostProcess = new PostProcess("LensHighlights", "lensHighlights", ["gain", "threshold", "screen_width", "screen_height"], // uniforms [], // samplers ratio, null, Texture.TRILINEAR_SAMPLINGMODE, this._scene.getEngine(), false, this._dofPentagon ? "#define PENTAGON\n" : ""); this._highlightsPostProcess.externalTextureSamplerBinding = true; this._highlightsPostProcess.onApply = (effect) => { effect.setFloat("gain", this._highlightsGain); effect.setFloat("threshold", this._highlightsThreshold); effect.setTextureFromPostProcess("textureSampler", this._chromaticAberrationPostProcess); effect.setFloat("screen_width", this._scene.getEngine().getRenderWidth()); effect.setFloat("screen_height", this._scene.getEngine().getRenderHeight()); }; } // colors shifting and distortion _createDepthOfFieldPostProcess(ratio) { this._depthOfFieldPostProcess = new PostProcess("LensDepthOfField", "depthOfField", [ "grain_amount", "blur_noise", "screen_width", "screen_height", "distortion", "dof_enabled", "screen_distance", "aperture", "darken", "edge_blur", "highlights", "near", "far", ], ["depthSampler", "grainSampler", "highlightsSampler"], ratio, null, Texture.TRILINEAR_SAMPLINGMODE, this._scene.getEngine(), false); this._depthOfFieldPostProcess.externalTextureSamplerBinding = true; this._depthOfFieldPostProcess.onApply = (effect) => { effect.setTexture("depthSampler", this._depthTexture); effect.setTexture("grainSampler", this._grainTexture); effect.setTextureFromPostProcess("textureSampler", this._highlightsPostProcess); effect.setTextureFromPostProcess("highlightsSampler", this._depthOfFieldPostProcess); effect.setFloat("grain_amount", this._grainAmount); effect.setBool("blur_noise", this._blurNoise); effect.setFloat("screen_width", this._scene.getEngine().getRenderWidth()); effect.setFloat("screen_height", this._scene.getEngine().getRenderHeight()); effect.setFloat("distortion", this._distortion); effect.setBool("dof_enabled", this._dofDistance !== -1); effect.setFloat("screen_distance", 1.0 / (0.1 - 1.0 / this._dofDistance)); effect.setFloat("aperture", this._dofAperture); effect.setFloat("darken", this._dofDarken); effect.setFloat("edge_blur", this._edgeBlur); effect.setBool("highlights", this._highlightsGain !== -1); if (this._scene.activeCamera) { effect.setFloat("near", this._scene.activeCamera.minZ); effect.setFloat("far", this._scene.activeCamera.maxZ); } }; } // creates a black and white random noise texture, 512x512 _createGrainTexture() { const size = 512; const data = new Uint8Array(size * size * 4); for (let index = 0; index < data.length;) { const value = Math.floor(RandomRange(0.42, 0.58) * 255); data[index++] = value; data[index++] = value; data[index++] = value; data[index++] = 255; } const texture = RawTexture.CreateRGBATexture(data, size, size, this._scene, false, false, 2); texture.name = "LensNoiseTexture"; texture.wrapU = Texture.WRAP_ADDRESSMODE; texture.wrapV = Texture.WRAP_ADDRESSMODE; this._grainTexture = texture; } } //# sourceMappingURL=lensRenderingPipeline.js.map