浏览代码

Add aniso texture

sebavan 6 年之前
父节点
当前提交
0e7771979d

+ 4 - 0
inspector/src/components/actionTabs/tabs/propertyGrids/materials/pbrMaterialPropertyGridComponent.tsx

@@ -70,6 +70,8 @@ export class PBRMaterialPropertyGridComponent extends React.Component<IPBRMateri
             { label: "ClearCoat Tangents", value: 9 },
             { label: "ClearCoat Bitangents", value: 10 },
             { label: "Anisotropic Normals", value: 11 },
+            { label: "Anisotropic Tangents", value: 12 },
+            { label: "Anisotropic Bitangents", value: 13 },
             // Maps
             { label: "Albdeo Map", value: 20 },
             { label: "Ambient Map", value: 21 },
@@ -81,6 +83,7 @@ export class PBRMaterialPropertyGridComponent extends React.Component<IPBRMateri
             { label: "ClearCoat Map", value: 27 },
             { label: "ClearCoat Tint Map", value: 28 },
             { label: "Sheen Map", value: 29 },
+            { label: "Anisotropic Map", value: 30 },
             // Env
             { label: "Env Refraction", value: 40 },
             { label: "Env Reflection", value: 41 },
@@ -172,6 +175,7 @@ export class PBRMaterialPropertyGridComponent extends React.Component<IPBRMateri
                         <div>
                             <SliderLineComponent label="Intensity" target={material.anisotropy} propertyName="intensity" minimum={0} maximum={1} step={0.01} onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
                             <Vector2LineComponent label="Direction" target={material.anisotropy} propertyName="direction" onPropertyChangedObservable={this.props.onPropertyChangedObservable} />
+                            <TextureLinkLineComponent label="Texture" texture={material.anisotropy.texture} material={material} onSelectionChangedObservable={this.props.onSelectionChangedObservable} onDebugSelectionChangeObservable={this._onDebugSelectionChangeObservable} />
                         </div>
                     }
                 </LineContainerComponent>

+ 158 - 35
src/Materials/PBR/pbrAnisotropicConfiguration.ts

@@ -1,18 +1,26 @@
-import { SerializationHelper, serialize, expandToProperty, serializeAsVector2 } from "../../Misc/decorators";
+import { SerializationHelper, serialize, expandToProperty, serializeAsVector2, serializeAsTexture } from "../../Misc/decorators";
 import { EffectFallbacks } from "../../Materials/effect";
 import { UniformBuffer } from "../../Materials/uniformBuffer";
 import { AbstractMesh } from "../../Meshes/abstractMesh";
 import { VertexBuffer } from "../../Meshes/buffer";
 import { Vector2 } from "../../Maths/math";
+import { Scene } from "../../scene";
+import { MaterialFlags } from "../../Materials/materialFlags";
+import { MaterialHelper } from "../../Materials/materialHelper";
+import { BaseTexture } from "../../Materials/Textures/baseTexture";
+import { IAnimatable } from "../../Misc";
+import { Nullable } from "../../types";
 
 /**
  * @hidden
  */
 export interface IMaterialAnisotropicDefines {
     ANISOTROPIC: boolean;
+    ANISOTROPIC_TEXTURE: boolean;
+    ANISOTROPIC_TEXTUREDIRECTUV: number;
     MAINUV1: boolean;
 
-    _areMiscDirty: boolean;
+    _areTexturesDirty: boolean;
     _needUVs: boolean;
 }
 
@@ -26,7 +34,7 @@ export class PBRAnisotropicConfiguration {
     /**
      * Defines if the anisotropy is enabled in the material.
      */
-    @expandToProperty("_markAllSubMeshesAsMiscDirty")
+    @expandToProperty("_markAllSubMeshesAsTexturesDirty")
     public isEnabled = false;
 
     /**
@@ -42,77 +50,158 @@ export class PBRAnisotropicConfiguration {
     @serializeAsVector2()
     public direction = new Vector2(1, 0);
 
+    @serializeAsTexture()
+    private _texture: Nullable<BaseTexture> = null;
+    /**
+     * Stores the anisotropy values in a texture.
+     * rg is direction (like normal from -1 to 1)
+     * b is a intensity
+     */
+    @expandToProperty("_markAllSubMeshesAsTexturesDirty")
+    public texture: Nullable<BaseTexture> = null;
+
     /** @hidden */
-    private _internalMarkAllSubMeshesAsMiscDirty: () => void;
+    private _internalMarkAllSubMeshesAsTexturesDirty: () => void;
 
     /** @hidden */
-    public _markAllSubMeshesAsMiscDirty(): void {
-        this._internalMarkAllSubMeshesAsMiscDirty();
+    public _markAllSubMeshesAsTexturesDirty(): void {
+        this._internalMarkAllSubMeshesAsTexturesDirty();
     }
 
     /**
-     * Instantiate a new istance of clear coat configuration.
-     * @param markAllSubMeshesAsMiscDirty Callback to flag the material to dirty
+     * Instantiate a new istance of anisotropy configuration.
+     * @param markAllSubMeshesAsTexturesDirty Callback to flag the material to dirty
      */
-    constructor(markAllSubMeshesAsMiscDirty: () => void) {
-        this._internalMarkAllSubMeshesAsMiscDirty = markAllSubMeshesAsMiscDirty;
+    constructor(markAllSubMeshesAsTexturesDirty: () => void) {
+        this._internalMarkAllSubMeshesAsTexturesDirty = markAllSubMeshesAsTexturesDirty;
+    }
+
+    /**
+     * Specifies that the submesh is ready to be used.
+     * @param defines the list of "defines" to update.
+     * @param scene defines the scene the material belongs to.
+     * @returns - boolean indicating that the submesh is ready or not.
+     */
+    public isReadyForSubMesh(defines: IMaterialAnisotropicDefines, scene: Scene): boolean {
+        if (defines._areTexturesDirty) {
+            if (scene.texturesEnabled) {
+                if (this._texture && MaterialFlags.AnisotropicTextureEnabled) {
+                    if (!this._texture.isReadyOrNotBlocking()) {
+                        return false;
+                    }
+                }
+            }
+        }
+
+        return true;
     }
 
     /**
      * Checks to see if a texture is used in the material.
      * @param defines the list of "defines" to update.
      * @param mesh the mesh we are preparing the defines for.
+     * @param scene defines the scene the material belongs to.
      */
-    public prepareDefines(defines: IMaterialAnisotropicDefines, mesh: AbstractMesh): void {
-        defines.ANISOTROPIC = this._isEnabled;
-        if (this._isEnabled && !mesh.isVerticesDataPresent(VertexBuffer.TangentKind)) {
-            defines._needUVs = true;
-            defines.MAINUV1 = true;
+    public prepareDefines(defines: IMaterialAnisotropicDefines, mesh: AbstractMesh, scene: Scene): void {
+        if (this._isEnabled) {
+            defines.ANISOTROPIC = this._isEnabled;
+            if (this._isEnabled && !mesh.isVerticesDataPresent(VertexBuffer.TangentKind)) {
+                defines._needUVs = true;
+                defines.MAINUV1 = true;
+            }
+
+            if (defines._areTexturesDirty) {
+                if (scene.texturesEnabled) {
+                    if (this._texture && MaterialFlags.AnisotropicTextureEnabled) {
+                        MaterialHelper.PrepareDefinesForMergedUV(this._texture, defines, "ANISOTROPIC_TEXTURE");
+                    } else {
+                        defines.ANISOTROPIC_TEXTURE = false;
+                    }
+                }
+            }
+        }
+        else {
+            defines.ANISOTROPIC = false;
+            defines.ANISOTROPIC_TEXTURE = false;
         }
     }
 
     /**
      * Binds the material data.
      * @param uniformBuffer defines the Uniform buffer to fill in.
+     * @param scene defines the scene the material belongs to.
      * @param isFrozen defines wether the material is frozen or not.
      */
-    public bindForSubMesh(uniformBuffer: UniformBuffer, isFrozen: boolean): void {
+    public bindForSubMesh(uniformBuffer: UniformBuffer, scene: Scene, isFrozen: boolean): void {
         if (!uniformBuffer.useUbo || !isFrozen || !uniformBuffer.isSync) {
-            // Clear Coat
+            if (this._texture && MaterialFlags.AnisotropicTextureEnabled) {
+                uniformBuffer.updateFloat2("vAnisotropyInfos", this._texture.coordinatesIndex, this._texture.level);
+                MaterialHelper.BindTextureMatrix(this._texture, uniformBuffer, "anisotropy");
+            }
+
+            // Anisotropy
             uniformBuffer.updateFloat3("vAnisotropy", this.direction.x, this.direction.y, this.intensity);
         }
+
+        // Textures
+        if (scene.texturesEnabled) {
+            if (this._texture && MaterialFlags.AnisotropicTextureEnabled) {
+                uniformBuffer.setTexture("anisotropySampler", this._texture);
+            }
+        }
     }
 
     /**
-    * Get the current class name of the texture useful for serialization or dynamic coding.
-    * @returns "PBRAnisotropicConfiguration"
-    */
-    public getClassName(): string {
-        return "PBRAnisotropicConfiguration";
+     * Checks to see if a texture is used in the material.
+     * @param texture - Base texture to use.
+     * @returns - Boolean specifying if a texture is used in the material.
+     */
+    public hasTexture(texture: BaseTexture): boolean {
+        if (this._texture === texture) {
+            return true;
+        }
+
+        return false;
     }
 
     /**
-     * Makes a duplicate of the current configuration into another one.
-     * @param anisotropicConfiguration define the config where to copy the info
+     * Returns an array of the actively used textures.
+     * @param activeTextures Array of BaseTextures
      */
-    public copyTo(anisotropicConfiguration: PBRAnisotropicConfiguration): void {
-        SerializationHelper.Clone(() => anisotropicConfiguration, this);
+    public getActiveTextures(activeTextures: BaseTexture[]): void {
+        if (this._texture) {
+            activeTextures.push(this._texture);
+        }
     }
 
     /**
-     * Serializes this clear coat configuration.
-     * @returns - An object with the serialized config.
+     * Returns the animatable textures.
+     * @param animatables Array of animatable textures.
      */
-    public serialize(): any {
-        return SerializationHelper.Serialize(this);
+    public getAnimatables(animatables: IAnimatable[]): void {
+        if (this._texture && this._texture.animations && this._texture.animations.length > 0) {
+            animatables.push(this._texture);
+        }
     }
 
     /**
-     * Parses a Clear Coat Configuration from a serialized object.
-     * @param source - Serialized object.
+     * Disposes the resources of the material.
+     * @param forceDisposeTextures - Forces the disposal of all textures.
      */
-    public parse(source: any): void {
-        SerializationHelper.Parse(() => this, source, null);
+    public dispose(forceDisposeTextures?: boolean): void {
+        if (forceDisposeTextures) {
+            if (this._texture) {
+                this._texture.dispose();
+            }
+        }
+    }
+
+    /**
+    * Get the current class name of the texture useful for serialization or dynamic coding.
+    * @returns "PBRAnisotropicConfiguration"
+    */
+    public getClassName(): string {
+        return "PBRAnisotropicConfiguration";
     }
 
     /**
@@ -134,7 +223,7 @@ export class PBRAnisotropicConfiguration {
      * @param uniforms defines the current uniform list.
      */
     public static AddUniforms(uniforms: string[]): void {
-        uniforms.push("vAnisotropy");
+        uniforms.push("vAnisotropy", "vAnisotropyInfos", "anisotropyMatrix");
     }
 
     /**
@@ -143,5 +232,39 @@ export class PBRAnisotropicConfiguration {
      */
     public static PrepareUniformBuffer(uniformBuffer: UniformBuffer): void {
         uniformBuffer.addUniform("vAnisotropy", 3);
+        uniformBuffer.addUniform("vAnisotropyInfos", 2);
+        uniformBuffer.addUniform("anisotropyMatrix", 16);
+    }
+
+    /**
+     * Add the required samplers to the current list.
+     * @param samplers defines the current sampler list.
+     */
+    public static AddSamplers(samplers: string[]): void {
+        samplers.push("anisotropySampler");
+    }
+
+    /**
+     * Makes a duplicate of the current configuration into another one.
+     * @param anisotropicConfiguration define the config where to copy the info
+     */
+    public copyTo(anisotropicConfiguration: PBRAnisotropicConfiguration): void {
+        SerializationHelper.Clone(() => anisotropicConfiguration, this);
+    }
+
+    /**
+     * Serializes this anisotropy configuration.
+     * @returns - An object with the serialized config.
+     */
+    public serialize(): any {
+        return SerializationHelper.Serialize(this);
+    }
+
+    /**
+     * Parses a anisotropy Configuration from a serialized object.
+     * @param source - Serialized object.
+     */
+    public parse(source: any): void {
+        SerializationHelper.Parse(() => this, source, null);
     }
 }

+ 15 - 5
src/Materials/PBR/pbrBaseMaterial.ts

@@ -197,7 +197,8 @@ class PBRMaterialDefines extends MaterialDefines
     public CLEARCOAT_TINT_TEXTUREDIRECTUV = 0;
 
     public ANISOTROPIC = false;
-    public ANISOTROPIC_DIRECTION = false;
+    public ANISOTROPIC_TEXTURE = false;
+    public ANISOTROPIC_TEXTUREDIRECTUV = 0;
 
     public BRDF_V_HEIGHT_CORRELATED = false;
     public MS_BRDF_ENERGY_CONSERVATION = false;
@@ -710,7 +711,7 @@ export abstract class PBRBaseMaterial extends PushMaterial {
     /**
      * Defines the anisotropic parameters for the material.
      */
-    public readonly anisotropy = new PBRAnisotropicConfiguration(this._markAllSubMeshesAsMiscDirty.bind(this));
+    public readonly anisotropy = new PBRAnisotropicConfiguration(this._markAllSubMeshesAsTexturesDirty.bind(this));
 
     /**
      * Defines the BRDF parameters for the material.
@@ -997,6 +998,10 @@ export abstract class PBRBaseMaterial extends PushMaterial {
             return false;
         }
 
+        if (!this.anisotropy.isReadyForSubMesh(defines, scene)) {
+            return false;
+        }
+
         if (defines._areImageProcessingDirty && this._imageProcessingConfiguration) {
             if (!this._imageProcessingConfiguration.isReady()) {
                 return false;
@@ -1191,6 +1196,7 @@ export abstract class PBRBaseMaterial extends PushMaterial {
         PBRClearCoatConfiguration.AddSamplers(samplers);
 
         PBRAnisotropicConfiguration.AddUniforms(uniforms);
+        PBRAnisotropicConfiguration.AddSamplers(samplers);
 
         PBRSheenConfiguration.AddUniforms(uniforms);
         PBRSheenConfiguration.AddSamplers(samplers);
@@ -1490,7 +1496,7 @@ export abstract class PBRBaseMaterial extends PushMaterial {
 
         // External config
         this.clearCoat.prepareDefines(defines, scene);
-        this.anisotropy.prepareDefines(defines, mesh);
+        this.anisotropy.prepareDefines(defines, mesh, scene);
         this.brdf.prepareDefines(defines);
         this.sheen.prepareDefines(defines, scene);
 
@@ -1835,7 +1841,7 @@ export abstract class PBRBaseMaterial extends PushMaterial {
             }
 
             this.clearCoat.bindForSubMesh(this._uniformBuffer, scene, engine, this._disableBumpMap, this.isFrozen, this._invertNormalMapX, this._invertNormalMapY);
-            this.anisotropy.bindForSubMesh(this._uniformBuffer, this.isFrozen);
+            this.anisotropy.bindForSubMesh(this._uniformBuffer, scene, this.isFrozen);
             this.sheen.bindForSubMesh(this._uniformBuffer, scene, this.isFrozen);
 
             // Clip plane
@@ -1935,6 +1941,7 @@ export abstract class PBRBaseMaterial extends PushMaterial {
 
         this.clearCoat.getAnimatables(results);
         this.sheen.getAnimatables(results);
+        this.anisotropy.getAnimatables(results);
 
         return results;
     }
@@ -2021,6 +2028,7 @@ export abstract class PBRBaseMaterial extends PushMaterial {
 
         this.clearCoat.getActiveTextures(activeTextures);
         this.sheen.getActiveTextures(activeTextures);
+        this.anisotropy.getActiveTextures(activeTextures);
 
         return activeTextures;
     }
@@ -2072,7 +2080,8 @@ export abstract class PBRBaseMaterial extends PushMaterial {
         }
 
         return this.clearCoat.hasTexture(texture) ||
-            this.sheen.hasTexture(texture);
+            this.sheen.hasTexture(texture) ||
+            this.anisotropy.hasTexture(texture);
     }
 
     /**
@@ -2129,6 +2138,7 @@ export abstract class PBRBaseMaterial extends PushMaterial {
 
         this.clearCoat.dispose(forceDisposeTextures);
         this.sheen.dispose(forceDisposeTextures);
+        this.anisotropy.dispose(forceDisposeTextures);
 
         this._renderTargets.dispose();
 

+ 16 - 0
src/Materials/materialFlags.ts

@@ -245,4 +245,20 @@ export class MaterialFlags {
         this._SheenTextureEnabled = value;
         Engine.MarkAllMaterialsAsDirty(Constants.MATERIAL_TextureDirtyFlag);
     }
+
+    private static _AnisotropicTextureEnabled = true;
+    /**
+     * Are anisotropic textures enabled in the application.
+     */
+    public static get AnisotropicTextureEnabled(): boolean {
+        return this._AnisotropicTextureEnabled;
+    }
+    public static set AnisotropicTextureEnabled(value: boolean) {
+        if (this._AnisotropicTextureEnabled === value) {
+            return;
+        }
+
+        this._AnisotropicTextureEnabled = value;
+        Engine.MarkAllMaterialsAsDirty(Constants.MATERIAL_TextureDirtyFlag);
+    }
 }

+ 8 - 0
src/Shaders/ShadersInclude/pbrDebug.fx

@@ -40,6 +40,12 @@
     #elif DEBUGMODE == 11 && defined(ANISOTROPIC)
         gl_FragColor.rgb = anisotropicNormal;
         #define DEBUGMODE_NORMALIZE
+    #elif DEBUGMODE == 12 && defined(ANISOTROPIC)
+        gl_FragColor.rgb = anisotropicTangent;
+        #define DEBUGMODE_NORMALIZE
+    #elif DEBUGMODE == 13 && defined(ANISOTROPIC)
+        gl_FragColor.rgb = anisotropicBitangent;
+        #define DEBUGMODE_NORMALIZE
 // Maps
     #elif DEBUGMODE == 20 && defined(ALBEDO)
         gl_FragColor.rgb = albedoTexture.rgb;
@@ -64,6 +70,8 @@
         gl_FragColor.rgb = clearCoatTintMapData.rgb;
     #elif DEBUGMODE == 29 && defined(SHEEN) && defined(SHEEN_TEXTURE)
         gl_FragColor.rgb = sheenMapData.rgb;
+    #elif DEBUGMODE == 30 && defined(ANISOTROPIC) && defined(ANISOTROPIC_TEXTURE)
+        gl_FragColor.rgb = anisotropyMapData.rgb;
 // Env
     #elif DEBUGMODE == 40 && defined(REFRACTION)
         // Base color.

+ 5 - 0
src/Shaders/ShadersInclude/pbrFragmentDeclaration.fx

@@ -95,6 +95,11 @@ uniform mat4 view;
 // Anisotropy
 #ifdef ANISOTROPIC
     uniform vec3 vAnisotropy;
+
+    #ifdef ANISOTROPIC_TEXTURE
+        uniform vec2 vAnisotropyInfos;
+        uniform mat4 anisotropyMatrix;
+    #endif
 #endif
 
 // Sheen

+ 2 - 0
src/Shaders/ShadersInclude/pbrUboDeclaration.fx

@@ -51,6 +51,8 @@ uniform Material
     uniform mat4 clearCoatTintMatrix;
 
     uniform vec3 vAnisotropy;
+    uniform vec2 vAnisotropyInfos;
+    uniform mat4 anisotropyMatrix;
 
     uniform vec4 vSheenColor;
     uniform vec2 vSheenInfos;

+ 16 - 0
src/Shaders/ShadersInclude/pbrVertexDeclaration.fx

@@ -76,3 +76,19 @@ uniform float pointSize;
         uniform mat4 clearCoatTintMatrix;
     #endif
 #endif
+
+// Anisotropy
+#ifdef ANISOTROPIC
+    #ifdef ANISOTROPIC_TEXTURE
+        uniform vec2 vAnisotropyInfos;
+        uniform mat4 anisotropyMatrix;
+    #endif
+#endif
+
+// Sheen
+#ifdef SHEEN
+    #ifdef SHEEN_TEXTURE
+        uniform vec2 vSheenInfos;
+        uniform mat4 sheenMatrix;
+    #endif
+#endif

+ 20 - 1
src/Shaders/pbr.fragment.fx

@@ -174,6 +174,19 @@ varying vec4 vColor;
     #endif
 #endif
 
+#ifdef ANISOTROPIC
+    #ifdef ANISOTROPIC_TEXTURE
+        #if ANISOTROPIC_TEXTUREDIRECTUV == 1
+            #define vAnisotropyUV vMainUV1
+        #elif ANISOTROPIC_TEXTUREDIRECTUV == 2
+            #define vAnisotropyUV vMainUV2
+        #else
+            varying vec2 vAnisotropyUV;
+        #endif
+        uniform sampler2D anisotropySampler;
+    #endif
+#endif
+
 // Refraction
 #ifdef REFRACTION
     #ifdef REFRACTIONMAP_3D
@@ -504,8 +517,14 @@ void main(void) {
 
     #ifdef ANISOTROPIC
         float anisotropy = vAnisotropy.b;
-
         vec3 anisotropyDirection = vec3(vAnisotropy.xy, 0.);
+
+        #ifdef ANISOTROPIC_TEXTURE
+            vec3 anisotropyMapData = texture2D(anisotropySampler, vAnisotropyUV + uvOffset).rgb * vAnisotropyInfos.y;
+            anisotropy *= anisotropyMapData.b;
+            anisotropyDirection.rg *= anisotropyMapData.rg * 2.0 - 1.0;
+        #endif
+
         mat3 anisoTBN = mat3(normalize(TBN[0]), normalize(TBN[1]), normalize(TBN[2]));
         vec3 anisotropicTangent = normalize(anisoTBN * anisotropyDirection);
         vec3 anisotropicBitangent = normalize(cross(anisoTBN[2], anisotropicTangent));

+ 19 - 0
src/Shaders/pbr.vertex.fx

@@ -84,6 +84,12 @@ varying vec2 vBumpUV;
     #endif
 #endif
 
+#ifdef ANISOTROPIC
+    #if defined(ANISOTROPIC_TEXTURE) && ANISOTROPIC_TEXTUREDIRECTUV == 0 
+        varying vec2 vAnisotropyUV;
+    #endif
+#endif
+
 // Output
 varying vec3 vPositionW;
 #if DEBUGMODE > 0
@@ -324,6 +330,19 @@ void main(void) {
     #endif
 #endif
 
+#ifdef ANISOTROPIC
+    #if defined(ANISOTROPIC_TEXTURE) && ANISOTROPIC_TEXTUREDIRECTUV == 0 
+        if (vAnisotropyInfos.x == 0.)
+        {
+            vAnisotropyUV = vec2(anisotropyMatrix * vec4(uv, 1.0, 0.0));
+        }
+        else
+        {
+            vAnisotropyUV = vec2(anisotropyMatrix * vec4(uv2, 1.0, 0.0));
+        }
+    #endif
+#endif
+
     // TBN
 #include<bumpVertex>