Popov72 5 سال پیش
والد
کامیت
c501889038

+ 7 - 2
src/Materials/Node/Blocks/Dual/reflectionTextureBaseBlock.ts

@@ -19,7 +19,7 @@ import { CubeTexture } from '../../../Textures/cubeTexture';
 import { Texture } from '../../../Textures/texture';
 
 /**
- * Block used to read a reflection texture from a sampler
+ * Base block used to read a reflection texture from a sampler
  */
 export abstract class ReflectionTextureBaseBlock extends NodeMaterialBlock {
     /** @hidden */
@@ -60,7 +60,7 @@ export abstract class ReflectionTextureBaseBlock extends NodeMaterialBlock {
     public texture: Nullable<BaseTexture>;
 
     /**
-     * Create a new TextureBlock
+     * Create a new ReflectionTextureBaseBlock
      * @param name defines the block name
      */
     public constructor(name: string) {
@@ -191,6 +191,11 @@ export abstract class ReflectionTextureBaseBlock extends NodeMaterialBlock {
         }
     }
 
+    /**
+     * Gets the code to inject in the vertex shader
+     * @param state current state of the node material building
+     * @returns the shader code
+     */
     public handleVertexSide(state: NodeMaterialBuildState): string {
         this._define3DName = state._getFreeDefineName("REFLECTIONMAP_3D");
         this._defineCubicName = state._getFreeDefineName("REFLECTIONMAP_CUBIC");

+ 30 - 2
src/Materials/Node/Blocks/PBR/ambientOcclusionBlock.ts

@@ -11,8 +11,15 @@ import { AbstractMesh } from '../../../../Meshes/abstractMesh';
 import { NodeMaterialConnectionPointCustomObject } from "../../nodeMaterialConnectionPointCustomObject";
 import { Scene } from '../../../../scene';
 
+/**
+ * Block used to implement the ambient occlusion module of the PBR material
+ */
 export class AmbientOcclusionBlock extends NodeMaterialBlock {
 
+    /**
+     * Create a new AmbientOcclusionBlock
+     * @param name defines the block name
+     */
     public constructor(name: string) {
         super(name, NodeMaterialBlockTargets.Fragment);
 
@@ -22,9 +29,13 @@ export class AmbientOcclusionBlock extends NodeMaterialBlock {
         this.registerInput("intensity", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
         this.registerInput("directLightIntensity", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
 
-        this.registerOutput("ambientOcclusion", NodeMaterialBlockConnectionPointTypes.Object, NodeMaterialBlockTargets.Fragment, new NodeMaterialConnectionPointCustomObject("ambientOcclusion", this, NodeMaterialConnectionPointDirection.Output, AmbientOcclusionBlock, "AOBlock"));
+        this.registerOutput("ambientOcclusion", NodeMaterialBlockConnectionPointTypes.Object, NodeMaterialBlockTargets.Fragment,
+            new NodeMaterialConnectionPointCustomObject("ambientOcclusion", this, NodeMaterialConnectionPointDirection.Output, AmbientOcclusionBlock, "AOBlock"));
     }
 
+    /**
+     * Specifies if the ambient texture contains the ambient occlusion information in its red channel only.
+     */
     @editableInPropertyPage("Ambient in gray scale", PropertyTypeForEdition.Boolean, "AMBIENT", { "notifiers": { "update": true }})
     public useAmbientInGrayScale: boolean = false;
 
@@ -41,25 +52,42 @@ export class AmbientOcclusionBlock extends NodeMaterialBlock {
      * @returns the class name
      */
     public getClassName() {
-        return "ambientOcclusionBlock";
+        return "AmbientOcclusionBlock";
     }
 
+    /**
+     * Gets the texture input component
+     */
     public get texture(): NodeMaterialConnectionPoint {
         return this._inputs[0];
     }
 
+    /**
+     * Gets the texture intensity component
+     */
     public get intensity(): NodeMaterialConnectionPoint {
         return this._inputs[1];
     }
 
+    /**
+     * Gets the direct light intensity input component
+     */
     public get directLightIntensity(): NodeMaterialConnectionPoint {
         return this._inputs[2];
     }
 
+    /**
+     * Gets the ambient occlusion object output component
+     */
     public get ambientOcclusion(): NodeMaterialConnectionPoint {
         return this._outputs[0];
     }
 
+    /**
+     * Gets the main code of the block (fragment side)
+     * @param block instance of an AmbientOcclusionBlock or null if the code must be generated without an active ambient occlusion module
+     * @returns the shader code
+     */
     public static getCode(block: Nullable<AmbientOcclusionBlock>): string {
         let code = `ambientOcclusionOutParams aoOut;\r\n`;
 

+ 40 - 6
src/Materials/Node/Blocks/PBR/anisotropyBlock.ts

@@ -8,11 +8,26 @@ import { _TypeStore } from '../../../../Misc/typeStore';
 import { AbstractMesh } from '../../../../Meshes/abstractMesh';
 import { NodeMaterialConnectionPointCustomObject } from "../../nodeMaterialConnectionPointCustomObject";
 
+/**
+ * Block used to implement the anisotropy module of the PBR material
+ */
 export class AnisotropyBlock extends NodeMaterialBlock {
 
+    /**
+     * The two properties below are set by the main PBR block prior to calling methods of this class.
+     * This is to avoid having to add them as inputs here whereas they are already inputs of the main block, so already known.
+     * It's less burden on the user side in the editor part.
+    */
+
+    /** @hidden */
     public worldPositionConnectionPoint: NodeMaterialConnectionPoint;
+    /** @hidden */
     public worldNormalConnectionPoint: NodeMaterialConnectionPoint;
 
+    /**
+     * Create a new AnisotropyBlock
+     * @param name defines the block name
+     */
     public constructor(name: string) {
         super(name, NodeMaterialBlockTargets.Fragment);
 
@@ -21,10 +36,11 @@ export class AnisotropyBlock extends NodeMaterialBlock {
         this.registerInput("intensity", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
         this.registerInput("direction", NodeMaterialBlockConnectionPointTypes.Vector2, true, NodeMaterialBlockTargets.Fragment);
         this.registerInput("texture", NodeMaterialBlockConnectionPointTypes.Color3, true, NodeMaterialBlockTargets.Fragment);
-        this.registerInput("uv", NodeMaterialBlockConnectionPointTypes.Vector2, true);
+        this.registerInput("uv", NodeMaterialBlockConnectionPointTypes.Vector2, true); // need this property and the next one in case there's no PerturbNormal block connected to the main PBR block
         this.registerInput("worldTangent", NodeMaterialBlockConnectionPointTypes.Vector4, true);
 
-        this.registerOutput("anisotropy", NodeMaterialBlockConnectionPointTypes.Object, NodeMaterialBlockTargets.Fragment, new NodeMaterialConnectionPointCustomObject("anisotropy", this, NodeMaterialConnectionPointDirection.Output, AnisotropyBlock, "AnisotropyBlock"));
+        this.registerOutput("anisotropy", NodeMaterialBlockConnectionPointTypes.Object, NodeMaterialBlockTargets.Fragment,
+            new NodeMaterialConnectionPointCustomObject("anisotropy", this, NodeMaterialConnectionPointDirection.Output, AnisotropyBlock, "AnisotropyBlock"));
     }
 
     /**
@@ -44,26 +60,44 @@ export class AnisotropyBlock extends NodeMaterialBlock {
         return "AnisotropyBlock";
     }
 
+    /**
+     * Gets the intensity input component
+     */
     public get intensity(): NodeMaterialConnectionPoint {
         return this._inputs[0];
     }
 
+    /**
+     * Gets the direction input component
+     */
     public get direction(): NodeMaterialConnectionPoint {
         return this._inputs[1];
     }
 
+    /**
+     * Gets the texture input component
+     */
     public get texture(): NodeMaterialConnectionPoint {
         return this._inputs[2];
     }
 
+    /**
+     * Gets the uv input component
+     */
     public get uv(): NodeMaterialConnectionPoint {
         return this._inputs[3];
     }
 
+    /**
+     * Gets the worldTangent input component
+     */
     public get worldTangent(): NodeMaterialConnectionPoint {
         return this._inputs[4];
     }
 
+    /**
+     * Gets the anisotropy object output component
+     */
     public get anisotropy(): NodeMaterialConnectionPoint {
         return this._outputs[0];
     }
@@ -79,7 +113,8 @@ export class AnisotropyBlock extends NodeMaterialBlock {
 
         if (!uv.isConnected) {
             // we must set the uv input as optional because we may not end up in this method (in case a PerturbNormal block is linked to the PBR material)
-            // in which case uv is not required. But if we do come here, we do need the uv, so we have to throw an error
+            // in which case uv is not required. But if we do come here, we do need the uv, so we have to raise an error but not with throw, else
+            // it will stop the building of the node material and will lead to errors in the editor!
             console.error("You must connect the 'uv' input of the Anisotropy block!");
         }
 
@@ -122,13 +157,12 @@ export class AnisotropyBlock extends NodeMaterialBlock {
             code += this._generateTBNSpace(state);
         }
 
-        code += `anisotropicOutParams anisotropicOut;\r\n`;
-
         const intensity = this.intensity.isConnected ? this.intensity.associatedVariableName : "1.0";
         const direction = this.direction.isConnected ? this.direction.associatedVariableName : "vec2(1., 0.)";
         const texture = this.texture.isConnected ? this.texture.associatedVariableName : "vec3(0.)";
 
-        code += `anisotropicBlock(
+        code += `anisotropicOutParams anisotropicOut;
+            anisotropicBlock(
                 vec3(${direction}, ${intensity}),
             #ifdef ANISOTROPIC_TEXTURE
                 ${texture},

+ 187 - 42
src/Materials/Node/Blocks/PBR/pbrMetallicRoughnessBlock.ts

@@ -41,6 +41,9 @@ const mapOutputToVariable: { [name: string] : [string, string] } = {
     "shadow":       ["shadow", ""],
 };
 
+/**
+ * Block used to implement the PBR metallic/roughness model
+ */
 export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
     /**
      * Gets or sets the light associated with this block
@@ -52,6 +55,10 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
     private _environmentBRDFTexture: Nullable<BaseTexture> = null;
     private _environmentBrdfSamplerName: string;
 
+    /**
+     * Create a new ReflectionBlock
+     * @param name defines the block name
+     */
     public constructor(name: string) {
         super(name, NodeMaterialBlockTargets.VertexAndFragment);
 
@@ -64,20 +71,25 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
         this.registerInput("baseColor", NodeMaterialBlockConnectionPointTypes.Color4, true, NodeMaterialBlockTargets.Fragment);
         this.registerInput("baseTexture", NodeMaterialBlockConnectionPointTypes.Color4, true, NodeMaterialBlockTargets.Fragment);
         this.registerInput("opacityTexture", NodeMaterialBlockConnectionPointTypes.Color4, true, NodeMaterialBlockTargets.Fragment);
-        this.registerInput("reflectivity", NodeMaterialBlockConnectionPointTypes.Object, false, NodeMaterialBlockTargets.Fragment, new NodeMaterialConnectionPointCustomObject("reflectivity", this, NodeMaterialConnectionPointDirection.Input, ReflectivityBlock, "ReflectivityBlock"));
         this.registerInput("ambientColor", NodeMaterialBlockConnectionPointTypes.Color3, true, NodeMaterialBlockTargets.Fragment);
-        this.registerInput("ambientOcclusion", NodeMaterialBlockConnectionPointTypes.Object, true, NodeMaterialBlockTargets.Fragment, new NodeMaterialConnectionPointCustomObject("ambientOcclusion", this, NodeMaterialConnectionPointDirection.Input, AmbientOcclusionBlock, "AOBlock"));
-        this.registerInput("reflection", NodeMaterialBlockConnectionPointTypes.Object, true, NodeMaterialBlockTargets.Fragment, new NodeMaterialConnectionPointCustomObject("reflection", this, NodeMaterialConnectionPointDirection.Input, ReflectionBlock, "ReflectionBlock"));
-        this.registerInput("sheen", NodeMaterialBlockConnectionPointTypes.Object, true, NodeMaterialBlockTargets.Fragment, new NodeMaterialConnectionPointCustomObject("sheen", this, NodeMaterialConnectionPointDirection.Input, SheenBlock, "SheenBlock"));
+        this.registerInput("reflectivity", NodeMaterialBlockConnectionPointTypes.Object, false, NodeMaterialBlockTargets.Fragment,
+            new NodeMaterialConnectionPointCustomObject("reflectivity", this, NodeMaterialConnectionPointDirection.Input, ReflectivityBlock, "ReflectivityBlock"));
+        this.registerInput("ambientOcclusion", NodeMaterialBlockConnectionPointTypes.Object, true, NodeMaterialBlockTargets.Fragment,
+            new NodeMaterialConnectionPointCustomObject("ambientOcclusion", this, NodeMaterialConnectionPointDirection.Input, AmbientOcclusionBlock, "AOBlock"));
+        this.registerInput("reflection", NodeMaterialBlockConnectionPointTypes.Object, true, NodeMaterialBlockTargets.Fragment,
+            new NodeMaterialConnectionPointCustomObject("reflection", this, NodeMaterialConnectionPointDirection.Input, ReflectionBlock, "ReflectionBlock"));
+        this.registerInput("sheen", NodeMaterialBlockConnectionPointTypes.Object, true, NodeMaterialBlockTargets.Fragment,
+            new NodeMaterialConnectionPointCustomObject("sheen", this, NodeMaterialConnectionPointDirection.Input, SheenBlock, "SheenBlock"));
         this.registerInput("clearCoat", NodeMaterialBlockConnectionPointTypes.Object, true, NodeMaterialBlockTargets.Fragment);
         this.registerInput("subSurface", NodeMaterialBlockConnectionPointTypes.Object, true, NodeMaterialBlockTargets.Fragment);
-        this.registerInput("anisotropy", NodeMaterialBlockConnectionPointTypes.Object, true, NodeMaterialBlockTargets.Fragment, new NodeMaterialConnectionPointCustomObject("anisotropy", this, NodeMaterialConnectionPointDirection.Input, AnisotropyBlock, "AnisotropyBlock"));
+        this.registerInput("anisotropy", NodeMaterialBlockConnectionPointTypes.Object, true, NodeMaterialBlockTargets.Fragment,
+            new NodeMaterialConnectionPointCustomObject("anisotropy", this, NodeMaterialConnectionPointDirection.Input, AnisotropyBlock, "AnisotropyBlock"));
 
         this.registerOutput("ambient", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
         this.registerOutput("diffuse", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
         this.registerOutput("specular", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
-        this.registerOutput("sheen", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
-        this.registerOutput("clearcoat", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
+        this.registerOutput("sheenDir", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
+        this.registerOutput("clearcoatDir", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
         this.registerOutput("diffuseInd", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
         this.registerOutput("specularInd", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
         this.registerOutput("sheenInd", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
@@ -87,42 +99,89 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
         this.registerOutput("shadow", NodeMaterialBlockConnectionPointTypes.Float, NodeMaterialBlockTargets.Fragment);
     }
 
+    /**
+     * Specifies that the alpha is coming form the albedo channel alpha channel for alpha blending.
+     */
     @editableInPropertyPage("Alpha from albedo", PropertyTypeForEdition.Boolean, "TRANSPARENCY", { "notifiers": { "update": true }})
     public useAlphaFromAlbedoTexture: boolean = false;
 
-    @editableInPropertyPage("Alpha Testing", PropertyTypeForEdition.Boolean, "TRANSPARENCY", { "notifiers": { "update": true }})
+    /**
+     * Specifies that alpha test should be used
+     */
+    @editableInPropertyPage("Alpha Testing", PropertyTypeForEdition.Boolean, "TRANSPARENCY")
     public useAlphaTest: boolean = false;
 
+    /**
+     * Defines the alpha limits in alpha test mode.
+     */
     @editableInPropertyPage("Alpha CutOff", PropertyTypeForEdition.Float, "TRANSPARENCY", { min: 0, max: 1, "notifiers": { "update": true }})
-    public alphaTestCutoff: number = 0.4;
+    public alphaTestCutoff: number = 0.5;
 
-    @editableInPropertyPage("Alpha blending", PropertyTypeForEdition.Boolean, "TRANSPARENCY", { "notifiers": { "update": true }})
+    /**
+     * Specifies that alpha blending should be used
+     */
+    @editableInPropertyPage("Alpha blending", PropertyTypeForEdition.Boolean, "TRANSPARENCY")
     public useAlphaBlending: boolean = false;
 
+    /**
+     * Defines if the alpha value should be determined via the rgb values.
+     * If true the luminance of the pixel might be used to find the corresponding alpha value.
+     */
     @editableInPropertyPage("Get alpha from opacity texture RGB", PropertyTypeForEdition.Boolean, "TRANSPARENCY", { "notifiers": { "update": true }})
     public opacityRGB: boolean = false;
 
+    /**
+     * Specifies that the material will keeps the reflection highlights over a transparent surface (only the most luminous ones).
+     * A car glass is a good exemple of that. When the street lights reflects on it you can not see what is behind.
+     */
     @editableInPropertyPage("Radiance over alpha", PropertyTypeForEdition.Boolean, "RENDERING", { "notifiers": { "update": true }})
     public useRadianceOverAlpha: boolean = true;
 
+    /**
+     * Specifies that the material will keeps the specular highlights over a transparent surface (only the most luminous ones).
+     * A car glass is a good exemple of that. When sun reflects on it you can not see what is behind.
+     */
     @editableInPropertyPage("Specular over alpha", PropertyTypeForEdition.Boolean, "RENDERING", { "notifiers": { "update": true }})
     public useSpecularOverAlpha: boolean = true;
 
+    /**
+     * Enables specular anti aliasing in the PBR shader.
+     * It will both interacts on the Geometry for analytical and IBL lighting.
+     * It also prefilter the roughness map based on the bump values.
+     */
     @editableInPropertyPage("Specular anti-aliasing", PropertyTypeForEdition.Boolean, "RENDERING", { "notifiers": { "update": true }})
     public enableSpecularAntiAliasing: boolean = false;
 
+    /**
+     * Defines if the material uses energy conservation.
+     */
     @editableInPropertyPage("Energy Conservation", PropertyTypeForEdition.Boolean, "ADVANCED", { "notifiers": { "update": true }})
     public useEnergyConservation: boolean = true;
 
+    /**
+     * This parameters will enable/disable radiance occlusion by preventing the radiance to lit
+     * too much the area relying on ambient texture to define their ambient occlusion.
+     */
     @editableInPropertyPage("Radiance occlusion", PropertyTypeForEdition.Boolean, "ADVANCED", { "notifiers": { "update": true }})
     public useRadianceOcclusion: boolean = true;
 
+    /**
+     * This parameters will enable/disable Horizon occlusion to prevent normal maps to look shiny when the normal
+     * makes the reflect vector face the model (under horizon).
+     */
     @editableInPropertyPage("Horizon occlusion", PropertyTypeForEdition.Boolean, "ADVANCED", { "notifiers": { "update": true }})
     public useHorizonOcclusion: boolean = true;
 
-    @editableInPropertyPage("Unlit", PropertyTypeForEdition.Boolean, "ADVANCED", { "notifiers": { "update": true }})
+    /**
+     * If set to true, no lighting calculations will be applied.
+     */
+    @editableInPropertyPage("Unlit", PropertyTypeForEdition.Boolean, "ADVANCED")
     public unlit: boolean = false;
 
+    /**
+     * Defines the material debug mode.
+     * It helps seeing only some components of the material while troubleshooting.
+     */
     @editableInPropertyPage("Debug mode", PropertyTypeForEdition.List, "DEBUG", { "notifiers": { "update": true }, "options": [
         { label: "None", value: 0 },
         // Geometry
@@ -187,9 +246,19 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
     ]})
     public debugMode = 0;
 
+    /**
+     * Specify from where on screen the debug mode should start.
+     * The value goes from -1 (full screen) to 1 (not visible)
+     * It helps with side by side comparison against the final render
+     * This defaults to 0
+     */
     @editableInPropertyPage("Split position", PropertyTypeForEdition.Float, "DEBUG", { min: -1, max: 1, "notifiers": { "update": true }})
     public debugLimit = 0;
 
+    /**
+     * As the default viewing range might not be enough (if the ambient is really small for instance)
+     * You can use the factor to better multiply the final value.
+     */
     @editableInPropertyPage("Output factor", PropertyTypeForEdition.Float, "DEBUG", { min: 0, max: 5, "notifiers": { "update": true }})
     public debugFactor = 1;
 
@@ -245,110 +314,191 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
         return "PBRMetallicRoughnessBlock";
     }
 
+    /**
+     * Gets the world position input component
+     */
     public get worldPosition(): NodeMaterialConnectionPoint {
         return this._inputs[0];
     }
 
+    /**
+     * Gets the world normal input component
+     */
     public get worldNormal(): NodeMaterialConnectionPoint {
         return this._inputs[1];
     }
 
+    /**
+     * Gets the perturbed normal input component
+     */
     public get perturbedNormal(): NodeMaterialConnectionPoint {
         return this._inputs[2];
     }
 
+    /**
+     * Gets the camera position input component
+     */
     public get cameraPosition(): NodeMaterialConnectionPoint {
         return this._inputs[3];
     }
 
+    /**
+     * Gets the base color input component
+     */
     public get baseColor(): NodeMaterialConnectionPoint {
         return this._inputs[4];
     }
 
+    /**
+     * Gets the base texture input component
+     */
     public get baseTexture(): NodeMaterialConnectionPoint {
         return this._inputs[5];
     }
 
+    /**
+     * Gets the opacity texture input component
+     */
     public get opacityTexture(): NodeMaterialConnectionPoint {
         return this._inputs[6];
     }
 
-    public get reflectivityParams(): NodeMaterialConnectionPoint {
+    /**
+     * Gets the ambient color input component
+     */
+    public get ambientColor(): NodeMaterialConnectionPoint {
         return this._inputs[7];
     }
 
-    public get ambientColor(): NodeMaterialConnectionPoint {
+    /**
+     * Gets the reflectivity object parameters
+     */
+    public get reflectivity(): NodeMaterialConnectionPoint {
         return this._inputs[8];
     }
 
-    public get ambientOcclusionParams(): NodeMaterialConnectionPoint {
+    /**
+     * Gets the ambient occlusion object parameters
+     */
+    public get ambientOcclusion(): NodeMaterialConnectionPoint {
         return this._inputs[9];
     }
 
-    public get reflectionParams(): NodeMaterialConnectionPoint {
+    /**
+     * Gets the reflection object parameters
+     */
+    public get reflection(): NodeMaterialConnectionPoint {
         return this._inputs[10];
     }
 
-    public get sheenParams(): NodeMaterialConnectionPoint {
+    /**
+     * Gets the sheen object parameters
+     */
+    public get sheen(): NodeMaterialConnectionPoint {
         return this._inputs[11];
     }
 
-    public get clearcoatParams(): NodeMaterialConnectionPoint {
+    /**
+     * Gets the clear coat object parameters
+     */
+    public get clearcoat(): NodeMaterialConnectionPoint {
         return this._inputs[12];
     }
 
-    public get subSurfaceParams(): NodeMaterialConnectionPoint {
+    /**
+     * Gets the sub surface object parameters
+     */
+    public get subSurface(): NodeMaterialConnectionPoint {
         return this._inputs[13];
     }
 
-    public get anisotropyParams(): NodeMaterialConnectionPoint {
+    /**
+     * Gets the anisotropy object parameters
+     */
+    public get anisotropy(): NodeMaterialConnectionPoint {
         return this._inputs[14];
     }
 
+    /**
+     * Gets the ambient output component
+     */
     public get ambient(): NodeMaterialConnectionPoint {
         return this._outputs[0];
     }
 
+    /**
+     * Gets the diffuse output component
+     */
     public get diffuse(): NodeMaterialConnectionPoint {
         return this._outputs[1];
     }
 
+    /**
+     * Gets the specular output component
+     */
     public get specular(): NodeMaterialConnectionPoint {
         return this._outputs[2];
     }
 
-    public get sheen(): NodeMaterialConnectionPoint {
+    /**
+     * Gets the sheen output component
+     */
+    public get sheenDir(): NodeMaterialConnectionPoint {
         return this._outputs[3];
     }
 
-    public get clearcoat(): NodeMaterialConnectionPoint {
+    /**
+     * Gets the clear coat output component
+     */
+    public get clearcoatDir(): NodeMaterialConnectionPoint {
         return this._outputs[4];
     }
 
+    /**
+     * Gets the indirect diffuse output component
+     */
     public get diffuseIndirect(): NodeMaterialConnectionPoint {
         return this._outputs[5];
     }
 
+    /**
+     * Gets the indirect specular output component
+     */
     public get specularIndirect(): NodeMaterialConnectionPoint {
         return this._outputs[6];
     }
 
+    /**
+     * Gets the indirect sheen output component
+     */
     public get sheenIndirect(): NodeMaterialConnectionPoint {
         return this._outputs[7];
     }
 
+    /**
+     * Gets the indirect clear coat output component
+     */
     public get clearcoatIndirect(): NodeMaterialConnectionPoint {
         return this._outputs[8];
     }
 
+    /**
+     * Gets the refraction output component
+     */
     public get refraction(): NodeMaterialConnectionPoint {
         return this._outputs[9];
     }
 
+    /**
+     * Gets the global lighting output component
+     */
     public get lighting(): NodeMaterialConnectionPoint {
         return this._outputs[10];
     }
 
+    /**
+     * Gets the shadow output component
+     */
     public get shadow(): NodeMaterialConnectionPoint {
         return this._outputs[11];
     }
@@ -366,6 +516,7 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
     }
 
     public prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines) {
+        // General
         defines.setValue("PBR", true);
         defines.setValue("METALLICWORKFLOW", true);
         defines.setValue("DEBUGMODE", this.debugMode);
@@ -373,14 +524,10 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
         defines.setValue("BUMP", this.perturbedNormal.isConnected);
 
         // Albedo & Opacity
-        if (this.baseTexture.isConnected) {
-            defines.setValue("ALBEDO", true);
-        }
-
-        if (this.opacityTexture.isConnected) {
-            defines.setValue("OPACITY", true);
-        }
+        defines.setValue("ALBEDO", this.baseTexture.isConnected);
+        defines.setValue("OPACITY", this.opacityTexture.isConnected);
 
+        // Transparency
         defines.setValue("ALPHABLEND", this.useAlphaBlending);
         defines.setValue("ALPHAFROMALBEDO", this.useAlphaFromAlbedoTexture);
         defines.setValue("ALPHATEST", this.useAlphaTest);
@@ -498,14 +645,14 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
             state.compilationString += `${worldPosVaryingName} = ${worldPos.associatedVariableName};\r\n`;
         }
 
-        const reflectionBlock = this.reflectionParams.isConnected ? this.reflectionParams.connectedPoint?.ownerBlock as ReflectionBlock : null;
+        const reflectionBlock = this.reflection.isConnected ? this.reflection.connectedPoint?.ownerBlock as ReflectionBlock : null;
 
         state.compilationString += reflectionBlock?.handleVertexSide(state) ?? "";
 
-        state._emitUniformFromString("vDebugMode", "vec2", "defined(DUMMY) || DEBUGMODE > 0");
+        state._emitUniformFromString("vDebugMode", "vec2", "defined(IGNORE) || DEBUGMODE > 0");
         state._emitUniformFromString("ambientFromScene", "vec3");
 
-        if (state._emitVaryingFromString("vClipSpacePosition", "vec4", "defined(DUMMY) || DEBUGMODE > 0")) {
+        if (state._emitVaryingFromString("vClipSpacePosition", "vec4", "defined(IGNORE) || DEBUGMODE > 0")) {
             state._injectAtEnd += `#if DEBUGMODE > 0\r\n`;
             state._injectAtEnd += `vClipSpacePosition = gl_Position;\r\n`;
             state._injectAtEnd += `#endif\r\n`;
@@ -561,9 +708,10 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
             this._environmentBRDFTexture = BRDFTextureTools.GetEnvironmentBRDFTexture(this._scene);
         }
 
-        const reflectionBlock = this.reflectionParams.isConnected ? this.reflectionParams.connectedPoint?.ownerBlock as ReflectionBlock : null;
+        const reflectionBlock = this.reflection.isConnected ? this.reflection.connectedPoint?.ownerBlock as ReflectionBlock : null;
 
         if (reflectionBlock) {
+            // Need those variables to be setup when calling _injectVertexCode
             reflectionBlock.worldPositionConnectionPoint = this.worldPosition;
             reflectionBlock.cameraPositionConnectionPoint = this.cameraPosition;
             reflectionBlock.worldNormalConnectionPoint = this.worldNormal;
@@ -588,6 +736,9 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
 
         state._emit2DSampler(this._environmentBrdfSamplerName);
 
+        state.sharedData.hints.needAlphaBlending = state.sharedData.hints.needAlphaBlending || this.useAlphaBlending;
+        state.sharedData.hints.needAlphaTesting = state.sharedData.hints.needAlphaTesting || this.useAlphaTest;
+
         //
         // Includes
         //
@@ -633,7 +784,6 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
         state._emitFunctionFromInclude("pbrBlockAmbientOcclusion", comments);
         state._emitFunctionFromInclude("pbrBlockAlphaFresnel", comments);
         state._emitFunctionFromInclude("pbrBlockAnisotropic", comments);
-        //state._emitFunctionFromInclude("pbrBlockReflection", comments);
         state._emitFunctionFromInclude("pbrBlockSheen", comments);
         state._emitFunctionFromInclude("pbrBlockClearcoat", comments);
         state._emitFunctionFromInclude("pbrBlockSubSurface", comments);
@@ -666,7 +816,7 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
         state.compilationString += state._emitCodeFromInclude("depthPrePass", comments);
 
         // _____________________________ AO  _______________________________
-        const aoBlock = this.ambientOcclusionParams.connectedPoint?.ownerBlock as Nullable<AmbientOcclusionBlock>;
+        const aoBlock = this.ambientOcclusion.connectedPoint?.ownerBlock as Nullable<AmbientOcclusionBlock>;
 
         state.compilationString += AmbientOcclusionBlock.getCode(aoBlock);
 
@@ -765,26 +915,21 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
             ]
         });
 
+        // _____________________________ Output Final Color Composition ________________________
         state.compilationString += state._emitCodeFromInclude("pbrBlockFinalColorComposition", comments, {
             replaceStrings: [
                 { search: /finalEmissive/g, replace: "vec3(0.)" },
             ]
         });
 
+        // _____________________________ Apply image processing ________________________
         state.compilationString += state._emitCodeFromInclude("pbrBlockImageProcessing", comments, {
             replaceStrings: [
                 { search: /visibility/g, replace: "1." },
             ]
         });
 
-        if (this.lighting.hasEndpoints) {
-            state.compilationString += this._declareOutput(this.lighting, state) + ` = finalColor;\r\n`;
-        }
-
-        if (this.shadow.hasEndpoints) {
-            state.compilationString += this._declareOutput(this.shadow, state) + ` = shadow;\r\n`;
-        }
-
+        // _____________________________ Generate debug code ________________________
         state.compilationString += state._emitCodeFromInclude("pbrDebug", comments, {
             replaceStrings: [
                 { search: /vNormalW/g, replace: this.worldNormal.associatedVariableName },

+ 52 - 6
src/Materials/Node/Blocks/PBR/reflectionBlock.ts

@@ -16,6 +16,9 @@ import { Effect } from '../../../effect';
 import { editableInPropertyPage, PropertyTypeForEdition } from "../../nodeMaterialDecorator";
 import { Scene } from '../../../../scene';
 
+/**
+ * Block used to implement the reflection module of the PBR material
+ */
 export class ReflectionBlock extends ReflectionTextureBaseBlock {
 
     private _defineLODReflectionAlpha: string;
@@ -25,16 +28,36 @@ export class ReflectionBlock extends ReflectionTextureBaseBlock {
     private _vReflectionMicrosurfaceInfosName: string;
     private _scene: Scene;
 
+    /**
+     * The three properties below are set by the main PBR block prior to calling methods of this class.
+     * This is to avoid having to add them as inputs here whereas they are already inputs of the main block, so already known.
+     * It's less burden on the user side in the editor part.
+    */
+
+    /** @hidden */
     public worldPositionConnectionPoint: NodeMaterialConnectionPoint;
+    /** @hidden */
     public worldNormalConnectionPoint: NodeMaterialConnectionPoint;
+    /** @hidden */
     public cameraPositionConnectionPoint: NodeMaterialConnectionPoint;
 
+    /**
+     * Defines if the material uses spherical harmonics vs spherical polynomials for the
+     * diffuse part of the IBL.
+     */
     @editableInPropertyPage("Spherical Harmonics", PropertyTypeForEdition.Boolean, "ADVANCED", { "notifiers": { "update": true }})
     public useSphericalHarmonics: boolean = true;
 
+    /**
+     * Force the shader to compute irradiance in the fragment shader in order to take bump in account.
+     */
     @editableInPropertyPage("Force irradiance in fragment", PropertyTypeForEdition.Boolean, "ADVANCED", { "notifiers": { "update": true }})
     public forceIrradianceInFragment: boolean = false;
 
+    /**
+     * Create a new ReflectionBlock
+     * @param name defines the block name
+     */
     public constructor(name: string) {
         super(name);
 
@@ -45,7 +68,8 @@ export class ReflectionBlock extends ReflectionTextureBaseBlock {
         this.registerInput("view", NodeMaterialBlockConnectionPointTypes.Matrix, false, NodeMaterialBlockTargets.Fragment);
         this.registerInput("color", NodeMaterialBlockConnectionPointTypes.Color3, true, NodeMaterialBlockTargets.Fragment);
 
-        this.registerOutput("reflection", NodeMaterialBlockConnectionPointTypes.Object, NodeMaterialBlockTargets.Fragment, new NodeMaterialConnectionPointCustomObject("reflection", this, NodeMaterialConnectionPointDirection.Output, ReflectionBlock, "ReflectionBlock"));
+        this.registerOutput("reflection", NodeMaterialBlockConnectionPointTypes.Object, NodeMaterialBlockTargets.Fragment,
+            new NodeMaterialConnectionPointCustomObject("reflection", this, NodeMaterialConnectionPointDirection.Output, ReflectionBlock, "ReflectionBlock"));
     }
 
     /**
@@ -57,7 +81,7 @@ export class ReflectionBlock extends ReflectionTextureBaseBlock {
     }
 
     /**
-     * Gets the world position input component
+     * Gets the position input component
      */
     public get position(): NodeMaterialConnectionPoint {
         return this._inputs[0];
@@ -98,14 +122,23 @@ export class ReflectionBlock extends ReflectionTextureBaseBlock {
         return this._inputs[2];
     }
 
+    /**
+     * Gets the color input component
+     */
     public get color(): NodeMaterialConnectionPoint {
         return this._inputs[3];
     }
 
+    /**
+     * Gets the reflection object output component
+     */
     public get reflection(): NodeMaterialConnectionPoint {
         return this._outputs[0];
     }
 
+    /**
+     * Returns true if the block has a texture (either its own texture or the environment texture from the scene, if set)
+     */
     public get hasTexture(): boolean {
         return !!this._getTexture();
     }
@@ -201,6 +234,11 @@ export class ReflectionBlock extends ReflectionTextureBaseBlock {
         }
     }
 
+    /**
+     * Gets the code to inject in the vertex shader
+     * @param state current state of the node material building
+     * @returns the shader code
+     */
     public handleVertexSide(state: NodeMaterialBuildState): string {
         let code = super.handleVertexSide(state);
 
@@ -249,6 +287,15 @@ export class ReflectionBlock extends ReflectionTextureBaseBlock {
         return code;
     }
 
+    /**
+     * Gets the main code of the block (fragment side)
+     * @param state current state of the node material building
+     * @param normalVarName name of the existing variable corresponding to the normal
+     * @param finalColorVarName name of the variable that will hold the final color
+     * @param finalIrradianceVector name of the variable that will hold the final irradiance vector
+     * @param finalIrradianceVarName name of the variable that will hold the final irradiance color
+     * @returns the shader code
+     */
     public getCode(state: NodeMaterialBuildState, normalVarName: string, finalColorVarName: string, finalIrradianceVector: string, finalIrradianceVarName: string): string {
         let code = "";
 
@@ -323,9 +370,8 @@ export class ReflectionBlock extends ReflectionTextureBaseBlock {
                 ${finalColorVarName} = ${this._reflectionColorName}${this.color.isConnected ? " * vec4(" + this.color.associatedVariableName + ", 1.)" : ""};
             #else
                 // ***not handled***
-            #endif\r\n`;
+            #endif
 
-        code += `
             vec3 ${finalIrradianceVarName} = vec3(0.);
             #ifdef USESPHERICALFROMREFLECTIONMAP
                 #if defined(USESPHERICALINVERTEX)
@@ -343,12 +389,12 @@ export class ReflectionBlock extends ReflectionTextureBaseBlock {
 
                     ${finalIrradianceVarName} = computeEnvironmentIrradiance(${finalIrradianceVector});
                 #endif
-            #endif\r\n`;
+            #endif
 
-        code += `
             #ifdef SS_TRANSLUCENCY
                 reflectionOut.irradianceVector = irradianceVector;
             #endif
+
             reflectionOut.environmentRadiance = environmentRadiance;
             reflectionOut.environmentIrradiance = environmentIrradiance;
             reflectionOut.reflectionCoords = ${this._reflectionCoordsName};\r\n`;

+ 65 - 31
src/Materials/Node/Blocks/PBR/reflectivityBlock.ts

@@ -10,20 +10,38 @@ import { NodeMaterialConnectionPointCustomObject } from "../../nodeMaterialConne
 import { NodeMaterialConnectionPoint, NodeMaterialConnectionPointDirection } from '../../nodeMaterialBlockConnectionPoint';
 import { Scene } from '../../../../scene';
 
+/**
+ * Block used to implement the reflectivity module of the PBR material
+ */
 export class ReflectivityBlock extends NodeMaterialBlock {
 
+    /**
+     * Specifies if the metallic texture contains the ambient occlusion information in its red channel.
+     */
     @editableInPropertyPage("AO from red channel", PropertyTypeForEdition.Boolean, "METALLIC WORKFLOW", { "notifiers": { "update": true }})
     public useAmbientOcclusionFromMetallicTextureRed: boolean = false;
 
+    /**
+     * Specifies if the metallic texture contains the metallness information in its blue channel.
+     */
     @editableInPropertyPage("Metallness from blue channel", PropertyTypeForEdition.Boolean, "METALLIC WORKFLOW", { "notifiers": { "update": true }})
     public useMetallnessFromMetallicTextureBlue: boolean = true;
 
+    /**
+     * Specifies if the metallic texture contains the roughness information in its alpha channel.
+     */
     @editableInPropertyPage("Roughness from alpha channel", PropertyTypeForEdition.Boolean, "METALLIC WORKFLOW", { "notifiers": { "update": true }})
     public useRoughnessFromMetallicTextureAlpha: boolean = false;
 
+    /**
+     * Specifies if the metallic texture contains the roughness information in its green channel.
+     */
     @editableInPropertyPage("Roughness from green channel", PropertyTypeForEdition.Boolean, "METALLIC WORKFLOW", { "notifiers": { "update": true }})
     public useRoughnessFromMetallicTextureGreen: boolean = true;
 
+    /**
+     * Specifies whether the F0 factor can be fetched from the mettalic texture.
+     */
     @editableInPropertyPage("Metallic F0 from alpha channel", PropertyTypeForEdition.Boolean, "METALLIC WORKFLOW", { "notifiers": { "update": true }})
     public useMetallicF0FactorFromMetallicTexture: boolean = false;
 
@@ -40,7 +58,8 @@ export class ReflectivityBlock extends NodeMaterialBlock {
         this.registerInput("roughness", NodeMaterialBlockConnectionPointTypes.Float, false, NodeMaterialBlockTargets.Fragment);
         this.registerInput("texture", NodeMaterialBlockConnectionPointTypes.Color4, true, NodeMaterialBlockTargets.Fragment);
 
-        this.registerOutput("reflectivity", NodeMaterialBlockConnectionPointTypes.Object, NodeMaterialBlockTargets.Fragment, new NodeMaterialConnectionPointCustomObject("reflectivity", this, NodeMaterialConnectionPointDirection.Output, ReflectivityBlock, "ReflectivityBlock"));
+        this.registerOutput("reflectivity", NodeMaterialBlockConnectionPointTypes.Object, NodeMaterialBlockTargets.Fragment,
+            new NodeMaterialConnectionPointCustomObject("reflectivity", this, NodeMaterialConnectionPointDirection.Output, ReflectivityBlock, "ReflectivityBlock"));
     }
 
     /**
@@ -62,57 +81,72 @@ export class ReflectivityBlock extends NodeMaterialBlock {
         return "ReflectivityBlock";
     }
 
+    /**
+     * Gets the metallic input component
+     */
     public get metallic(): NodeMaterialConnectionPoint {
         return this._inputs[0];
     }
 
+    /**
+     * Gets the roughness input component
+     */
     public get roughness(): NodeMaterialConnectionPoint {
         return this._inputs[1];
     }
 
+    /**
+     * Gets the texture input component
+     */
     public get texture(): NodeMaterialConnectionPoint {
         return this._inputs[2];
     }
 
     /**
-     * Gets the reflectivity output component
+     * Gets the reflectivity object output component
      */
     public get reflectivity(): NodeMaterialConnectionPoint {
         return this._outputs[0];
     }
 
+    /**
+     * Gets the main code of the block (fragment side)
+     * @returns the shader code
+     */
     public getCode(aoIntensityVarName: string): string {
         const metalRoughTexture = this.texture.isConnected ? this.texture.connectedPoint?.associatedVariableName : null;
 
-        let code = `vec3 baseColor = surfaceAlbedo;\r\nreflectivityOutParams reflectivityOut;\r\n`;
-
-        code += `reflectivityBlock(
-            vec4(${this.metallic.associatedVariableName}, ${this.roughness.associatedVariableName}, 0., 0.04),
-        #ifdef METALLICWORKFLOW
-            surfaceAlbedo,
-        #endif
-        #ifdef REFLECTIVITY
-            vec3(0., 0., ${aoIntensityVarName}),
-            ${metalRoughTexture},
-        #endif
-        #if defined(METALLICWORKFLOW) && defined(REFLECTIVITY)  && defined(AOSTOREINMETALMAPRED)
-            aoOut.ambientOcclusionColor,
-        #endif
-        #ifdef MICROSURFACEMAP
-            microSurfaceTexel, <== not handled!
-        #endif
-            reflectivityOut
-        );
-
-        float microSurface = reflectivityOut.microSurface;
-        float roughness = reflectivityOut.roughness;
-
-        #ifdef METALLICWORKFLOW
-            surfaceAlbedo = reflectivityOut.surfaceAlbedo;
-        #endif
-        #if defined(METALLICWORKFLOW) && defined(REFLECTIVITY) && defined(AOSTOREINMETALMAPRED)
-            aoOut.ambientOcclusionColor = reflectivityOut.ambientOcclusionColor;
-        #endif\r\n`;
+        // note: metallic F0 factor = 0.04
+        let code = `vec3 baseColor = surfaceAlbedo;
+            reflectivityOutParams reflectivityOut;
+
+            reflectivityBlock(
+                vec4(${this.metallic.associatedVariableName}, ${this.roughness.associatedVariableName}, 0., 0.04),
+            #ifdef METALLICWORKFLOW
+                surfaceAlbedo,
+            #endif
+            #ifdef REFLECTIVITY
+                vec3(0., 0., ${aoIntensityVarName}),
+                ${metalRoughTexture},
+            #endif
+            #if defined(METALLICWORKFLOW) && defined(REFLECTIVITY)  && defined(AOSTOREINMETALMAPRED)
+                aoOut.ambientOcclusionColor,
+            #endif
+            #ifdef MICROSURFACEMAP
+                microSurfaceTexel, <== not handled!
+            #endif
+                reflectivityOut
+            );
+
+            float microSurface = reflectivityOut.microSurface;
+            float roughness = reflectivityOut.roughness;
+
+            #ifdef METALLICWORKFLOW
+                surfaceAlbedo = reflectivityOut.surfaceAlbedo;
+            #endif
+            #if defined(METALLICWORKFLOW) && defined(REFLECTIVITY) && defined(AOSTOREINMETALMAPRED)
+                aoOut.ambientOcclusionColor = reflectivityOut.ambientOcclusionColor;
+            #endif\r\n`;
 
         return code;
     }