Popov72 пре 5 година
родитељ
комит
d8017dcc4b

+ 81 - 78
nodeEditor/src/blockTools.ts

@@ -64,20 +64,21 @@ import { ReflectBlock } from 'babylonjs/Materials/Node/Blocks/reflectBlock';
 import { DesaturateBlock } from 'babylonjs/Materials/Node/Blocks/desaturateBlock';
 import { PBRMetallicRoughnessBlock } from 'babylonjs/Materials/Node/Blocks/Fragment/pbrMetallicRoughnessBlock';
 import { SheenBlock } from 'babylonjs/Materials/Node/Blocks/Fragment/sheenBlock';
+import { AmbientOcclusionBlock } from 'babylonjs/Materials/Node/Blocks/Fragment/ambientOcclusionBlock';
 
 export class BlockTools {
     public static GetBlockFromString(data: string, scene: Scene, nodeMaterial: NodeMaterial) {
         switch (data) {
             case "DesaturateBlock":
-                return new DesaturateBlock("Desaturate");                  
+                return new DesaturateBlock("Desaturate");
             case "RefractBlock":
-                return new RefractBlock("Refract");               
+                return new RefractBlock("Refract");
             case "ReflectBlock":
-                return new ReflectBlock("Reflect");              
+                return new ReflectBlock("Reflect");
             case "DerivativeBlock":
-                return new DerivativeBlock("Derivative");               
+                return new DerivativeBlock("Derivative");
             case "Rotate2dBlock":
-                return new Rotate2dBlock("Rotate2d");            
+                return new Rotate2dBlock("Rotate2d");
             case "NormalBlendBlock":
                 return new NormalBlendBlock("NormalBlend");
             case "WorleyNoise3DBlock":
@@ -97,7 +98,7 @@ export class BlockTools {
             case "ColorMergerBlock":
                 return new ColorMergerBlock("ColorMerger");
             case "VectorMergerBlock":
-                return new VectorMergerBlock("VectorMerger");                
+                return new VectorMergerBlock("VectorMerger");
             case "ColorSplitterBlock":
                 return new ColorSplitterBlock("ColorSplitter");
             case "VectorSplitterBlock":
@@ -105,7 +106,7 @@ export class BlockTools {
             case "TextureBlock":
                 return new TextureBlock("Texture");
             case "ReflectionTextureBlock":
-                return new ReflectionTextureBlock("Reflection texture");                
+                return new ReflectionTextureBlock("Reflection texture");
             case "LightBlock":
                 return new LightBlock("Lights");
             case "FogBlock":
@@ -145,45 +146,45 @@ export class BlockTools {
             case "DivideBlock":
                 return new DivideBlock("Divide");
             case "SubtractBlock":
-                return new SubtractBlock("Subtract"); 
+                return new SubtractBlock("Subtract");
             case "StepBlock":
-                return new StepBlock("Step");        
+                return new StepBlock("Step");
             case "SmoothStepBlock":
-                return new SmoothStepBlock("Smooth step");        
+                return new SmoothStepBlock("Smooth step");
             case "OneMinusBlock":
-                return new OneMinusBlock("One minus");          
+                return new OneMinusBlock("One minus");
             case "ReciprocalBlock":
-                return new ReciprocalBlock("Reciprocal");    
+                return new ReciprocalBlock("Reciprocal");
             case "ViewDirectionBlock":
-                return new ViewDirectionBlock("View direction");    
+                return new ViewDirectionBlock("View direction");
             case "LightInformationBlock":
                 let lightInformationBlock = new LightInformationBlock("Light information");
                 lightInformationBlock.light = scene.lights.length ? scene.lights[0] : null;
                 return lightInformationBlock;
             case "MaxBlock":
-                return new MaxBlock("Max");       
+                return new MaxBlock("Max");
             case "MinBlock":
-                return new MinBlock("Min");      
+                return new MinBlock("Min");
             case "LengthBlock":
-                return new LengthBlock("Length");   
+                return new LengthBlock("Length");
             case "DistanceBlock":
-                return new DistanceBlock("Distance");     
+                return new DistanceBlock("Distance");
             case "NegateBlock":
-                return new NegateBlock("Negate");                                     
-            case "PerturbNormalBlock":                                          
-                return new PerturbNormalBlock("Perturb normal");                     
-            case "RandomNumberBlock":                                          
-                return new RandomNumberBlock("Random number");         
-            case "ReplaceColorBlock":                                          
-                return new ReplaceColorBlock("Replace color");      
-            case "PosterizeBlock":                                          
-                return new PosterizeBlock("Posterize");                              
-            case "ArcTan2Block":                                          
-                return new ArcTan2Block("ArcTan2");                            
-            case "GradientBlock":                                          
-                return new GradientBlock("Gradient");                             
-            case "FrontFacingBlock":                                          
-                return new FrontFacingBlock("Front facing");            
+                return new NegateBlock("Negate");
+            case "PerturbNormalBlock":
+                return new PerturbNormalBlock("Perturb normal");
+            case "RandomNumberBlock":
+                return new RandomNumberBlock("Random number");
+            case "ReplaceColorBlock":
+                return new ReplaceColorBlock("Replace color");
+            case "PosterizeBlock":
+                return new PosterizeBlock("Posterize");
+            case "ArcTan2Block":
+                return new ArcTan2Block("ArcTan2");
+            case "GradientBlock":
+                return new GradientBlock("Gradient");
+            case "FrontFacingBlock":
+                return new FrontFacingBlock("Front facing");
             case "CosBlock": {
                 let cosBlock = new TrigonometryBlock("Cos");
                 cosBlock.operation = TrigonometryBlockOperations.Cos;
@@ -198,7 +199,7 @@ export class BlockTools {
                 let absBlock = new TrigonometryBlock("Abs");
                 absBlock.operation = TrigonometryBlockOperations.Abs;
                 return absBlock;
-            }            
+            }
             case "SqrtBlock": {
                 let sqrtBlock = new TrigonometryBlock("Sqrt");
                 sqrtBlock.operation = TrigonometryBlockOperations.Sqrt;
@@ -233,12 +234,12 @@ export class BlockTools {
                 let signBlock = new TrigonometryBlock("Sign");
                 signBlock.operation = TrigonometryBlockOperations.Sign;
                 return signBlock;
-            }            
+            }
             case "LogBlock": {
                 let logBlock = new TrigonometryBlock("Log");
                 logBlock.operation = TrigonometryBlockOperations.Log;
                 return logBlock;
-            }                                                            
+            }
             case "ExpBlock": {
                 let expBlock = new TrigonometryBlock("Exp");
                 expBlock.operation = TrigonometryBlockOperations.Exp;
@@ -258,7 +259,7 @@ export class BlockTools {
                 let radiansToDegreesBlock = new TrigonometryBlock("Radians to degrees");
                 radiansToDegreesBlock.operation = TrigonometryBlockOperations.Degrees;
                 return radiansToDegreesBlock;
-            }                        
+            }
             case "RoundBlock": {
                 let roundBlock = new TrigonometryBlock("Round");
                 roundBlock.operation = TrigonometryBlockOperations.Round;
@@ -268,22 +269,22 @@ export class BlockTools {
                 let ceilingBlock = new TrigonometryBlock("Ceiling");
                 ceilingBlock.operation = TrigonometryBlockOperations.Ceiling;
                 return ceilingBlock;
-            }     
+            }
             case "FloorBlock": {
                 let floorBlock = new TrigonometryBlock("Floor");
                 floorBlock.operation = TrigonometryBlockOperations.Floor;
                 return floorBlock;
-            }       
+            }
             case "SawToothWaveBlock": {
                 let sawToothWaveBlock = new WaveBlock("SawTooth wave");
                 sawToothWaveBlock.kind = WaveBlockKind.SawTooth;
                 return sawToothWaveBlock;
-            }     
+            }
             case "SquareWaveBlock": {
                 let squareWaveBlock = new WaveBlock("Square wave");
                 squareWaveBlock.kind = WaveBlockKind.Square;
                 return squareWaveBlock;
-            }     
+            }
             case "TriangleWaveBlock": {
                 let triangleWaveBlock = new WaveBlock("Triangle wave");
                 triangleWaveBlock.kind = WaveBlockKind.Triangle;
@@ -293,95 +294,95 @@ export class BlockTools {
                 let worldMatrixBlock = new InputBlock("World");
                 worldMatrixBlock.setAsSystemValue(NodeMaterialSystemValues.World);
                 return worldMatrixBlock;
-            }             
+            }
             case "WorldViewMatrixBlock": {
                 let worldViewMatrixBlock = new InputBlock("World x View");
                 worldViewMatrixBlock.setAsSystemValue(NodeMaterialSystemValues.WorldView);
                 return worldViewMatrixBlock;
-            }             
+            }
             case "WorldViewProjectionMatrixBlock": {
                 let worldViewProjectionMatrixBlock = new InputBlock("World x View x Projection");
                 worldViewProjectionMatrixBlock.setAsSystemValue(NodeMaterialSystemValues.WorldViewProjection);
                 return worldViewProjectionMatrixBlock;
-            }                    
+            }
             case "ViewMatrixBlock": {
                 let viewMatrixBlock = new InputBlock("View");
                 viewMatrixBlock.setAsSystemValue(NodeMaterialSystemValues.View);
                 return viewMatrixBlock;
-            }                          
+            }
             case "ViewProjectionMatrixBlock": {
                 let viewProjectionMatrixBlock = new InputBlock("View x Projection");
                 viewProjectionMatrixBlock.setAsSystemValue(NodeMaterialSystemValues.ViewProjection);
                 return viewProjectionMatrixBlock;
-            }                              
+            }
             case "ProjectionMatrixBlock": {
                 let projectionMatrixBlock = new InputBlock("Projection");
                 projectionMatrixBlock.setAsSystemValue(NodeMaterialSystemValues.Projection);
                 return projectionMatrixBlock;
-            }                                 
+            }
             case "CameraPositionBlock": {
                 let cameraPosition = new InputBlock("Camera position");
                 cameraPosition.setAsSystemValue(NodeMaterialSystemValues.CameraPosition);
                 return cameraPosition;
-            }                              
+            }
             case "FogColorBlock": {
                 let FogColor = new InputBlock("Fog color");
                 FogColor.setAsSystemValue(NodeMaterialSystemValues.FogColor);
                 return FogColor;
-            }                                   
+            }
             case "PositionBlock": {
                 let meshPosition = new InputBlock("position");
                 meshPosition.setAsAttribute("position");
                 return meshPosition;
-            }                                        
+            }
             case "UVBlock": {
                 let meshUV = new InputBlock("uv");
                 meshUV.setAsAttribute("uv");
                 return meshUV;
-            }                                         
+            }
             case "ColorBlock": {
                 let meshColor = new InputBlock("color");
                 meshColor.setAsAttribute("color");
                 return meshColor;
-            }                                              
+            }
             case "NormalBlock": {
                 let meshNormal = new InputBlock("normal");
                 meshNormal.setAsAttribute("normal");
                 return meshNormal;
-            }                                                 
+            }
             case "TangentBlock": {
                 let meshTangent = new InputBlock("tangent");
                 meshTangent.setAsAttribute("tangent");
                 return meshTangent;
-            }                                                  
+            }
             case "MatrixIndicesBlock": {
                 let meshMatrixIndices = new InputBlock("matricesIndices");
                 meshMatrixIndices.setAsAttribute("matricesIndices");
                 return meshMatrixIndices;
-            }                                                    
+            }
             case "MatrixWeightsBlock": {
                 let meshMatrixWeights = new InputBlock("matricesWeights");
                 meshMatrixWeights.setAsAttribute("matricesWeights");
                 return meshMatrixWeights;
-            }                                                     
+            }
             case "TimeBlock": {
                 let timeBlock = new InputBlock("Time", undefined, NodeMaterialBlockConnectionPointTypes.Float);
                 timeBlock.animationType = AnimatedInputBlockTypes.Time;
                 return timeBlock;
-            }   
+            }
             case "DeltaTimeBlock": {
-                let deltaTimeBlock = new InputBlock("Delta time");                
+                let deltaTimeBlock = new InputBlock("Delta time");
                 deltaTimeBlock.setAsSystemValue(NodeMaterialSystemValues.DeltaTime);
                 return deltaTimeBlock;
-            }      
+            }
             case "WorldPositionBlock": {
-                let worldPositionBlock = nodeMaterial.getInputBlockByPredicate(b => b.isAttribute && b.name === "position");                
+                let worldPositionBlock = nodeMaterial.getInputBlockByPredicate((b) => b.isAttribute && b.name === "position");
                 if (!worldPositionBlock) {
                     worldPositionBlock = new InputBlock("position");
                     worldPositionBlock.setAsAttribute("position");
                 }
 
-                let worldMatrixBlock = nodeMaterial.getInputBlockByPredicate(b => b.isSystemValue && b.systemValue === NodeMaterialSystemValues.World);  
+                let worldMatrixBlock = nodeMaterial.getInputBlockByPredicate((b) => b.isSystemValue && b.systemValue === NodeMaterialSystemValues.World);
 
                 if (!worldMatrixBlock) {
                     worldMatrixBlock = new InputBlock("World");
@@ -393,15 +394,15 @@ export class BlockTools {
                 worldMatrixBlock.connectTo(transformBlock);
 
                 return transformBlock;
-            }        
+            }
             case "WorldNormalBlock": {
-                let worldNormalBlock = nodeMaterial.getInputBlockByPredicate(b => b.isAttribute && b.name === "normal");                
+                let worldNormalBlock = nodeMaterial.getInputBlockByPredicate((b) => b.isAttribute && b.name === "normal");
                 if (!worldNormalBlock) {
                     worldNormalBlock = new InputBlock("normal");
                     worldNormalBlock.setAsAttribute("normal");
                 }
 
-                let worldMatrixBlock = nodeMaterial.getInputBlockByPredicate(b => b.isSystemValue && b.systemValue === NodeMaterialSystemValues.World);  
+                let worldMatrixBlock = nodeMaterial.getInputBlockByPredicate((b) => b.isSystemValue && b.systemValue === NodeMaterialSystemValues.World);
 
                 if (!worldMatrixBlock) {
                     worldMatrixBlock = new InputBlock("World");
@@ -413,15 +414,15 @@ export class BlockTools {
                 worldMatrixBlock.connectTo(transformBlock);
 
                 return transformBlock;
-            }     
+            }
             case "WorldTangentBlock": {
-                let worldTangentBlock = nodeMaterial.getInputBlockByPredicate(b => b.isAttribute && b.name === "tangent");                
+                let worldTangentBlock = nodeMaterial.getInputBlockByPredicate((b) => b.isAttribute && b.name === "tangent");
                 if (!worldTangentBlock) {
                     worldTangentBlock = new InputBlock("tangent");
                     worldTangentBlock.setAsAttribute("tangent");
                 }
 
-                let worldMatrixBlock = nodeMaterial.getInputBlockByPredicate(b => b.isSystemValue && b.systemValue === NodeMaterialSystemValues.World);  
+                let worldMatrixBlock = nodeMaterial.getInputBlockByPredicate((b) => b.isSystemValue && b.systemValue === NodeMaterialSystemValues.World);
 
                 if (!worldMatrixBlock) {
                     worldMatrixBlock = new InputBlock("World");
@@ -433,12 +434,14 @@ export class BlockTools {
                 worldMatrixBlock.connectTo(transformBlock);
 
                 return transformBlock;
-            }              
+            }
             case "PBRMetallicRoughnessBlock":
                 return new PBRMetallicRoughnessBlock("PBRMetallicRoughness");
             case "SheenBlock":
                 return new SheenBlock("Sheen");
-            }
+            case "AmbientOcclusionBlock":
+                return new AmbientOcclusionBlock("AmbientOcclusion");
+        }
 
         return null;
     }
@@ -447,21 +450,21 @@ export class BlockTools {
         let color = "#880000";
         switch (type) {
             case NodeMaterialBlockConnectionPointTypes.Float:
-				color = "#cb9e27";
+                color = "#cb9e27";
                 break;
-            case NodeMaterialBlockConnectionPointTypes.Vector2:                
-				color = "#16bcb1";
+            case NodeMaterialBlockConnectionPointTypes.Vector2:
+                color = "#16bcb1";
                 break;
-            case NodeMaterialBlockConnectionPointTypes.Vector3:                
-            case NodeMaterialBlockConnectionPointTypes.Color3:                
+            case NodeMaterialBlockConnectionPointTypes.Vector3:
+            case NodeMaterialBlockConnectionPointTypes.Color3:
                 color = "#b786cb";
                 break;
-            case NodeMaterialBlockConnectionPointTypes.Vector4:                
-            case NodeMaterialBlockConnectionPointTypes.Color4:                
-				color = "#be5126";
+            case NodeMaterialBlockConnectionPointTypes.Vector4:
+            case NodeMaterialBlockConnectionPointTypes.Color4:
+                color = "#be5126";
                 break;
-            case NodeMaterialBlockConnectionPointTypes.Matrix:                
-				color = "#591990";
+            case NodeMaterialBlockConnectionPointTypes.Matrix:
+                color = "#591990";
                 break;
         }
 

+ 15 - 14
nodeEditor/src/components/nodeList/nodeListComponent.tsx

@@ -12,7 +12,7 @@ interface INodeListComponentProps {
 
 export class NodeListComponent extends React.Component<INodeListComponentProps, {filter: string}> {
 
-    private static _Tooltips:{[key: string]: string} = {
+    private static _Tooltips: {[key: string]: string} = {
         "BonesBlock": "Provides a world matrix for each vertex, based on skeletal (bone/joint) animation",
         "MorphTargetsBlock": "Provides the final positions, normals, tangents, and uvs based on morph targets in a mesh",
         "AddBlock": "Adds the left and right inputs of the same type together",
@@ -79,7 +79,7 @@ export class NodeListComponent extends React.Component<INodeListComponentProps,
         "CameraPositionBlock": "Outputs a Vector3 position of the active scene camera",
         "FogBlock": "Applies fog to the scene with an increasing opacity based on distance from the camera",
         "FogColorBlock": "The system value for fog color pulled from the scene",
-        "ImageProcessingBlock": "Provides access to all of the Babylon image processing properties",        
+        "ImageProcessingBlock": "Provides access to all of the Babylon image processing properties",
         "LightBlock": "Outputs diffuse and specular contributions from one or more scene lights",
         "LightInformationBlock": "Provides the direction, color and intensity of a selected light based on its world position",
         "ReflectionTextureBlock": "Creates a reflection from the input texture",
@@ -115,11 +115,12 @@ export class NodeListComponent extends React.Component<INodeListComponentProps,
         "SimplexPerlin3DBlock": "Creates a type of gradient noise with few directional artifacts.",
         "WorleyNoise3DBlock": "Creates a random pattern resembling cells.",
         "ReflectBlock": "Outputs the direction of the input vector reflected across the surface normal.",
-        "RefractBlock": "Outputs a direction simulating a deflection of the input vector.", 
+        "RefractBlock": "Outputs a direction simulating a deflection of the input vector.",
         "Rotate2dBlock": "Rotates UV coordinates around the W axis.",
         "PBRMetallicRoughnessBlock": "PBR metallic/roughness material",
-        "SheenBlock": "Sheen block"
-    }
+        "SheenBlock": "Sheen block",
+        "AmbientOcclusionBlock": "Ambient occlusion block"
+    };
 
     constructor(props: INodeListComponentProps) {
         super(props);
@@ -134,34 +135,34 @@ export class NodeListComponent extends React.Component<INodeListComponentProps,
     render() {
         // Block types used to create the menu from
         const allBlocks = {
-            
+
             Animation: ["BonesBlock", "MorphTargetsBlock"],
             Color_Management: ["ReplaceColorBlock", "PosterizeBlock", "GradientBlock", "DesaturateBlock"],
             Conversion_Blocks: ["ColorMergerBlock", "ColorSplitterBlock", "VectorMergerBlock", "VectorSplitterBlock"],
             Inputs: ["Float", "Vector2", "Vector3", "Vector4", "Color3", "Color4", "TextureBlock", "ReflectionTextureBlock", "TimeBlock", "DeltaTimeBlock"],
             Interpolation: ["LerpBlock", "StepBlock", "SmoothStepBlock", "NLerpBlock"],
-            Math__Standard: ["AddBlock", "DivideBlock", "MaxBlock", "MinBlock", "MultiplyBlock", "NegateBlock", "OneMinusBlock", "ReciprocalBlock", "ScaleBlock", "SignBlock", "SqrtBlock", "SubtractBlock"], 
+            Math__Standard: ["AddBlock", "DivideBlock", "MaxBlock", "MinBlock", "MultiplyBlock", "NegateBlock", "OneMinusBlock", "ReciprocalBlock", "ScaleBlock", "SignBlock", "SqrtBlock", "SubtractBlock"],
             Math__Scientific: ["AbsBlock", "ArcCosBlock", "ArcSinBlock", "ArcTanBlock", "ArcTan2Block", "CosBlock", "DegreesToRadiansBlock", "ExpBlock", "Exp2Block", "FractBlock", "LogBlock", "PowBlock", "RadiansToDegreesBlock", "SawToothWaveBlock", "SinBlock", "SquareWaveBlock", "TanBlock", "TriangleWaveBlock"],
             Math__Vector: ["CrossBlock", "DerivativeBlock", "DistanceBlock", "DotBlock", "FresnelBlock", "LengthBlock", "ReflectBlock", "RefractBlock", "Rotate2dBlock", "TransformBlock", ],
             Matrices: ["Matrix", "WorldMatrixBlock", "WorldViewMatrixBlock", "WorldViewProjectionMatrixBlock", "ViewMatrixBlock", "ViewProjectionMatrixBlock", "ProjectionMatrixBlock"],
-            Mesh: ["InstancesBlock", "PositionBlock", "UVBlock", "ColorBlock", "NormalBlock", "PerturbNormalBlock", "NormalBlendBlock" , "TangentBlock", "MatrixIndicesBlock", "MatrixWeightsBlock", "WorldPositionBlock", "WorldNormalBlock", "WorldTangentBlock", "FrontFacingBlock"], 
+            Mesh: ["InstancesBlock", "PositionBlock", "UVBlock", "ColorBlock", "NormalBlock", "PerturbNormalBlock", "NormalBlendBlock" , "TangentBlock", "MatrixIndicesBlock", "MatrixWeightsBlock", "WorldPositionBlock", "WorldNormalBlock", "WorldTangentBlock", "FrontFacingBlock"],
             Noises: ["RandomNumberBlock", "SimplexPerlin3DBlock", "WorleyNoise3DBlock"],
             Output_Nodes: ["VertexOutputBlock", "FragmentOutputBlock", "DiscardBlock"],
-            PBR: ["PBRMetallicRoughnessBlock", "SheenBlock"],
+            PBR: ["AmbientOcclusionBlock", "PBRMetallicRoughnessBlock", "SheenBlock"],
             Range: ["ClampBlock", "RemapBlock", "NormalizeBlock"],
             Round: ["RoundBlock", "CeilingBlock", "FloorBlock"],
             Scene: ["FogBlock", "CameraPositionBlock", "FogColorBlock", "ImageProcessingBlock", "LightBlock", "LightInformationBlock", "ViewDirectionBlock"],
-        }
+        };
 
         // Create node menu
-        var blockMenu = []
+        var blockMenu = [];
         for (var key in allBlocks) {
             var blockList = (allBlocks as any)[key].filter((b: string) => !this.state.filter || b.toLowerCase().indexOf(this.state.filter.toLowerCase()) !== -1)
             .sort((a: string, b: string) => a.localeCompare(b))
             .map((block: any, i: number) => {
                 let tooltip = NodeListComponent._Tooltips[block] || "";
 
-                return <DraggableLineComponent key={block} data={block} tooltip={tooltip}/>
+                return <DraggableLineComponent key={block} data={block} tooltip={tooltip}/>;
             });
 
             if (blockList.length) {
@@ -178,9 +179,9 @@ export class NodeListComponent extends React.Component<INodeListComponentProps,
                 <div className="panes">
                     <div className="pane">
                         <div className="filter">
-                            <input type="text" placeholder="Filter" 
+                            <input type="text" placeholder="Filter"
                                 onFocus={() => this.props.globalState.blockKeyboardEvents = true}
-                                onBlur={evt => {
+                                onBlur={(evt) => {
                                     this.props.globalState.blockKeyboardEvents = false;
                                 }}
                                 onChange={(evt) => this.filterContent(evt.target.value)} />

+ 51 - 0
src/Materials/Node/Blocks/Fragment/ambientOcclusionBlock.ts

@@ -0,0 +1,51 @@
+import { NodeMaterialBlock } from '../../nodeMaterialBlock';
+import { NodeMaterialBlockConnectionPointTypes } from '../../Enums/nodeMaterialBlockConnectionPointTypes';
+import { NodeMaterialBuildState } from '../../nodeMaterialBuildState';
+import { NodeMaterialConnectionPoint } from '../../nodeMaterialBlockConnectionPoint';
+import { NodeMaterialBlockTargets } from '../../Enums/nodeMaterialBlockTargets';
+import { _TypeStore } from '../../../../Misc/typeStore';
+
+export class AmbientOcclusionBlock extends NodeMaterialBlock {
+
+    public constructor(name: string) {
+        super(name, NodeMaterialBlockTargets.Fragment);
+
+        this.registerInput("texture", NodeMaterialBlockConnectionPointTypes.Color3, true, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("intensity", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("directLightIntensity", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
+
+        this.registerOutput("ambientOcclusion", NodeMaterialBlockConnectionPointTypes.Float, NodeMaterialBlockTargets.Fragment);
+    }
+
+    /**
+     * Gets the current class name
+     * @returns the class name
+     */
+    public getClassName() {
+        return "ambientOcclusionBlock";
+    }
+
+    public get texture(): NodeMaterialConnectionPoint {
+        return this._inputs[0];
+    }
+
+    public get intensity(): NodeMaterialConnectionPoint {
+        return this._inputs[1];
+    }
+
+    public get directLightIntensity(): NodeMaterialConnectionPoint {
+        return this._inputs[2];
+    }
+
+    public get ambientOcclusion(): NodeMaterialConnectionPoint {
+        return this._outputs[0];
+    }
+
+    protected _buildBlock(state: NodeMaterialBuildState) {
+        super._buildBlock(state);
+
+        return this;
+    }
+}
+
+_TypeStore.RegisteredTypes["BABYLON.ambientOcclusionBlock"] = AmbientOcclusionBlock;

+ 1 - 0
src/Materials/Node/Blocks/Fragment/index.ts

@@ -7,3 +7,4 @@ export * from "./frontFacingBlock";
 export * from "./derivativeBlock";
 export * from "./pbrMetallicRoughnessBlock";
 export * from "./sheenBlock";
+export * from "./ambientOcclusionBlock";

+ 67 - 29
src/Materials/Node/Blocks/Fragment/pbrMetallicRoughnessBlock.ts

@@ -13,7 +13,9 @@ import { _TypeStore } from '../../../../Misc/typeStore';
 import { AbstractMesh } from '../../../../Meshes/abstractMesh';
 import { Effect, IEffectCreationOptions } from '../../../effect';
 import { Mesh } from '../../../../Meshes/mesh';
+import { PBRBaseMaterial } from '../../../PBR/pbrBaseMaterial';
 import { Scene } from '../../../../scene';
+import { AmbientOcclusionBlock } from './ambientOcclusionBlock';
 
 export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
     private _lightId: number;
@@ -38,6 +40,7 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
         this.registerInput("roughness", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
         this.registerInput("metalRoughText", NodeMaterialBlockConnectionPointTypes.Color4, true, NodeMaterialBlockTargets.Fragment);
         this.registerInput("opacityTexture", NodeMaterialBlockConnectionPointTypes.Color4, true, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("ambientColor", NodeMaterialBlockConnectionPointTypes.Color3, true, NodeMaterialBlockTargets.Fragment);
         this.registerInput("ambientOcclusion", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
         this.registerInput("reflection", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
         this.registerInput("sheen", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
@@ -108,30 +111,34 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
         return this._inputs[9];
     }
 
-    public get ambientOcclusionParams(): NodeMaterialConnectionPoint {
+    public get ambientColor(): NodeMaterialConnectionPoint {
         return this._inputs[10];
     }
 
-    public get reflectionParams(): NodeMaterialConnectionPoint {
+    public get ambientOcclusionParams(): NodeMaterialConnectionPoint {
         return this._inputs[11];
     }
 
-    public get sheenParams(): NodeMaterialConnectionPoint {
+    public get reflectionParams(): NodeMaterialConnectionPoint {
         return this._inputs[12];
     }
 
-    public get clearcoatParams(): NodeMaterialConnectionPoint {
+    public get sheenParams(): NodeMaterialConnectionPoint {
         return this._inputs[13];
     }
 
-    public get subSurfaceParams(): NodeMaterialConnectionPoint {
+    public get clearcoatParams(): NodeMaterialConnectionPoint {
         return this._inputs[14];
     }
 
-    public get anisotropyParams(): NodeMaterialConnectionPoint {
+    public get subSurfaceParams(): NodeMaterialConnectionPoint {
         return this._inputs[15];
     }
 
+    public get anisotropyParams(): NodeMaterialConnectionPoint {
+        return this._inputs[16];
+    }
+
     public get ambient(): NodeMaterialConnectionPoint {
         return this._outputs[0];
     }
@@ -193,6 +200,22 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
     }
 
     public prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines) {
+        defines.setValue("PBR", true);
+
+        // Albedo & Opacity
+        if (this.baseTexture.isConnected) {
+            defines.setValue("ALBEDO", true);
+        }
+
+        if (this.opacityTexture.isConnected) {
+            defines.setValue("OPACITY", true);
+        }
+
+        // Ambient occlusion
+        const aoBlock = this.ambientOcclusionParams.connectedPoint?.ownerBlock as Nullable<AmbientOcclusionBlock>;
+
+        defines.setValue("AMBIENT", aoBlock?.texture.isConnected ?? false);
+
         if (!defines._areLightsDirty) {
             return;
         }
@@ -204,6 +227,8 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
             MaterialHelper.PrepareDefinesForLights(scene, mesh, defines, true, nodeMaterial.maxSimultaneousLights);
             defines._needNormals = true;
 
+            defines.setValue("SPECULARTERM", false); //!! DBG
+
             // Multiview
             //MaterialHelper.PrepareDefinesForMultiview(scene, defines);
         } else {
@@ -221,14 +246,6 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
                 defines.rebuild();
             }
         }
-
-        if (this.baseTexture.isConnected) {
-            defines.setValue("ALBEDO", true);
-        }
-
-        if (this.opacityTexture.isConnected) {
-            defines.setValue("OPACITY", true);
-        }
     }
 
     public updateUniformsAndSamples(state: NodeMaterialBuildState, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines, uniformBuffers: string[]) {
@@ -389,6 +406,16 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
         //
         // code
         //
+        const vLightingIntensity = "vec4(1.)";
+
+        const aoBlock = this.ambientOcclusionParams.connectedPoint?.ownerBlock as Nullable<AmbientOcclusionBlock>;
+        const aoColor = this.ambientColor.isConnected ? this.ambientColor.associatedVariableName : "vec3(0., 0., 0.)";
+        let aoDirectLightIntensity = aoBlock?.directLightIntensity.isConnected ? aoBlock.directLightIntensity.associatedVariableName : PBRBaseMaterial.DEFAULT_AO_ON_ANALYTICAL_LIGHTS.toString();
+
+        if (!aoBlock?.directLightIntensity.isConnected && aoDirectLightIntensity.charAt(aoDirectLightIntensity.length - 1) !== '.') {
+            aoDirectLightIntensity += ".";
+        }
+
         if (this._lightId === 0) {
             // _____________________________ Geometry Information ____________________________
             if (state._registerTempVariable("viewDirectionW")) {
@@ -432,19 +459,20 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
             // _____________________________ AO  _______________________________
             state.compilationString += `ambientOcclusionOutParams aoOut;\r\n`;
 
-            const aoBlock = this.ambientOcclusionParams.connectedPoint?.ownerBlock;
-            const aoTexture = "";//this.ambientOcclusion.isConnected ? this.aoTexture.associatedVariableName : "";
+            const aoTexture = aoBlock?.texture.isConnected ? aoBlock.texture.associatedVariableName : "vec2(0., 0.)";
+            const aoLevel = "1.";
+            const aoIntensity = aoBlock?.intensity.isConnected ? aoBlock.intensity.associatedVariableName : "1.";
 
             state.compilationString += `ambientOcclusionBlock(
-                    #ifdef AMBIENT
-                        ${aoTexture},
-                        vec2(1., 1.),
-                    #endif
-                        aoOut
-                    );\r\n`;
+                #ifdef AMBIENT
+                    ${aoTexture},
+                    vec4(0., ${aoLevel}, ${aoIntensity}, 0.),
+                #endif
+                    aoOut
+                );\r\n`;
 
             // _____________________________ Direct Lighting Info __________________________________
-            //state.compilationString += state._emitCodeFromInclude("pbrBlockDirectLighting", comments);
+            state.compilationString += state._emitCodeFromInclude("pbrBlockDirectLighting", comments);
         }
 
         /*if (this.light) {
@@ -457,24 +485,34 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
             state.compilationString += state._emitCodeFromInclude("lightFragment", comments, {
                 repeatKey: "maxSimultaneousLights"
             });
-        }
+        }*/
 
         // _____________________________ Compute Final Lit and Unlit Components ________________________
-        state.compilationString += state._emitCodeFromInclude("pbrBlockFinalLitComponents", comments);
+        //state.compilationString += state._emitCodeFromInclude("pbrBlockFinalLitComponents", comments);
 
-        state.compilationString += state._emitCodeFromInclude("pbrBlockFinalUnlitComponents", comments);
+        state.compilationString += state._emitCodeFromInclude("pbrBlockFinalUnlitComponents", comments, {
+            replaceStrings: [
+                { search: /vec3 finalEmissive[\s\S]*?finalEmissive\*=vLightingIntensity\.y;/g, replace: "" },
+                { search: /vAmbientColor/g, replace: aoColor },
+                { search: /vLightingIntensity/g, replace: vLightingIntensity },
+                { search: /vAmbientInfos\.w/g, replace: aoDirectLightIntensity },
+            ]
+        });
 
-        state.compilationString += state._emitCodeFromInclude("pbrBlockFinalColorComposition", comments);*/
+        state.compilationString += state._emitCodeFromInclude("pbrBlockFinalColorComposition", comments, {
+            replaceStrings: [
+                { search: /finalEmissive/g, replace: "vec3(0.)" },
+            ]
+        });
 
         if (this.lighting.hasEndpoints) {
-            state.compilationString += this._declareOutput(this.lighting, state) + ` = vec4(surfaceAlbedo, alpha);\r\n`;
+            state.compilationString += this._declareOutput(this.lighting, state) + ` = finalColor;\r\n`;
         }
 
         if (this.shadow.hasEndpoints) {
             state.compilationString += this._declareOutput(this.shadow, state) + ` = shadow;\r\n`;
         }
 
-        console.log(this.sheenParams);
         (window as any).sheenParams = this.sheenParams;
         return this;
     }