Przeglądaj źródła

Add a CurrentScreenBlock

Popov72 5 lat temu
rodzic
commit
b5f85140fa

+ 3 - 0
nodeEditor/src/blockTools.ts

@@ -71,6 +71,7 @@ import { ReflectionBlock } from 'babylonjs/Materials/Node/Blocks/PBR/reflectionB
 import { ClearCoatBlock } from 'babylonjs/Materials/Node/Blocks/PBR/clearCoatBlock';
 import { RefractionBlock } from 'babylonjs/Materials/Node/Blocks/PBR/refractionBlock';
 import { SubSurfaceBlock } from 'babylonjs/Materials/Node/Blocks/PBR/subSurfaceBlock';
+import { CurrentScreenBlock } from 'babylonjs/Materials/Node/Blocks/Dual/currentScreenBlock';
 
 export class BlockTools {
     public static GetBlockFromString(data: string, scene: Scene, nodeMaterial: NodeMaterial) {
@@ -464,6 +465,8 @@ export class BlockTools {
                 return new RefractionBlock("Refraction");
             case "SubSurfaceBlock":
                 return new SubSurfaceBlock("SubSurface");
+            case "CurrentScreenBlock":
+                return new CurrentScreenBlock("CurrentScreen");
         }
 
         return null;

+ 1 - 0
nodeEditor/src/components/nodeList/nodeListComponent.tsx

@@ -127,6 +127,7 @@ export class NodeListComponent extends React.Component<INodeListComponentProps,
         "RefractionBlock": "PBR Refraction block",
         "SubSurfaceBlock": "PBR SubSurface block",
         "Position2DBlock": "A Vector2 representing the position of each vertex of the screen quad",
+        "CurrentScreenBlock": "The screen buffer used as input for the post process",
     };
 
     constructor(props: INodeListComponentProps) {

+ 1 - 0
nodeEditor/src/diagram/displayLedger.ts

@@ -22,4 +22,5 @@ DisplayLedger.RegisteredControls["TextureBlock"] = TextureDisplayManager;
 DisplayLedger.RegisteredControls["ReflectionTextureBlock"] = TextureDisplayManager;
 DisplayLedger.RegisteredControls["ReflectionBlock"] = TextureDisplayManager;
 DisplayLedger.RegisteredControls["RefractionBlock"] = TextureDisplayManager;
+DisplayLedger.RegisteredControls["CurrentScreenBlock"] = TextureDisplayManager;
 DisplayLedger.RegisteredControls["DiscardBlock"] = DiscardDisplayManager;

+ 19 - 13
nodeEditor/src/diagram/properties/texturePropertyTabComponent.tsx

@@ -17,14 +17,18 @@ import { ReflectionTextureBlock } from 'babylonjs/Materials/Node/Blocks/Dual/ref
 import { ReflectionBlock } from 'babylonjs/Materials/Node/Blocks/PBR/reflectionBlock';
 import { RefractionBlock } from 'babylonjs/Materials/Node/Blocks/PBR/refractionBlock';
 import { TextureBlock } from 'babylonjs/Materials/Node/Blocks/Dual/textureBlock';
+import { CurrentScreenBlock } from 'babylonjs/Materials/Node/Blocks/Dual/currentScreenBlock';
 import { GeneralPropertyTabComponent, GenericPropertyTabComponent } from './genericNodePropertyComponent';
+import { NodeMaterialModes } from 'babylonjs/Materials/Node/Enums/nodeMaterialModes';
 
 type ReflectionTexture = ReflectionTextureBlock | ReflectionBlock | RefractionBlock;
 
+type AnyTexture = TextureBlock | ReflectionTexture | CurrentScreenBlock;
+
 export class TexturePropertyTabComponent extends React.Component<IPropertyComponentProps, {isEmbedded: boolean, loadAsCubeTexture: boolean}> {
 
-    get textureBlock(): TextureBlock | ReflectionTexture {
-        return this.props.block as TextureBlock | ReflectionTexture;
+    get textureBlock(): AnyTexture {
+        return this.props.block as AnyTexture;
     }
 
     constructor(props: IPropertyComponentProps) {
@@ -37,7 +41,7 @@ export class TexturePropertyTabComponent extends React.Component<IPropertyCompon
 
     UNSAFE_componentWillUpdate(nextProps: IPropertyComponentProps, nextState: {isEmbedded: boolean, loadAsCubeTexture: boolean}) {
         if (nextProps.block !== this.props.block) {
-            let texture = (nextProps.block as TextureBlock | ReflectionTexture).texture as BaseTexture;
+            let texture = (nextProps.block as AnyTexture).texture as BaseTexture;
 
             nextState.isEmbedded = !texture || texture.name.substring(0, 4) === "data";
             nextState.loadAsCubeTexture = texture && texture.isCube;
@@ -80,7 +84,8 @@ export class TexturePropertyTabComponent extends React.Component<IPropertyCompon
 
         if (!texture) {
             if (!this.state.loadAsCubeTexture) {
-                this.textureBlock.texture = new Texture(null, this.props.globalState.nodeMaterial.getScene(), false, this.textureBlock instanceof ReflectionTextureBlock || this.textureBlock instanceof ReflectionBlock || this.textureBlock instanceof RefractionBlock);
+                this.textureBlock.texture = new Texture(null, this.props.globalState.nodeMaterial.getScene(), false, 
+                    this.textureBlock instanceof ReflectionTextureBlock || this.textureBlock instanceof ReflectionBlock || this.textureBlock instanceof RefractionBlock || this.props.globalState.mode === NodeMaterialModes.PostProcess);
                 texture = this.textureBlock.texture;
                 texture.coordinatesMode = Texture.EQUIRECTANGULAR_MODE;
             } else {
@@ -148,6 +153,7 @@ export class TexturePropertyTabComponent extends React.Component<IPropertyCompon
         url = url.replace(/\?nocache=\d+/, "");
 
         let isInReflectionMode = this.textureBlock instanceof ReflectionTextureBlock || this.textureBlock instanceof ReflectionBlock || this.textureBlock instanceof RefractionBlock;
+        let isFrozenTexture = this.textureBlock instanceof CurrentScreenBlock;
 
         var reflectionModeOptions: {label: string, value: number}[] = [
             {
@@ -207,21 +213,21 @@ export class TexturePropertyTabComponent extends React.Component<IPropertyCompon
                         }} />
                     }                    
                     {
-                        texture && !isInReflectionMode &&
+                        texture && !isInReflectionMode && !isFrozenTexture &&
                         <CheckBoxLineComponent label="Clamp U" isSelected={() => texture.wrapU === Texture.CLAMP_ADDRESSMODE} onSelect={(value) => {
                             texture.wrapU = value ? Texture.CLAMP_ADDRESSMODE : Texture.WRAP_ADDRESSMODE;
                             this.props.globalState.onUpdateRequiredObservable.notifyObservers();
                         }} />
                     }
                     {
-                        texture && !isInReflectionMode &&
+                        texture && !isInReflectionMode && !isFrozenTexture &&
                         <CheckBoxLineComponent label="Clamp V" isSelected={() => texture.wrapV === Texture.CLAMP_ADDRESSMODE} onSelect={(value) => {
                             texture.wrapV = value ? Texture.CLAMP_ADDRESSMODE : Texture.WRAP_ADDRESSMODE;
                             this.props.globalState.onUpdateRequiredObservable.notifyObservers();
                         }} />
                     }        
                     {
-                        texture && !isInReflectionMode &&
+                        texture && !isInReflectionMode && !isFrozenTexture &&
                         <FloatLineComponent globalState={this.props.globalState} label="Offset U" target={texture} propertyName="uOffset" 
                         onChange={() => {
                             this.props.globalState.onUpdateRequiredObservable.notifyObservers();
@@ -229,7 +235,7 @@ export class TexturePropertyTabComponent extends React.Component<IPropertyCompon
                         />
                     }
                     {
-                        texture && !isInReflectionMode &&
+                        texture && !isInReflectionMode && !isFrozenTexture &&
                         <FloatLineComponent globalState={this.props.globalState} label="Offset V" target={texture} propertyName="vOffset"
                         onChange={() => {
                             this.props.globalState.onUpdateRequiredObservable.notifyObservers();
@@ -237,21 +243,21 @@ export class TexturePropertyTabComponent extends React.Component<IPropertyCompon
                         />
                     }
                     {
-                        texture && !isInReflectionMode &&
+                        texture && !isInReflectionMode && !isFrozenTexture &&
                         <FloatLineComponent globalState={this.props.globalState} label="Scale U" target={texture} propertyName="uScale"
                         onChange={() => {
                             this.props.globalState.onUpdateRequiredObservable.notifyObservers();
                         }} />
                     }
                     {
-                        texture && !isInReflectionMode &&
+                        texture && !isInReflectionMode && !isFrozenTexture &&
                         <FloatLineComponent globalState={this.props.globalState} label="Scale V" target={texture} propertyName="vScale"
                         onChange={() => {
                             this.props.globalState.onUpdateRequiredObservable.notifyObservers();
                         }} />
                     }
                     {
-                        texture && !isInReflectionMode &&
+                        texture && !isInReflectionMode && !isFrozenTexture &&
                         <SliderLineComponent label="Rotation U" target={texture} propertyName="uAng" minimum={0} maximum={Math.PI * 2} useEuler={true} step={0.1}
                         onChange={() => {
                             this.props.globalState.onUpdateRequiredObservable.notifyObservers();
@@ -259,7 +265,7 @@ export class TexturePropertyTabComponent extends React.Component<IPropertyCompon
                         />
                     }
                     {
-                        texture && !isInReflectionMode &&
+                        texture && !isInReflectionMode && !isFrozenTexture &&
                         <SliderLineComponent label="Rotation V" target={texture} propertyName="vAng" minimum={0} maximum={Math.PI * 2} useEuler={true} step={0.1}
                         onChange={() => {
                             this.props.globalState.onUpdateRequiredObservable.notifyObservers();
@@ -267,7 +273,7 @@ export class TexturePropertyTabComponent extends React.Component<IPropertyCompon
                         />
                     }                    
                     {
-                        texture && !isInReflectionMode &&
+                        texture && !isInReflectionMode && !isFrozenTexture &&
                         <SliderLineComponent label="Rotation W" target={texture} propertyName="wAng" minimum={0} maximum={Math.PI * 2} useEuler={true} step={0.1}
                         onChange={() => {
                             this.props.globalState.onUpdateRequiredObservable.notifyObservers();

+ 1 - 0
nodeEditor/src/diagram/propertyLedger.ts

@@ -21,4 +21,5 @@ PropertyLedger.RegisteredControls["TextureBlock"] = TexturePropertyTabComponent;
 PropertyLedger.RegisteredControls["ReflectionTextureBlock"] = TexturePropertyTabComponent;
 PropertyLedger.RegisteredControls["ReflectionBlock"] = TexturePropertyTabComponent;
 PropertyLedger.RegisteredControls["RefractionBlock"] = TexturePropertyTabComponent;
+PropertyLedger.RegisteredControls["CurrentScreenBlock"] = TexturePropertyTabComponent;
 PropertyLedger.RegisteredControls["TrigonometryBlock"] = TrigonometryPropertyTabComponent;

+ 327 - 0
src/Materials/Node/Blocks/Dual/currentScreenBlock.ts

@@ -0,0 +1,327 @@
+import { NodeMaterialBlock } from '../../nodeMaterialBlock';
+import { NodeMaterialBlockConnectionPointTypes } from '../../Enums/nodeMaterialBlockConnectionPointTypes';
+import { NodeMaterialBuildState } from '../../nodeMaterialBuildState';
+import { NodeMaterialBlockTargets } from '../../Enums/nodeMaterialBlockTargets';
+import { NodeMaterialConnectionPoint } from '../../nodeMaterialBlockConnectionPoint';
+import { AbstractMesh } from '../../../../Meshes/abstractMesh';
+import { NodeMaterial, NodeMaterialDefines } from '../../nodeMaterial';
+import { BaseTexture } from '../../../Textures/baseTexture';
+import { Nullable } from '../../../../types';
+import { _TypeStore } from '../../../../Misc/typeStore';
+import { Texture } from '../../../Textures/texture';
+import { Scene } from '../../../../scene';
+import { InputBlock } from '../Input/inputBlock';
+
+/**
+ * Base block used as input for post process
+ */
+export class CurrentScreenBlock extends NodeMaterialBlock {
+
+    private _samplerName = "textureSampler";
+    private _linearDefineName: string;
+    private _gammaDefineName: string;
+    private _mainUVName: string;
+    private _tempTextureRead: string;
+
+    /**
+     * Gets or sets the texture associated with the node
+     */
+    public texture: Nullable<BaseTexture>;
+
+    /**
+     * Gets or sets a boolean indicating if content needs to be converted to gamma space
+     */
+    public convertToGammaSpace = false;
+
+    /**
+     * Gets or sets a boolean indicating if content needs to be converted to linear space
+     */
+    public convertToLinearSpace = false;
+
+    /**
+     * Create a new CurrentScreenBlock
+     * @param name defines the block name
+     */
+    public constructor(name: string) {
+        super(name, NodeMaterialBlockTargets.VertexAndFragment);
+
+        this._isUnique = true;
+
+        this.registerInput("uv", NodeMaterialBlockConnectionPointTypes.Vector2, false, NodeMaterialBlockTargets.VertexAndFragment);
+
+        this.registerOutput("rgba", NodeMaterialBlockConnectionPointTypes.Color4, NodeMaterialBlockTargets.Neutral);
+        this.registerOutput("rgb", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Neutral);
+        this.registerOutput("r", NodeMaterialBlockConnectionPointTypes.Float, NodeMaterialBlockTargets.Neutral);
+        this.registerOutput("g", NodeMaterialBlockConnectionPointTypes.Float, NodeMaterialBlockTargets.Neutral);
+        this.registerOutput("b", NodeMaterialBlockConnectionPointTypes.Float, NodeMaterialBlockTargets.Neutral);
+        this.registerOutput("a", NodeMaterialBlockConnectionPointTypes.Float, NodeMaterialBlockTargets.Neutral);
+
+        this._inputs[0].acceptedConnectionPointTypes.push(NodeMaterialBlockConnectionPointTypes.Vector3);
+        this._inputs[0].acceptedConnectionPointTypes.push(NodeMaterialBlockConnectionPointTypes.Vector4);
+
+        this._inputs[0]._prioritizeVertex = true;
+    }
+
+    /**
+     * Gets the current class name
+     * @returns the class name
+     */
+    public getClassName() {
+        return "CurrentScreenBlock";
+    }
+
+    /**
+     * Gets the uv input component
+     */
+    public get uv(): NodeMaterialConnectionPoint {
+        return this._inputs[0];
+    }
+
+    /**
+     * Gets the rgba output component
+     */
+    public get rgba(): NodeMaterialConnectionPoint {
+        return this._outputs[0];
+    }
+
+    /**
+     * Gets the rgb output component
+     */
+    public get rgb(): NodeMaterialConnectionPoint {
+        return this._outputs[1];
+    }
+
+    /**
+     * Gets the r output component
+     */
+    public get r(): NodeMaterialConnectionPoint {
+        return this._outputs[2];
+    }
+
+    /**
+     * Gets the g output component
+     */
+    public get g(): NodeMaterialConnectionPoint {
+        return this._outputs[3];
+    }
+
+    /**
+     * Gets the b output component
+     */
+    public get b(): NodeMaterialConnectionPoint {
+        return this._outputs[4];
+    }
+
+    /**
+     * Gets the a output component
+     */
+    public get a(): NodeMaterialConnectionPoint {
+        return this._outputs[5];
+    }
+
+    /**
+     * Initialize the block and prepare the context for build
+     * @param state defines the state that will be used for the build
+     */
+    public initialize(state: NodeMaterialBuildState) {
+        state._excludeVariableName("textureSampler");
+    }
+
+    public get target() {
+        // TextureBlock has a special optimizations for uvs that come from the vertex shaders as they can be packed into a single varyings.
+        // But we need to detect uvs coming from fragment then
+        if (!this.uv.isConnected) {
+            return NodeMaterialBlockTargets.VertexAndFragment;
+        }
+
+        if (this.uv.sourceBlock!.isInput) {
+            return NodeMaterialBlockTargets.VertexAndFragment;
+        }
+
+        let parent = this.uv.connectedPoint;
+
+        while (parent) {
+            if (parent.target === NodeMaterialBlockTargets.Fragment) {
+                return NodeMaterialBlockTargets.Fragment;
+            }
+
+            if (parent.target === NodeMaterialBlockTargets.Vertex) {
+                return NodeMaterialBlockTargets.VertexAndFragment;
+            }
+
+            if (parent.target === NodeMaterialBlockTargets.Neutral || parent.target === NodeMaterialBlockTargets.VertexAndFragment) {
+                let parentBlock = parent.ownerBlock;
+
+                parent = null;
+                for (var input of parentBlock.inputs) {
+                    if (input.connectedPoint) {
+                        parent = input.connectedPoint;
+                        break;
+                    }
+                }
+            }
+
+        }
+
+        return NodeMaterialBlockTargets.VertexAndFragment;
+    }
+
+    public prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines) {
+        defines.setValue(this._linearDefineName, this.convertToGammaSpace, true);
+        defines.setValue(this._gammaDefineName, this.convertToLinearSpace, true);
+    }
+
+    public isReady() {
+        if (this.texture && !this.texture.isReadyOrNotBlocking()) {
+            return false;
+        }
+
+        return true;
+    }
+
+    private _injectVertexCode(state: NodeMaterialBuildState) {
+        let uvInput = this.uv;
+
+        if (uvInput.connectedPoint!.ownerBlock.isInput) {
+            let uvInputOwnerBlock = uvInput.connectedPoint!.ownerBlock as InputBlock;
+
+            if (!uvInputOwnerBlock.isAttribute) {
+                state._emitUniformFromString(uvInput.associatedVariableName, "vec2");
+            }
+        }
+
+        this._mainUVName = "vMain" + uvInput.associatedVariableName;
+
+        state._emitVaryingFromString(this._mainUVName, "vec2");
+
+        state.compilationString += `${this._mainUVName} = ${uvInput.associatedVariableName}.xy;\r\n`;
+
+        if (!this._outputs.some((o) => o.isConnectedInVertexShader)) {
+            return;
+        }
+
+        this._writeTextureRead(state, true);
+
+        for (var output of this._outputs) {
+            if (output.hasEndpoints) {
+                this._writeOutput(state, output, output.name, true);
+            }
+        }
+    }
+
+    private _writeTextureRead(state: NodeMaterialBuildState, vertexMode = false) {
+        let uvInput = this.uv;
+
+        if (vertexMode) {
+            if (state.target === NodeMaterialBlockTargets.Fragment) {
+                return;
+            }
+
+            state.compilationString += `vec4 ${this._tempTextureRead} = texture2D(${this._samplerName}, ${uvInput.associatedVariableName});\r\n`;
+            return;
+        }
+
+        if (this.uv.ownerBlock.target === NodeMaterialBlockTargets.Fragment) {
+            state.compilationString += `vec4 ${this._tempTextureRead} = texture2D(${this._samplerName}, ${uvInput.associatedVariableName});\r\n`;
+            return;
+        }
+
+        state.compilationString += `vec4 ${this._tempTextureRead} = texture2D(${this._samplerName}, ${this._mainUVName});\r\n`;
+    }
+
+    private _writeOutput(state: NodeMaterialBuildState, output: NodeMaterialConnectionPoint, swizzle: string, vertexMode = false) {
+        if (vertexMode) {
+            if (state.target === NodeMaterialBlockTargets.Fragment) {
+                return;
+            }
+
+            state.compilationString += `${this._declareOutput(output, state)} = ${this._tempTextureRead}.${swizzle};\r\n`;
+
+            return;
+        }
+
+        if (this.uv.ownerBlock.target === NodeMaterialBlockTargets.Fragment) {
+            state.compilationString += `${this._declareOutput(output, state)} = ${this._tempTextureRead}.${swizzle};\r\n`;
+            return;
+        }
+
+        state.compilationString += `${this._declareOutput(output, state)} = ${this._tempTextureRead}.${swizzle};\r\n`;
+
+        state.compilationString += `#ifdef ${this._linearDefineName}\r\n`;
+        state.compilationString += `${output.associatedVariableName} = toGammaSpace(${output.associatedVariableName});\r\n`;
+        state.compilationString += `#endif\r\n`;
+
+        state.compilationString += `#ifdef ${this._gammaDefineName}\r\n`;
+        state.compilationString += `${output.associatedVariableName} = toLinearSpace(${output.associatedVariableName});\r\n`;
+        state.compilationString += `#endif\r\n`;
+    }
+
+    protected _buildBlock(state: NodeMaterialBuildState) {
+        super._buildBlock(state);
+
+        if (state.target === NodeMaterialBlockTargets.Vertex) {
+            this._tempTextureRead = state._getFreeVariableName("tempTextureRead");
+
+            state._emit2DSampler(this._samplerName);
+
+            state.sharedData.blockingBlocks.push(this);
+            state.sharedData.textureBlocks.push(this);
+            state.sharedData.blocksWithDefines.push(this);
+        }
+
+        if (state.target !== NodeMaterialBlockTargets.Fragment) {
+            // Vertex
+            this._injectVertexCode(state);
+            return;
+        }
+
+        // Fragment
+        if (!this._outputs.some((o) => o.isConnectedInFragmentShader)) {
+            return;
+        }
+
+        state._emit2DSampler(this._samplerName);
+
+        this._linearDefineName = state._getFreeDefineName("ISLINEAR");
+        this._gammaDefineName = state._getFreeDefineName("ISGAMMA");
+
+        let comments = `//${this.name}`;
+        state._emitFunctionFromInclude("helperFunctions", comments);
+
+        this._writeTextureRead(state);
+
+        for (var output of this._outputs) {
+            if (output.hasEndpoints) {
+                this._writeOutput(state, output, output.name);
+            }
+        }
+
+        return this;
+    }
+
+    public serialize(): any {
+        let serializationObject = super.serialize();
+
+        serializationObject.convertToGammaSpace = this.convertToGammaSpace;
+        serializationObject.convertToLinearSpace = this.convertToLinearSpace;
+        if (this.texture) {
+            serializationObject.texture = this.texture.serialize();
+        }
+
+        return serializationObject;
+    }
+
+    public _deserialize(serializationObject: any, scene: Scene, rootUrl: string) {
+        super._deserialize(serializationObject, scene, rootUrl);
+
+        this.convertToGammaSpace = serializationObject.convertToGammaSpace;
+        this.convertToLinearSpace = !!serializationObject.convertToLinearSpace;
+
+        if (serializationObject.texture && !NodeMaterial.IgnoreTexturesAtLoadTime) {
+            rootUrl = serializationObject.texture.url.indexOf("data:") === 0 ? "" : rootUrl;
+            this.texture = Texture.Parse(serializationObject.texture, scene, rootUrl) as Texture;
+        }
+    }
+}
+
+_TypeStore.RegisteredTypes["BABYLON.CurrentScreenBlock"] = CurrentScreenBlock;

+ 2 - 1
src/Materials/Node/Blocks/Dual/index.ts

@@ -2,4 +2,5 @@
 export * from "./fogBlock";
 export * from "./lightBlock";
 export * from "./textureBlock";
-export * from "./reflectionTextureBlock";
+export * from "./reflectionTextureBlock";
+export * from "./currentScreenBlock";

+ 1 - 1
src/Materials/Node/nodeMaterial.ts

@@ -965,7 +965,7 @@ export class NodeMaterial extends PushMaterial {
      * Gets the list of texture blocks
      * @returns an array of texture blocks
      */
-    public getTextureBlocks(): (TextureBlock | ReflectionTextureBaseBlock | RefractionBlock)[] {
+    public getTextureBlocks(): (TextureBlock | ReflectionTextureBaseBlock | RefractionBlock | CurrentScreenBlock)[] {
         if (!this._sharedData) {
             return [];
         }

+ 2 - 1
src/Materials/Node/nodeMaterialBuildStateSharedData.ts

@@ -4,6 +4,7 @@ import { InputBlock } from './Blocks/Input/inputBlock';
 import { TextureBlock } from './Blocks/Dual/textureBlock';
 import { ReflectionTextureBaseBlock } from './Blocks/Dual/reflectionTextureBaseBlock';
 import { RefractionBlock } from './Blocks/PBR/refractionBlock';
+import { CurrentScreenBlock } from './Blocks/Dual/currentScreenBlock';
 import { Scene } from '../../scene';
 
 /**
@@ -33,7 +34,7 @@ export class NodeMaterialBuildStateSharedData {
     /**
      * Input blocks
      */
-    public textureBlocks = new Array<TextureBlock | ReflectionTextureBaseBlock | RefractionBlock>();
+    public textureBlocks = new Array<TextureBlock | ReflectionTextureBaseBlock | RefractionBlock | CurrentScreenBlock>();
 
     /**
      * Bindable blocks (Blocks that need to set data to the effect)