123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- import { Camera } from "Cameras";
- import { Scene } from "scene";
- import { Engine } from "Engine";
- import { AbstractMesh } from "Mesh";
- import { RenderTargetTexture } from "Materials";
- import { SceneComponentConstants, ISceneSerializableComponent } from "sceneComponent";
- import { _TimeToken } from "Instrumentation";
- import { _DepthCullingState, _StencilState, _AlphaState } from "States";
- import { EffectLayer } from "Layer";
- import { AbstractScene } from "abstractScene";
- import { AssetContainer } from "assetContainer";
- // Adds the parser to the scene parsers.
- AbstractScene.AddParser(SceneComponentConstants.NAME_EFFECTLAYER, (parsedData: any, scene: Scene, container: AssetContainer, rootUrl: string) => {
- if (parsedData.effectLayers) {
- if (!container.effectLayers) {
- container.effectLayers = new Array<EffectLayer>();
- }
- for (let index = 0; index < parsedData.effectLayers.length; index++) {
- var effectLayer = EffectLayer.Parse(parsedData.effectLayers[index], scene, rootUrl);
- container.effectLayers.push(effectLayer);
- }
- }
- });
- declare module "abstractScene" {
- export interface AbstractScene {
- /**
- * The list of effect layers (highlights/glow) added to the scene
- * @see http://doc.babylonjs.com/how_to/highlight_layer
- * @see http://doc.babylonjs.com/how_to/glow_layer
- */
- effectLayers: Array<EffectLayer>;
- /**
- * Removes the given effect layer from this scene.
- * @param toRemove defines the effect layer to remove
- * @returns the index of the removed effect layer
- */
- removeEffectLayer(toRemove: EffectLayer): number;
- /**
- * Adds the given effect layer to this scene
- * @param newEffectLayer defines the effect layer to add
- */
- addEffectLayer(newEffectLayer: EffectLayer): void;
- }
- }
- AbstractScene.prototype.removeEffectLayer = function(toRemove: EffectLayer): number {
- var index = this.effectLayers.indexOf(toRemove);
- if (index !== -1) {
- this.effectLayers.splice(index, 1);
- }
- return index;
- };
- AbstractScene.prototype.addEffectLayer = function(newEffectLayer: EffectLayer): void {
- this.effectLayers.push(newEffectLayer);
- };
- /**
- * Defines the layer scene component responsible to manage any effect layers
- * in a given scene.
- */
- export class EffectLayerSceneComponent implements ISceneSerializableComponent {
- /**
- * The component name helpfull to identify the component in the list of scene components.
- */
- public readonly name = SceneComponentConstants.NAME_EFFECTLAYER;
- /**
- * The scene the component belongs to.
- */
- public scene: Scene;
- private _engine: Engine;
- private _renderEffects = false;
- private _needStencil = false;
- private _previousStencilState = false;
- /**
- * Creates a new instance of the component for the given scene
- * @param scene Defines the scene to register the component in
- */
- constructor(scene: Scene) {
- this.scene = scene;
- this._engine = scene.getEngine();
- scene.effectLayers = new Array<EffectLayer>();
- }
- /**
- * Registers the component in a given scene
- */
- public register(): void {
- this.scene._isReadyForMeshStage.registerStep(SceneComponentConstants.STEP_ISREADYFORMESH_EFFECTLAYER, this, this._isReadyForMesh);
- this.scene._cameraDrawRenderTargetStage.registerStep(SceneComponentConstants.STEP_CAMERADRAWRENDERTARGET_EFFECTLAYER, this, this._renderMainTexture);
- this.scene._beforeCameraDrawStage.registerStep(SceneComponentConstants.STEP_BEFORECAMERADRAW_EFFECTLAYER, this, this._setStencil);
- this.scene._afterRenderingGroupDrawStage.registerStep(SceneComponentConstants.STEP_AFTERRENDERINGGROUPDRAW_EFFECTLAYER_DRAW, this, this._drawRenderingGroup);
- this.scene._afterCameraDrawStage.registerStep(SceneComponentConstants.STEP_AFTERCAMERADRAW_EFFECTLAYER, this, this._setStencilBack);
- this.scene._afterCameraDrawStage.registerStep(SceneComponentConstants.STEP_AFTERCAMERADRAW_EFFECTLAYER_DRAW, this, this._drawCamera);
- }
- /**
- * Rebuilds the elements related to this component in case of
- * context lost for instance.
- */
- public rebuild(): void {
- let layers = this.scene.effectLayers;
- for (let effectLayer of layers) {
- effectLayer._rebuild();
- }
- }
- /**
- * Serializes the component data to the specified json object
- * @param serializationObject The object to serialize to
- */
- public serialize(serializationObject: any): void {
- // Effect layers
- serializationObject.effectLayers = [];
- let layers = this.scene.effectLayers;
- for (let effectLayer of layers) {
- if (effectLayer.serialize) {
- serializationObject.effectLayers.push(effectLayer.serialize());
- }
- }
- }
- /**
- * Adds all the element from the container to the scene
- * @param container the container holding the elements
- */
- public addFromContainer(container: AbstractScene): void {
- if (!container.effectLayers) {
- return;
- }
- container.effectLayers.forEach((o) => {
- this.scene.addEffectLayer(o);
- });
- }
- /**
- * Removes all the elements in the container from the scene
- * @param container contains the elements to remove
- */
- public removeFromContainer(container: AbstractScene): void {
- if (!container.effectLayers) {
- return;
- }
- container.effectLayers.forEach((o) => {
- this.scene.removeEffectLayer(o);
- });
- }
- /**
- * Disposes the component and the associated ressources.
- */
- public dispose(): void {
- let layers = this.scene.effectLayers;
- while (layers.length) {
- layers[0].dispose();
- }
- }
- private _isReadyForMesh(mesh: AbstractMesh, hardwareInstancedRendering: boolean): boolean {
- let layers = this.scene.effectLayers;
- for (let layer of layers) {
- if (!layer.hasMesh(mesh)) {
- continue;
- }
- for (var subMesh of mesh.subMeshes) {
- if (!layer.isReady(subMesh, hardwareInstancedRendering)) {
- return false;
- }
- }
- }
- return true;
- }
- private _renderMainTexture(camera: Camera): void {
- this._renderEffects = false;
- this._needStencil = false;
- let layers = this.scene.effectLayers;
- if (layers && layers.length > 0) {
- this._previousStencilState = this._engine.getStencilBuffer();
- for (let effectLayer of layers) {
- if (effectLayer.shouldRender() &&
- (!effectLayer.camera ||
- (effectLayer.camera.cameraRigMode === Camera.RIG_MODE_NONE && camera === effectLayer.camera) ||
- (effectLayer.camera.cameraRigMode !== Camera.RIG_MODE_NONE && effectLayer.camera._rigCameras.indexOf(camera) > -1))) {
- this._renderEffects = true;
- this._needStencil = this._needStencil || effectLayer.needStencil();
- let renderTarget = (<RenderTargetTexture>(<any>effectLayer)._mainTexture);
- if (renderTarget._shouldRender()) {
- this.scene.incrementRenderId();
- renderTarget.render(false, false);
- }
- }
- }
- this.scene.incrementRenderId();
- }
- }
- private _setStencil() {
- // Activate effect Layer stencil
- if (this._needStencil) {
- this._engine.setStencilBuffer(true);
- }
- }
- private _setStencilBack() {
- // Restore effect Layer stencil
- if (this._needStencil) {
- this._engine.setStencilBuffer(this._previousStencilState);
- }
- }
- private _draw(renderingGroupId: number): void {
- if (this._renderEffects) {
- this._engine.setDepthBuffer(false);
- let layers = this.scene.effectLayers;
- for (let i = 0; i < layers.length; i++) {
- const effectLayer = layers[i];
- if (effectLayer.renderingGroupId === renderingGroupId) {
- if (effectLayer.shouldRender()) {
- effectLayer.render();
- }
- }
- }
- this._engine.setDepthBuffer(true);
- }
- }
- private _drawCamera(): void {
- if (this._renderEffects) {
- this._draw(-1);
- }
- }
- private _drawRenderingGroup(index: number): void {
- if (!this.scene._isInIntermediateRendering() && this._renderEffects) {
- this._draw(index);
- }
- }
- }
|