Просмотр исходного кода

refactoring as a scene component

Benjamin Guignabert 5 лет назад
Родитель
Сommit
d65d9c1c5e

+ 1 - 2
localDev/index.html

@@ -12,8 +12,7 @@
     <script src="../dist/preview%20release/recast.js"></script>
     <script src="../dist/preview%20release/libktx.js"></script>
     <script src="../Tools/DevLoader/BabylonLoader.js"></script>
-    <script type="text/javascript" src="https://spectorcdn.babylonjs.com/spector.bundle.js"></script>
-    
+
     <style>
         html,
         body {

+ 7 - 9
src/Engines/Extensions/engine.renderTargetCube.ts

@@ -48,19 +48,13 @@ ThinEngine.prototype.createRenderTargetCubeTexture = function(size: number, opti
         Logger.Warn("Float textures are not supported. Cube render target forced to TEXTURETYPE_UNESIGNED_BYTE type");
     }
 
-    for (var face = 0; face < 6; face++) {
-        gl.texImage2D((gl.TEXTURE_CUBE_MAP_POSITIVE_X + face), 0, this._getRGBABufferInternalSizedFormat(fullOptions.type, fullOptions.format), size, size, 0, this._getInternalFormat(fullOptions.format), this._getWebGLTextureType(fullOptions.type), null);
-    }
-
     gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, filters.mag);
     gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, filters.min);
     gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
     gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
-    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE);
-    
-    // MipMaps
-    if (fullOptions.generateMipMaps) {
-        gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
+
+    for (var face = 0; face < 6; face++) {
+        gl.texImage2D((gl.TEXTURE_CUBE_MAP_POSITIVE_X + face), 0, this._getRGBABufferInternalSizedFormat(fullOptions.type, fullOptions.format), size, size, 0, this._getInternalFormat(fullOptions.format), this._getWebGLTextureType(fullOptions.type), null);
     }
 
     // Create the framebuffer
@@ -69,6 +63,10 @@ ThinEngine.prototype.createRenderTargetCubeTexture = function(size: number, opti
 
     texture._depthStencilBuffer = this._setupFramebufferDepthAttachments(fullOptions.generateStencilBuffer, fullOptions.generateDepthBuffer, size, size);
 
+    // MipMaps
+    if (fullOptions.generateMipMaps) {
+        gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
+    }
 
     // Unbind
     this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, null);

+ 10 - 10
src/Materials/PBR/pbrBaseMaterial.ts

@@ -35,9 +35,10 @@ import { Constants } from "../../Engines/constants";
 import { IAnimatable } from '../../Animations/animatable.interface';
 
 import "../../Materials/Textures/baseTexture.polynomial";
-import "../../Materials/Textures/baseTexture.prefiltering";
 import "../../Shaders/pbr.fragment";
 import "../../Shaders/pbr.vertex";
+
+import { EnvironmentRealtimeFiltering } from "./pbrRealtimeFiltering";
 import { EffectFallbacks } from '../effectFallbacks';
 
 const onCreatedEffectParameters = { effect: null as unknown as Effect, subMesh: null as unknown as Nullable<SubMesh> };
@@ -751,6 +752,8 @@ export abstract class PBRBaseMaterial extends PushMaterial {
      */
     public readonly subSurface = new PBRSubSurfaceConfiguration(this._markAllSubMeshesAsTexturesDirty.bind(this));
 
+    public realtimeFilter = new EnvironmentRealtimeFiltering(this);
+
     protected _rebuildInParallel = false;
 
     /**
@@ -798,8 +801,6 @@ export abstract class PBRBaseMaterial extends PushMaterial {
         return "PBRBaseMaterial";
     }
 
-    public debugRealtimeSampling = false;
-
     /**
      * Enabled the use of logarithmic depth buffers, which is good for wide depth buffers.
      */
@@ -1284,8 +1285,8 @@ export abstract class PBRBaseMaterial extends PushMaterial {
                     defines.LODINREFLECTIONALPHA = reflectionTexture.lodLevelInAlpha;
                     defines.LINEARSPECULARREFLECTION = reflectionTexture.linearSpecularLOD;
 
-                    if (reflectionTexture.realTimeFiltering) {
-                        defines.NUM_SAMPLES = reflectionTexture.numSamples;
+                    if (this.realtimeFilter.enabled) {
+                        defines.NUM_SAMPLES = this.realtimeFilter.numSamples;
                         defines.DEBUG_REALTIME_SAMPLING = true;
                     }
                     
@@ -1695,11 +1696,10 @@ export abstract class PBRBaseMaterial extends PushMaterial {
                             ubo.updateVector3("vReflectionSize", cubeTexture.boundingBoxSize);
                         }
 
-                        if (reflectionTexture.realTimeFiltering) {
-                            // TODO move this into pbrbasematerial
-                            reflectionTexture.generateFilterSamples(this._roughness!);           
-                            effect.setArray3("sampleDirections", reflectionTexture._sampleDirections);
-                            effect.setArray("weights", reflectionTexture._sampleWeights);
+                        if (this.realtimeFilter.enabled) {
+                            this.realtimeFilter.generateFilterSamples(this._roughness!);           
+                            effect.setArray3("sampleDirections", this.realtimeFilter.sampleDirections);
+                            effect.setArray("weights", this.realtimeFilter.sampleWeights);
                         }
 
                         if (!defines.USEIRRADIANCEMAP) {

+ 69 - 0
src/Materials/PBR/pbrRealtimeFiltering.ts

@@ -0,0 +1,69 @@
+import { PBRBaseMaterial } from "./pbrBaseMaterial";
+import { HDRFiltering } from "../Textures/Filtering/hdrFiltering";
+import { Constants } from "../../Engines/constants";
+import { Vector3 } from "../../Maths/math";
+
+/**
+ * Allows for realtime filtering of reflection texture
+ * Only turn this on for material having dynamic HDR textures (real-time probes)
+ * and keep the sample count very low.
+ * Baking with HDRFiltering.ts is a way better solution performance-wise
+ */
+export class EnvironmentRealtimeFiltering {
+        private _material: PBRBaseMaterial;
+        private _cachedRoughness: number = 0;
+
+        constructor(material: PBRBaseMaterial) {
+        	this._material = material;
+        }
+        private _enabled: boolean = false;
+        /**
+         * Enables realtime filtering on the material.
+         */
+        public get enabled() {
+        	return this._enabled;
+        }
+        public set enabled(b: boolean) {
+        	this._enabled = b;
+        	this._material.markAsDirty(Constants.MATERIAL_TextureDirtyFlag);
+        }
+
+        private _numSamples: number = 16;
+        /**
+         * Number of samples used to evaluate BRDF on the texture.
+         */
+        public get numSamples() {
+        	return this._numSamples;
+        }
+        public set numSamples(n: number) {
+        	this._numSamples = n;
+        	this._material.markAsDirty(Constants.MATERIAL_TextureDirtyFlag);
+
+        	if (this.sampleDirections) {
+        		this.sampleDirections.length = 0;
+        	}
+        }
+
+        /**
+         * Sample directions around a z-orientated normal
+         */
+        public sampleDirections: number[];
+        public sampleDirectionV3: Vector3[]; // debug, remove
+        /**
+         * Sample weights of the probability density function
+         */
+        public sampleWeights: number[];
+
+        /**
+         * Generates the samples for a roughness value.
+         */
+        public generateFilterSamples(roughness: number) {
+        	if (this.enabled && (!this.sampleDirections || !this.sampleDirections.length || roughness != this._cachedRoughness)) {
+				const sampleDirections = HDRFiltering.generateSamples(this._numSamples, roughness);
+				this.sampleDirectionV3 = sampleDirections;
+				this.sampleWeights = HDRFiltering.generateWeights(sampleDirections, roughness);
+				this.sampleDirections = HDRFiltering.flatten(sampleDirections);
+        		this._cachedRoughness = roughness;
+        	}
+		}
+}

+ 32 - 30
src/Materials/Textures/Filtering/hdrFiltering.ts

@@ -1,4 +1,5 @@
 import { Vector3, Color4 } from "../../../Maths/math";
+import { Nullable } from "../../../types";
 import { InternalTexture } from "../internalTexture"
 import { RenderTargetTexture } from "../renderTargetTexture"
 import { HDRCubeTexture } from "../hdrCubeTexture"
@@ -21,7 +22,7 @@ export class HDRFiltering {
 	private _engine: Engine;
 	private _effect: Effect;
 
-	private _numSamples: number = 256;
+	private _numSamples: number = 128;
 
 	constructor(scene: Scene) {
 		// pass
@@ -84,8 +85,8 @@ export class HDRFiltering {
 	        const a2 = alphaG * alphaG;
 	        // NdotH = samples[i].z
 	        const d = samples[i].z * samples[i].z * (a2 - 1) + 1;
-	        // result.push(a2  / (Math.PI * d * d)); // TODO is it wrong in IBL baker ?
-	        result.push(a2  / (d * d));
+	        result.push(a2  / (Math.PI * d * d));
+	        // result.push(a2  / (d * d));
 	    }
 
 	    return result;
@@ -100,12 +101,15 @@ export class HDRFiltering {
 	}
 
 	// Todo merge hdrCubeTexture with CubeTexture
-	public prefilter(texture: CubeTexture | HDRCubeTexture) : Promise<RenderTargetTexture | null> {
+	public prefilter(texture: CubeTexture | HDRCubeTexture, onFinished?: () => void) {
 		return new Promise((resolve) => {
 			const callback = () => {
 				if (this.isReady(texture)) {
-					resolve(this._prefilter(texture));
-					console.log("unregister");
+					this._prefilter(texture);
+					resolve();
+					if (onFinished) {
+						onFinished();
+					}
 					this._scene.unregisterAfterRender(callback);
 				}
 			};
@@ -114,38 +118,36 @@ export class HDRFiltering {
 		})
 	}
 
-	private _prefilter(texture: CubeTexture | HDRCubeTexture) : RenderTargetTexture | null {
+	private _prefilter(texture: CubeTexture | HDRCubeTexture) : CubeTexture | HDRCubeTexture {
 		// const nbRoughnessStops = 2;
 		const maxLodLevel = Math.round(Math.log(texture.getSize().width) / Math.log(2));
 		const samples = this._numSamples;
-		console.log(this._numSamples, maxLodLevel);
-		const outputTexture = new RenderTargetTexture("temp", texture.getSize(), this._scene, true, true, undefined, true, undefined, false);
-		outputTexture.gammaSpace = false;
+		const tempTexture = new RenderTargetTexture("temp", texture.getSize(), this._scene, true, true, undefined, true, undefined, false);
 
 		for (let i = 0; i < maxLodLevel + 1; i++) {
 			const roughness = i / maxLodLevel;
 			const kernel = HDRFiltering.generateSamples(samples, roughness);
 			const weights = HDRFiltering.generateWeights(kernel, roughness);
 
-			this.filter(texture, outputTexture, kernel, weights, i);
+			this.filter(texture, tempTexture, kernel, weights, i);
 		}
 
-		return outputTexture;
+		texture._texture!._webGLTexture = tempTexture._texture!._webGLTexture;
+		return texture;
 	}
 
-	public filter(texture: CubeTexture | HDRCubeTexture, outputTexture: RenderTargetTexture, kernel: Vector3[], weights: number[], lodLevel: number = 0) : RenderTargetTexture | null {
+	public filter(texture: CubeTexture | HDRCubeTexture, outputTexture: RenderTargetTexture, kernel: Vector3[], weights: number[], lodLevel: number = 0) : Nullable<RenderTargetTexture> {
 		if (!texture.isReady()) {
 			return null;
 		}
 
-		// Direction are flipped because of LH vs RH
 		const directions = [
-			[new Vector3(0, 0, 1), new Vector3(0, 1, 0), new Vector3(-1, 0, 0)], // PositiveX
-			[new Vector3(0, 0, -1), new Vector3(0, 1, 0), new Vector3(1, 0, 0)], // NegativeX
-			[new Vector3(-1, 0, 0), new Vector3(0, 0, -1), new Vector3(0, -1, 0)], // PositiveY
-			[new Vector3(-1, 0, 0), new Vector3(0, 0, 1), new Vector3(0, 1, 0)], // NegativeY
-			[new Vector3(-1, 0, 0), new Vector3(0, 1, 0), new Vector3(0, 0, -1)], // PositiveZ
-			[new Vector3(1, 0, 0), new Vector3(0, 1, 0), new Vector3(0, 0, 1)], // NegativeZ
+			[new Vector3(0, 0, -1), new Vector3(0, -1, 0), new Vector3(1, 0, 0)], // PositiveX
+			[new Vector3(0, 0, 1), new Vector3(0, -1, 0), new Vector3(-1, 0, 0)], // NegativeX
+			[new Vector3(1, 0, 0), new Vector3(0, 0, 1), new Vector3(0, 1, 0)], // PositiveY
+			[new Vector3(1, 0, 0), new Vector3(0, 0, -1), new Vector3(0, -1, 0)], // NegativeY
+			[new Vector3(1, 0, 0), new Vector3(0, -1, 0), new Vector3(0, 0, 1)], // PositiveZ
+			[new Vector3(-1, 0, 0), new Vector3(0, -1, 0), new Vector3(0, 0, -1)], // NegativeZ
 		];
 
 		for (let i = 0; i < 6 ; i++) {
@@ -221,26 +223,20 @@ export class HDRFiltering {
      * @param lodLevel defines which lod of the texture to render to
      */
     public directRender(targetTexture: InternalTexture, faceIndex = 0, lodLevel = 0): void {
-    	console.log("Rendering lod level " + lodLevel)
         var engine = this._engine;
-        var gl = engine._gl;
         engine._currentRenderTarget = null;
         engine.bindFramebuffer(targetTexture, faceIndex, undefined, undefined, true, lodLevel);
-        const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
-
-        console.assert(status === gl.FRAMEBUFFER_COMPLETE, 'incomplete!');
-
         engine.clear(new Color4(0.0, 0.0, 0.0, 0.0), true, true);
         // VBOs
         this._prepareBuffers();
         engine.bindBuffers(this._vertexBuffers, this._indexBuffer, this._effect);
         engine.drawElementsType(Material.TriangleFillMode, 0, 6);
 
-        // engine.restoreDefaultFramebuffer();
+        engine.restoreDefaultFramebuffer();
         // Restore depth buffer
-	    // engine.setState(true);
-     //    engine.setDepthBuffer(true);
-     //    engine.setDepthWrite(true);
+	    engine.setState(true);
+        engine.setDepthBuffer(true);
+        engine.setDepthWrite(true);
     }
 
     private _indexBuffer: DataBuffer;
@@ -280,4 +276,10 @@ export class HDRFiltering {
 
         this._indexBuffer = this._scene.getEngine().createIndexBuffer(indices);
     }
+
+    public dispose() {
+    	this._vertexBuffers[VertexBuffer.PositionKind].dispose();
+    	this._effect.dispose();
+    }
+
 }

+ 0 - 72
src/Materials/Textures/baseTexture.prefiltering.ts

@@ -1,72 +0,0 @@
-import { BaseTexture } from "./baseTexture";
-import { HDRFiltering } from "./Filtering/hdrFiltering";
-import { Constants } from "../../Engines/constants";
-import { Vector3 } from "../../Maths/math";
-
-declare module "./baseTexture" {
-    export interface BaseTexture {
-        /**
-         * Only turn this on for dynamic HDR textures (real-time probes)
-         */
-        realTimeFiltering: boolean;
-        _realTimeFiltering: boolean;
-        numSamples: number;
-        _numSamples: number;
-        _sampleDirections: number[];
-        _sampleDirectionV3: Vector3[]; // debug, remove
-        _sampleWeights: number[];
-        generateFilterSamples(roughness: number) : void;
-    }
-}
-
-BaseTexture.prototype._realTimeFiltering = false;
-BaseTexture.prototype._numSamples = 16;
-
-Object.defineProperty(BaseTexture.prototype, "numSamples", {
-    get: function(this: BaseTexture) {
-    	return this._numSamples;
-    },
-    set: function(this: BaseTexture, value: number) {
-    	let scene = this.getScene();
-    	this._numSamples = value;
-    	if (!scene) {
-    		return;
-    	}
-    	scene.markAllMaterialsAsDirty(Constants.MATERIAL_TextureDirtyFlag, (mat) => {
-    	    return mat.hasTexture(this);
-    	});
-
-    },
-    enumerable: true,
-    configurable: true
-});
-
-Object.defineProperty(BaseTexture.prototype, "realTimeFiltering", {
-    get: function(this: BaseTexture) {
-    	return this._realTimeFiltering;
-    },
-    set: function(this: BaseTexture, value: boolean) {
-    	let scene = this.getScene();
-    	this._realTimeFiltering = value;
-    	if (!scene) {
-    		return;
-    	}
-    	scene.markAllMaterialsAsDirty(Constants.MATERIAL_TextureDirtyFlag, (mat) => {
-    	    return mat.hasTexture(this);
-    	});
-
-    },
-    enumerable: true,
-    configurable: true
-});
-
-BaseTexture.prototype.generateFilterSamples = function(roughness) {
-	const sampleDirections = HDRFiltering.generateSamples(this._numSamples, roughness);
-	this._sampleDirectionV3 = sampleDirections;
-	this._sampleWeights = HDRFiltering.generateWeights(sampleDirections, roughness);
-	this._sampleDirections = [];
-
-	for (let i = 0; i < sampleDirections.length; i++) {
-		this._sampleDirections.push(sampleDirections[i].x, sampleDirections[i].y, sampleDirections[i].z);
-	}
-}

+ 12 - 2
src/Materials/Textures/hdrCubeTexture.ts

@@ -32,6 +32,7 @@ export class HDRCubeTexture extends BaseTexture {
 
     private _generateHarmonics = true;
     private _noMipmap: boolean;
+    private _prefilterOnLoad: boolean;
     private _textureMatrix: Matrix;
     private _size: number;
     private _onLoad: Nullable<() => void> = null;
@@ -113,9 +114,9 @@ export class HDRCubeTexture extends BaseTexture {
      * @param noMipmap Forces to not generate the mipmap if true
      * @param generateHarmonics Specifies whether you want to extract the polynomial harmonics during the generation process
      * @param gammaSpace Specifies if the texture will be use in gamma or linear space (the PBR material requires those texture in linear space, but the standard material would require them in Gamma space)
-     * @param reserved Reserved flag for internal use.
+     * @param prefilterOnLoad Prefilters HDR texture to allow use of this texture as a PBR reflection texture.
      */
-    constructor(url: string, scene: Scene, size: number, noMipmap = false, generateHarmonics = true, gammaSpace = false, reserved = false, onLoad: Nullable<() => void> = null, onError: Nullable<(message?: string, exception?: any) => void> = null) {
+    constructor(url: string, scene: Scene, size: number, noMipmap = false, generateHarmonics = true, gammaSpace = false, prefilterOnLoad = true, onLoad: Nullable<() => void> = null, onError: Nullable<(message?: string, exception?: any) => void> = null) {
         super(scene);
 
         if (!url) {
@@ -127,6 +128,7 @@ export class HDRCubeTexture extends BaseTexture {
         this.hasAlpha = false;
         this.isCube = true;
         this._textureMatrix = Matrix.Identity();
+        this._prefilterOnLoad = prefilterOnLoad;
         this._onLoad = onLoad;
         this._onError = onError;
         this.gammaSpace = gammaSpace;
@@ -238,11 +240,19 @@ export class HDRCubeTexture extends BaseTexture {
                     results.push(dataFace);
                 }
             }
+
             return results;
         };
 
         let scene = this.getScene();
+
+
         if (scene) {
+            if (this._prefilterOnLoad) {
+                const previousOnLoad = this._onLoad;
+                this._onLoad = () => scene!.hdrFiltering.prefilter(this, previousOnLoad || undefined);
+            }
+
             this._texture = scene.getEngine().createRawCubeTextureFromUrl(this.url, scene, this._size,
                 Constants.TEXTUREFORMAT_RGB,
                 scene.getEngine().getCaps().textureFloat ? Constants.TEXTURETYPE_FLOAT : Constants.TEXTURETYPE_UNSIGNED_INT,

+ 79 - 0
src/Materials/Textures/hdrFilteringSceneComponent.ts

@@ -0,0 +1,79 @@
+import { Scene } from "../../scene";
+import { HDRFiltering } from "./Filtering/hdrFiltering";
+import { SceneComponentConstants, ISceneComponent } from "../../sceneComponent";
+
+declare module "../../scene" {
+    export interface Scene {
+        /**
+         * TODO Gets or sets the simplification queue attached to the scene
+         * @see http://doc.babylonjs.com/how_to/in-browser_mesh_simplification
+         */
+        hdrFiltering: HDRFiltering;
+        /** @hidden (Backing field) */
+        _hdrFiltering: HDRFiltering;
+    }
+}
+Object.defineProperty(Scene.prototype, "hdrFiltering", {
+    get: function(this: Scene) {
+        if (!this._hdrFiltering) {
+            this._hdrFiltering = new HDRFiltering(this);
+            let component = this._getComponent(SceneComponentConstants.NAME_HDRFILTERING) as HDRFilteringSceneComponent;
+            if (!component) {
+                component = new HDRFilteringSceneComponent(this);
+                this._addComponent(component);
+            }
+        }
+        return this._hdrFiltering;
+    },
+    set: function(this: Scene, value: HDRFiltering) {
+        this._hdrFiltering = value;
+    },
+    enumerable: true,
+    configurable: true
+});
+
+/**
+ * Defines the simplification queue scene component responsible to help scheduling the various simplification task
+ * created in a scene
+ */
+export class HDRFilteringSceneComponent implements ISceneComponent {
+    /**
+     * The component name helpfull to identify the component in the list of scene components.
+     */
+    public readonly name = SceneComponentConstants.NAME_HDRFILTERING;
+
+    /**
+     * The scene the component belongs to.
+     */
+    public scene: Scene;
+
+    /**
+     * Creates a new instance of the component for the given scene
+     * @param scene Defines the scene to register the component in
+     */
+    constructor(scene: Scene) {
+        this.scene = scene;
+    }
+
+    /**
+     * Registers the component in a given scene
+     */
+    public register(): void {
+        // Nothing to do for this component
+    }
+
+    /**
+     * Rebuilds the elements related to this component in case of
+     * context lost for instance.
+     */
+    public rebuild(): void {
+        // Nothing to do for this component
+    }
+
+    /**
+     * Disposes the component and the associated ressources
+     */
+    public dispose(): void {
+        this.scene.hdrFiltering.dispose();
+    }
+}

+ 1 - 2
src/Materials/Textures/index.ts

@@ -1,6 +1,5 @@
 export * from "./baseTexture";
 export * from "./baseTexture.polynomial";
-export * from "./baseTexture.prefiltering";
 export * from "./colorGradingTexture";
 export * from "./cubeTexture";
 export * from "./dynamicTexture";
@@ -22,4 +21,4 @@ export * from "./texture";
 export * from "./videoTexture";
 export * from "./htmlElementTexture";
 export * from "./Packer/index";
-export * from "./Filtering/hdrFiltering";
+export * from "./hdrFilteringSceneComponent";

+ 2 - 2
src/Shaders/ShadersInclude/pbrFragmentSamplersDeclaration.fx

@@ -187,7 +187,7 @@
     uniform float weights[NUM_SAMPLES];
     vec4 sampleUnfiltered(samplerCube sampler, vec3 direction, float lod) {
         // Rotation by PI around y is necessary for consistency with IBLBaker
-        vec3 n = vec3(-direction.x, direction.y, -direction.z);
+        vec3 n = vec3(direction.x, direction.y, direction.z);
         vec3 tangent = abs(n.z) < 0.999 ? vec3(0., 0., 1.) : vec3(1., 0., 0.);
         tangent = normalize(cross(tangent, n));
         vec3 bitangent = cross(n, tangent);
@@ -205,7 +205,7 @@
             NoH = clamp(dot(h, n), 0.0, 1.0);
             NoL = clamp(dot(l, n), 0.0, 1.0);
             if (NoL > 0.) {
-                float solidAngleTexel = 4. / (6. * 128. * 128.);
+                float solidAngleTexel = 4.0 * 3.14159 / (6. * 128. * 128.);
                 float solidAngleSample = 4.0 / (float(NUM_SAMPLES) * weights[i]);
                 float lod = 0.5 * log2(solidAngleSample/solidAngleTexel);
                 // gamma correction needed ?

+ 1 - 3
src/Shaders/hdrFiltering.fragment.fx

@@ -6,8 +6,6 @@ uniform float weights[NUM_SAMPLES];
 varying vec3 direction;
 
 void main() {
-    // Rotation by PI around y is necessary for consistency with IBLBaker
-    // vec3 n = vec3(-direction.x, direction.y, -direction.z);
     vec3 n = normalize(direction);
     vec3 tangent = abs(n.z) < 0.999 ? vec3(0., 0., 1.) : vec3(1., 0., 0.);
     tangent = normalize(cross(tangent, n));
@@ -27,7 +25,7 @@ void main() {
         NoL = clamp(dot(l, n), 0.0, 1.0);
         if (NoL > 0.) {
             float solidAngleTexel = 4. * 3.14159 / (6. * cubeWidth * cubeWidth);
-            float solidAngleSample = 1.5 * 4.0 / (float(NUM_SAMPLES) * weights[i]); // Multiplying by 1.5 gives better results
+            float solidAngleSample = 1.5 * 4.0 / (float(NUM_SAMPLES) * weights[i]);
             float lod = 0.5 * log2(solidAngleSample / solidAngleTexel);
             // gamma correction needed ?
             color += textureCubeLodEXT(inputTexture, l, lod).xyz * NoL;

+ 1 - 0
src/sceneComponent.ts

@@ -23,6 +23,7 @@ export class SceneComponentConstants {
     public static readonly NAME_PARTICLESYSTEM = "ParticleSystem";
     public static readonly NAME_GAMEPAD = "Gamepad";
     public static readonly NAME_SIMPLIFICATIONQUEUE = "SimplificationQueue";
+    public static readonly NAME_HDRFILTERING = "HDRFiltering";
     public static readonly NAME_GEOMETRYBUFFERRENDERER = "GeometryBufferRenderer";
     public static readonly NAME_DEPTHRENDERER = "DepthRenderer";
     public static readonly NAME_POSTPROCESSRENDERPIPELINEMANAGER = "PostProcessRenderPipelineManager";