Jump to content

Bug on bump material under some lightening conditions


Recommended Posts

Hi everyone,


On some complex materials (bump+diff+spec), at certain viewing angles, there are rendering bugs on textures.

It looks like when viewing at some angles, a shift occurs between the bump map and the diffuse map.


Check this PG :



Look at the object's face facing camera, it's kind of "sharpenly blurred", this is not the correct aspect.

Then click on the object, it will rotate upside down, and now the same face previously bad rendered is correctly rendered.

Then move a bit the camera around this face and you'll see a kind of "moiré" (you'll need a good screen to see it) resulting of the interaction between lights and bump map, where it's sometimes ok and sometimes not. When you manage to see this "moiré", you can stop moving camera, and notice that this comes from the fact that there is one sharp "line" followed by a blurred "line", then a sharp one, etc...


You can then look all around the object, turned-over or not, to see that at some angles everything is ok, and at other angles their are problems.

You can also change the specular values (color and power) to change the strongness of the bug and the "moiré" effect.


I notice this bug for the first time when trying the first BJS implementation of SSAO. Back to that time I thought it was related to SSAO because when deactivating SSAO the bug disappeared, but now the bug is always occuring even with no SSAO activation at all.


I'll try with a previous 2.0-beta to check if this was or not an already existing bug before SSAO implentation.

Link to comment
Share on other sites

Urgg, that was a deep quest, BUT here is some (I hope) usefull piece of info :


commit 488cbb630f24bddc1ae31b547fb13225c30d8882 (06/12/2014), babylon.2.0-alpha.js : the bug does not occur !! (but there is an awful lightening problem, a kind of specular light ray going through the scene, and the turned-over object is incorrectly lighted -too dark-)


next commit d6557f0bdaab3813ff3e7e367ced755c718b44fa (09/12/2014), babylon.2.0-alpha.js : the bug appears for the first time (but the other lightening problem is solved)

Link to comment
Share on other sites

Here are the diffs (hope this dump will be helpfull, wouldn't it have been easier for you to check that directly in your versionning system inside VisualStudio ?) :


  • babylon.engine.ts
diff --git a/Babylon/babylon.engine.ts b/Babylon/babylon.engine.tsindex 4ecb501..52ffb20 100644--- a/Babylon/babylon.engine.ts+++ b/Babylon/babylon.engine.ts@@ -429,6 +429,7 @@         // States         private _depthCullingState = new _DepthCullingState();         private _alphaState = new _AlphaState();+        private _alphaMode = Engine.ALPHA_DISABLE;          // Cache         private _loadedTexturesCache = new Array<WebGLTexture>();@@ -551,6 +552,8 @@             document.addEventListener("webkitpointerlockchange", this._onPointerLockChange, false);              this._audioEngine = new BABYLON.AudioEngine();++            Tools.Log("Babylon.js engine (v" + Engine.Version + ") launched");         }          public getAudioEngine(): AudioEngine {@@ -755,7 +758,7 @@         }          public flushFramebuffer(): void {-            this._gl.flush();+         //   this._gl.flush();         }          public restoreDefaultFramebuffer(): void {@@ -1203,7 +1206,6 @@         }          public setAlphaMode(mode: number): void {-             switch (mode) {                 case BABYLON.Engine.ALPHA_DISABLE:                     this.setDepthWrite(true);@@ -1220,6 +1222,12 @@                     this._alphaState.alphaBlend = true;                     break;             }++            this._alphaMode = mode;+        }++        public getAlphaMode(): number {+            return this._alphaMode;         }          public setAlphaTesting(enable: boolean): void {
  • babylon.standardMaterial.ts
diff --git a/Babylon/Materials/babylon.standardMaterial.ts b/Babylon/Materials/babylon.standardMaterial.tsindex 967e263..cc67d9c 100644--- a/Babylon/Materials/babylon.standardMaterial.ts+++ b/Babylon/Materials/babylon.standardMaterial.ts@@ -486,7 +486,7 @@             if (this.bumpTexture && scene.getEngine().getCaps().standardDerivatives && BABYLON.StandardMaterial.BumpTextureEnabled) {                 this._effect.setTexture("bumpSampler", this.bumpTexture); -                this._effect.setFloat2("vBumpInfos", this.bumpTexture.coordinatesIndex, this.bumpTexture.level);+                this._effect.setFloat2("vBumpInfos", this.bumpTexture.coordinatesIndex, 1.0 / this.bumpTexture.level);                 this._effect.setMatrix("bumpMatrix", this.bumpTexture.getTextureMatrix());             } 
  • babylon.standardProceduralTexture.ts
diff --git a/Babylon/Materials/textures/Procedurals/babylon.standardProceduralTexture.ts b/Babylon/Materials/textures/Procedurals/babylon.standardProceduralTexture.tsindex f5a7391..cb8ed60 100644--- a/Babylon/Materials/textures/Procedurals/babylon.standardProceduralTexture.ts+++ b/Babylon/Materials/textures/Procedurals/babylon.standardProceduralTexture.ts@@ -40,6 +40,7 @@         private _alpha: number = 0.0;         private _autoGenerateTime: boolean = true;         private _fireColors: BABYLON.Color3[];+        private _alphaThreshold: number = 0.5;          constructor(name: string, size: number, scene: Scene, fallbackTexture?: Texture, generateMipMaps?: boolean) {             super(name, size, "fire", scene, fallbackTexture, generateMipMaps);@@ -59,6 +60,7 @@             this.setColor3("c4", this._fireColors[3]);             this.setColor3("c5", this._fireColors[4]);             this.setColor3("c6", this._fireColors[5]);+            this.setFloat("alphaThreshold", this._alphaThreshold);         }          public render(useCameraPostProcess?: boolean) {@@ -194,74 +196,64 @@     }      export class GrassProceduralTexture extends ProceduralTexture {+        private _grassColors: BABYLON.Color3[];         private _herb1: BABYLON.Color3 = new BABYLON.Color3(0.29, 0.38, 0.02);         private _herb2: BABYLON.Color3 = new BABYLON.Color3(0.36, 0.49, 0.09);         private _herb3: BABYLON.Color3 = new BABYLON.Color3(0.51, 0.6, 0.28);-        private _dirt: BABYLON.Color3 = new BABYLON.Color3(0.6, 0.46, 0.13);-        private _ground: BABYLON.Color3 = new BABYLON.Color3(1, 1, 1);+        private _dirtColor: BABYLON.Color3 = new BABYLON.Color3(0.6, 0.46, 0.13);+        private _groundColor: BABYLON.Color3 = new BABYLON.Color3(1, 1, 1);          constructor(name: string, size: number, scene: Scene, fallbackTexture?: Texture, generateMipMaps?: boolean) {             super(name, size, "grass", scene, fallbackTexture, generateMipMaps);-            this.updateShaderUniforms();-            this.refreshRate = 0;-        } -        public updateShaderUniforms() {-            this.setColor3("herb1", this._herb1);-            this.setColor3("herb2", this._herb2);-            this.setColor3("herb3", this._herb2);-            this.setColor3("dirt", this._dirt);-            this.setColor3("ground", this._ground);-        }--        public get herb1(): BABYLON.Color3 {-            return this._herb1;-        }+            this._grassColors = [+                new BABYLON.Color3(0.29, 0.38, 0.02),+                new BABYLON.Color3(0.36, 0.49, 0.09),+                new BABYLON.Color3(0.51, 0.6, 0.28),+            ]; -        public set herb1(value: BABYLON.Color3) {-            this._herb1 = value;             this.updateShaderUniforms();+            this.refreshRate = 0;         } -        public get herb2(): BABYLON.Color3 {-            return this._herb2;-        }--        public set herb2(value: BABYLON.Color3) {-            this._herb2 = value;-            this.updateShaderUniforms();+        public updateShaderUniforms() {+            this.setColor3("herb1", this._grassColors[0]);+            this.setColor3("herb2", this._grassColors[1]);+            this.setColor3("herb3", this._grassColors[2]);+            this.setColor3("dirt", this._dirtColor);+            this.setColor3("ground", this._groundColor);         } -        public get herb3(): BABYLON.Color3 {-            return this._herb3;+        public get grassColors(): BABYLON.Color3[] {+            return this._grassColors;         } -        public set herb3(value: BABYLON.Color3) {-            this._herb3 = value;+        public set grassColors(value: BABYLON.Color3[]) {+            this._grassColors = value;             this.updateShaderUniforms();         } -        public get dirt(): BABYLON.Color3 {-            return this._dirt;+        public get dirtColor(): BABYLON.Color3 {+            return this._dirtColor;         } -        public set dirt(value: BABYLON.Color3) {-            this._dirt = value;+        public set dirtColor(value: BABYLON.Color3) {+            this._dirtColor = value;             this.updateShaderUniforms();         } -        public get ground(): BABYLON.Color3 {-            return this._ground;+        public get groundColor(): BABYLON.Color3 {+            return this._groundColor;         }          public set ground(value: BABYLON.Color3) {-            this._ground = value;+            this.groundColor = value;             this.updateShaderUniforms();         }     }      export class RoadProceduralTexture extends ProceduralTexture {-        private _macadamColor: BABYLON.Color3 = new BABYLON.Color3(0.53, 0.53, 0.53);+        private _roadColor: BABYLON.Color3 = new BABYLON.Color3(0.53, 0.53, 0.53);          constructor(name: string, size: number, scene: Scene, fallbackTexture?: Texture, generateMipMaps?: boolean) {             super(name, size, "road", scene, fallbackTexture, generateMipMaps);@@ -270,15 +262,15 @@         }          public updateShaderUniforms() {-            this.setColor3("macadamColor", this._macadamColor);+            this.setColor3("roadColor", this._roadColor);         } -        public get macadamColor(): BABYLON.Color3 {-            return this._macadamColor;+        public get roadColor(): BABYLON.Color3 {+            return this._roadColor;         } -        public set macadamColor(value: BABYLON.Color3) {-            this._macadamColor = value;+        public set roadColor(value: BABYLON.Color3) {+            this._roadColor = value;             this.updateShaderUniforms();         }     }
  • babylon.abstractMesh.ts
diff --git a/Babylon/Mesh/babylon.abstractMesh.ts b/Babylon/Mesh/babylon.abstractMesh.tsindex adcfa6a..d74aab0 100644--- a/Babylon/Mesh/babylon.abstractMesh.ts+++ b/Babylon/Mesh/babylon.abstractMesh.ts@@ -50,6 +50,9 @@         public renderOutline = false;         public outlineColor = BABYLON.Color3.Red();         public outlineWidth = 0.02;+        public renderOverlay = false;+        public overlayColor = BABYLON.Color3.Red();+        public overlayAlpha = 0.5;         public hasVertexAlpha = false;         public useVertexColors = true;
  • babylon.mesh.ts
diff --git a/Babylon/Mesh/babylon.mesh.ts b/Babylon/Mesh/babylon.mesh.tsindex 934f350..752e0b4 100644--- a/Babylon/Mesh/babylon.mesh.ts+++ b/Babylon/Mesh/babylon.mesh.ts@@ -526,6 +526,7 @@             if (this.renderOutline) {                 engine.setDepthWrite(false);                 scene.getOutlineRenderer().render(subMesh, batch);+                engine.setDepthWrite(savedDepthWrite);             }              effectiveMaterial._preBind();@@ -571,6 +572,14 @@                 engine.setColorWrite(true);             } +            // Overlay+            if (this.renderOverlay) {+                var currentMode = engine.getAlphaMode();+                engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE);+                scene.getOutlineRenderer().render(subMesh, batch, true);+                engine.setAlphaMode(currentMode);+            }+             for (callbackIndex = 0; callbackIndex < this._onAfterRenderCallbacks.length; callbackIndex++) {                 this._onAfterRenderCallbacks[callbackIndex]();             }
  • babylon.outlineRenderer.ts
diff --git a/Babylon/Rendering/babylon.outlineRenderer.ts b/Babylon/Rendering/babylon.outlineRenderer.tsindex 17221f6..9af7456 100644--- a/Babylon/Rendering/babylon.outlineRenderer.ts+++ b/Babylon/Rendering/babylon.outlineRenderer.ts@@ -8,11 +8,11 @@             this._scene = scene;         } -        public render(subMesh: SubMesh, batch: _InstancesBatch) {+        public render(subMesh: SubMesh, batch: _InstancesBatch, useOverlay: boolean = false) {             var scene = this._scene;             var engine = this._scene.getEngine(); -            var hardwareInstancedRendering = (engine.getCaps().instancedArrays !== null) && (batch.visibleInstances !== null);+            var hardwareInstancedRendering = (engine.getCaps().instancedArrays !== null) && (batch.visibleInstances[subMesh._id] !== null) && (batch.visibleInstances[subMesh._id] !== undefined);              if (!this.isReady(subMesh, hardwareInstancedRendering)) {                 return;@@ -22,8 +22,8 @@             var material = subMesh.getMaterial();              engine.enableEffect(this._effect);-            this._effect.setFloat("offset", mesh.outlineWidth);-            this._effect.setColor3("color", mesh.outlineColor);+            this._effect.setFloat("offset", useOverlay ? 0 : mesh.outlineWidth);+            this._effect.setColor4("color", useOverlay ? mesh.overlayColor : mesh.outlineColor, useOverlay ? mesh.overlayAlpha : 1.0);             this._effect.setMatrix("viewProjection", scene.getTransformMatrix());              // Bones@@ -41,7 +41,6 @@                 this._effect.setMatrix("diffuseMatrix", alphaTexture.getTextureMatrix());             } -             if (hardwareInstancedRendering) {                 mesh._renderWithInstances(subMesh, Material.TriangleFillMode, batch, this._effect, engine);             } else {
  • default.fragment.fx
diff --git a/Babylon/Shaders/default.fragment.fx b/Babylon/Shaders/default.fragment.fxindex a0d36da..3f17f1d 100644--- a/Babylon/Shaders/default.fragment.fx+++ b/Babylon/Shaders/default.fragment.fx@@ -317,9 +317,9 @@ mat3 cotangent_frame(vec3 normal, vec3 p, vec2 uv)  vec3 perturbNormal(vec3 viewDir) {-	vec3 map = texture2D(bumpSampler, vBumpUV).xyz * vBumpInfos.y;+	vec3 map = texture2D(bumpSampler, vBumpUV).xyz; 	map = map * 255. / 127. - 128. / 127.;-	mat3 TBN = cotangent_frame(vNormalW, -viewDir, vBumpUV);+	mat3 TBN = cotangent_frame(vNormalW * vBumpInfos.y, -viewDir, vBumpUV); 	return normalize(TBN * map); } #endif
  • fire.fragment.fx
diff --git a/Babylon/Shaders/fire.fragment.fx b/Babylon/Shaders/fire.fragment.fxindex 8757789..3e54547 100644--- a/Babylon/Shaders/fire.fragment.fx+++ b/Babylon/Shaders/fire.fragment.fx@@ -11,7 +11,7 @@ uniform vec3 c5; uniform vec3 c6; uniform vec2 speed; uniform float shift;-uniform float alpha;+uniform float alphaThreshold;  varying vec2 vUV; @@ -40,5 +40,8 @@ void main() { 	float q = fbm(p - iGlobalTime * 0.1); 	vec2 r = vec2(fbm(p + q + iGlobalTime * speed.x - p.x - p.y), fbm(p + q - iGlobalTime * speed.y)); 	vec3 c = mix(c1, c2, fbm(p + r)) + mix(c3, c4, r.x) - mix(c5, c6, r.y);-	gl_FragColor = vec4(c * cos(shift * vUV.y), alpha);+	vec3 color = c * cos(shift * vUV.y);+	float luminance = dot(color.rgb, vec3(0.3, 0.59, 0.11));++	gl_FragColor = vec4(color, luminance * alphaThreshold + (1.0 - alphaThreshold)); }\ No newline at end of file
  • outline.fragment.fx
diff --git a/Babylon/Shaders/outline.fragment.fx b/Babylon/Shaders/outline.fragment.fxindex 95198b5..fc6b047 100644--- a/Babylon/Shaders/outline.fragment.fx+++ b/Babylon/Shaders/outline.fragment.fx@@ -1,6 +1,6 @@ precision highp float; -uniform vec3 color;+uniform vec4 color;  #ifdef ALPHATEST varying vec2 vUV;@@ -13,5 +13,5 @@ void main(void) { 		discard; #endif -	gl_FragColor = vec4(color, 1.);+	gl_FragColor = color; }\ No newline at end of file
  • road.fragment.fx
diff --git a/Babylon/Shaders/road.fragment.fx b/Babylon/Shaders/road.fragment.fxindex 7bfdf3b..3efaed1 100644--- a/Babylon/Shaders/road.fragment.fx+++ b/Babylon/Shaders/road.fragment.fx@@ -3,7 +3,7 @@ precision highp float; #endif  varying vec2 vUV;                    -uniform vec3 macadamColor;+uniform vec3 roadColor;  float rand(vec2 n) { 	return fract(cos(dot(n, vec2(12.9898, 4.1414))) * 43758.5453);@@ -27,6 +27,6 @@ float fbm(vec2 n) {  void main(void) { 	float ratioy = mod(gl_FragCoord.y * 100.0 , fbm(vUV * 2.0));-	vec3 color = macadamColor * ratioy;+	vec3 color = roadColor * ratioy; 	gl_FragColor = vec4(color, 1.0); }\ No newline at end of file
  • babylon.tools.ts
diff --git a/Babylon/Tools/babylon.tools.ts b/Babylon/Tools/babylon.tools.tsindex 6f1ffdb..95532b8 100644--- a/Babylon/Tools/babylon.tools.ts+++ b/Babylon/Tools/babylon.tools.ts@@ -619,6 +619,9 @@         private static _MessageLogLevel = 1;         private static _WarningLogLevel = 2;         private static _ErrorLogLevel = 4;+        private static _LogCache = "";++        public static OnNewCacheEntry: (entry: string) => void;          static get NoneLogLevel(): number {             return Tools._NoneLogLevel;@@ -640,11 +643,19 @@             return Tools._MessageLogLevel | Tools._WarningLogLevel | Tools._ErrorLogLevel;         } +        private static _AddLogEntry(entry: string) {+            Tools._LogCache = entry + Tools._LogCache;++            if (Tools.OnNewCacheEntry) {+                Tools.OnNewCacheEntry(entry);+            }+        }+         private static _FormatMessage(message: string): string {             var padStr = i => (i < 10) ? "0" + i : "" + i;              var date = new Date();-            return "BJS - [" + padStr(date.getHours()) + ":" + padStr(date.getMinutes()) + ":" + padStr(date.getSeconds()) + "]: " + message;+            return "[" + padStr(date.getHours()) + ":" + padStr(date.getMinutes()) + ":" + padStr(date.getSeconds()) + "]: " + message;         }          public static Log: (message: string) => void = Tools._LogEnabled;@@ -653,7 +664,11 @@             // nothing to do         }         private static _LogEnabled(message: string): void {-            console.log(Tools._FormatMessage(message));+            var formattedMessage = Tools._FormatMessage(message);+            console.log("BJS - " + formattedMessage);++            var entry = "<div style='color:white'>" + formattedMessage + "</div><br>";+            Tools._AddLogEntry(entry);         }          public static Warn: (message: string) => void = Tools._WarnEnabled;@@ -662,7 +677,11 @@             // nothing to do         }         private static _WarnEnabled(message: string): void {-            console.warn(Tools._FormatMessage(message));+            var formattedMessage = Tools._FormatMessage(message);+            console.warn("BJS - " + formattedMessage);++            var entry = "<div style='color:orange'>" + formattedMessage + "</div><br>";+            Tools._AddLogEntry(entry);         }          public static Error: (message: string) => void = Tools._ErrorEnabled;@@ -671,7 +690,15 @@             // nothing to do         }         private static _ErrorEnabled(message: string): void {-            console.error(Tools._FormatMessage(message));+            var formattedMessage = Tools._FormatMessage(message);+            console.error("BJS - " + formattedMessage);++            var entry = "<div style='color:red'>" + formattedMessage + "</div><br>";+            Tools._AddLogEntry(entry);+        }++        public static get LogCache(): string {+            return Tools._LogCache;         }          public static set LogLevels(level: number) {
  • babylon.sound.ts
diff --git a/Babylon/Audio/babylon.sound.ts b/Babylon/Audio/babylon.sound.tsindex d439a50..667e4d8 100644--- a/Babylon/Audio/babylon.sound.ts+++ b/Babylon/Audio/babylon.sound.ts@@ -1,31 +1,60 @@module BABYLON {     export class Sound {         private _audioBuffer;-        public distanceMax: number = 10;+        public maxDistance: number = 10;         public autoplay: boolean = false;         public loop: boolean = false;         private _position: Vector3 = Vector3.Zero();-        private _orientation: Vector3 = Vector3.Zero();+        private _direction: Vector3 = Vector3.Zero();         private _volume: number;         private _currentVolume: number;         private _isLoaded: boolean = false;         private _isReadyToPlay: boolean = false;+        private _isPlaying: boolean = false;+        private _isDirectional: boolean = false;         private _audioEngine: BABYLON.AudioEngine;         private _readyToPlayCallback;         private _soundSource: AudioBufferSourceNode;         private _soundPanner: PannerNode;+        // Used if you'd like to create a directional sound.+        // If not set, the sound will be omnidirectional+        private _coneInnerAngle: number = null;+        private _coneOuterAngle: number = null;+        private _coneOuterGain: number = null;         constructor(url: string, engine: BABYLON.Engine, readyToPlayCallback, distanceMax?: number, autoplay?: boolean, loop?: boolean) {             this._audioEngine = engine.getAudioEngine();;             this._readyToPlayCallback = readyToPlayCallback;-            if (distanceMax) this.distanceMax = distanceMax;-            if (autoplay) this.autoplay = autoplay;-            if (loop) this.loop = loop;+            if (distanceMax) { this.maxDistance = distanceMax; }+            if (autoplay) { this.autoplay = autoplay; }+            if (loop) { this.loop = loop; }             if (this._audioEngine.canUseWebAudio) {                 BABYLON.Tools.LoadFile(url, (data) => { this._soundLoaded(data); }, null, null, true);             }         }+        /**+        * Transform this sound into a directional source+        * @param coneInnerAngle Size of the inner cone in degree+        * @param coneOuterAngle Size of the outer cone in degree+        * @param coneOuterGain Volume of the sound outside the outer cone (between 0.0 and 1.0)+        */+        public setDirectionalCone(coneInnerAngle: number, coneOuterAngle: number, coneOuterGain: number) {+            if (coneOuterAngle < coneInnerAngle) {+                BABYLON.Tools.Error("setDirectionalCone(): outer angle of the cone must be superior or equal to the inner angle.");+                return;+            }+            this._coneInnerAngle = coneInnerAngle;+            this._coneOuterAngle = coneOuterAngle;+            this._coneOuterGain = coneOuterGain;+            this._isDirectional = true;++            if (this._isPlaying && this.loop) {+                this.stop();+                this.play();+            }+        }+         public setPosition(newPosition: Vector3) {             this._position = newPosition;@@ -34,11 +63,12 @@             }         }-        public setOrientiation(newOrientation: Vector3) {-            this._orientation = newOrientation;+        public setDirection(newDirection: Vector3) {+            this._direction = newDirection;             if (this._isReadyToPlay) {-                this._soundPanner.setOrientation(this._orientation.x, this._orientation.y, this._orientation.z);+                console.log(this._direction.x + " " + this._direction.y + " " + this._direction.z);+                this._soundPanner.setOrientation(this._direction.x, this._direction.y, this._direction.z);             }         }@@ -48,14 +78,23 @@                 this._soundSource.buffer = this._audioBuffer;                 this._soundPanner = this._audioEngine.audioContext.createPanner();                 this._soundPanner.setPosition(this._position.x, this._position.y, this._position.z);+                //this._soundPanner.maxDistance = this.maxDistance;+                if (this._isDirectional) {+                    this._soundPanner.coneInnerAngle = this._coneInnerAngle;+                    this._soundPanner.coneOuterAngle = this._coneOuterAngle;+                    this._soundPanner.coneOuterGain = this._coneOuterGain;+                }                 this._soundPanner.connect(this._audioEngine.masterGain);                 this._soundSource.connect(this._soundPanner);                 this._soundSource.loop = this.loop;                 this._soundSource.start(0);+                this._isPlaying = true;             }         }         public stop() {+            this._soundSource.stop(0);+            this._isPlaying = false;         }         public pause() {@@ -67,6 +106,10 @@         private _onRegisterAfterWorldMatrixUpdate(connectedMesh: BABYLON.AbstractMesh) {             this.setPosition(connectedMesh.position);+            var mat = connectedMesh.getWorldMatrix();+            var direction = BABYLON.Vector3.TransformCoordinates(new BABYLON.Vector3(0, 0, -1), mat);+            direction.normalize();+            this.setDirection(direction);         }         private _soundLoaded(audioData: ArrayBuffer) {
Link to comment
Share on other sites

Ok, I'll provide a repro case without external objects. I'm not sure whether the bug is visible or not with primitive meshes, I kind of noticed that it's easier to spot with a soft surface, like a rounded cube. Maybe with the new ribbon mesh, or the cat (if UVs sets are correctly mapped). Will try that tomorrow.


BTW, I'm surprised scene loading takes ages. I know the file is big (3.5MB) but the server should be pretty reachable (french university global subnet) and there is a manifest file, the .babylon should be loaded only once, at first, and then be locally stored in indexDB, isn't it the case ?


(Anyway, I will do a simpler PG)

Link to comment
Share on other sites

Hey Vousk,


I've been looking into your problem and here is my conclusion: there is no bug with BJS bump mapping, the problem lies in your diffuse and bump textures. (Sorry in advance if I'm wrong and blatantly accused your work for no reason!!).


Here is a PG with your example, with the debug layer shown and the model scaled up (to be able to zoom more): http://www.babylonjs-playground.com/#1MYQJJ#56


Now try to disable diffuse and bump textures with the debug layer, one after the other. i don't know what your intent was, but these two textures look very similar and though are not really matching in resolution. Also, the diffuse texture is actually a kind of precomputed bump texture, which conflicts with the real-time computed one. This means that under certain lighting conditions, the two motifs will overlap and create a kind of "evened out" mess.


In the diff you posted there is a clear modification on the way bump mapping is computed, so I thought this was where the problem came from. But after tinkering a bit, I couldn't get rid of this weird effect. Plus, when the diffuse texture is disabled, the bump effect looks absolutely normal.


I hope this will help you. My advice would be to redo your diffuse texture in a way that it holds only color information and no relief at all. What is called 'albedo' in Physics Based Rendering systems (let's get prepared for the future, shall we? ;) )

Link to comment
Share on other sites

Thank you jahow for diving into that problem! :)


And you're totaly right on every point you mention  B)


- My diffuse tex and bump tex are not same resolution, the reason is simple : the bump tex will be loaded once and reused for all materials, whereas there will be one diffuse texture for each "color", so the bump one is 512px and all the diffuses are 256px (or less). But I've never had problem with that in the different game engines I used to deal with. :unsure:


- Yep, albedo is what some shader tools recommend, but unfortunatly in most real cases it's not applicable. You have to bake the bump just a little into the diffuse to add realism, to ensure your objects to be visually ok in every situation. Why ? For (at least) three reasons :

1. with bump map only, few illuminated area immediatly looks fake (because of no details anymore)

2. the diffuse enforce drasticaly the visual effect of the bump without the need of increasing bump deepness - increasing this value always results in awful artifacts, unrealistic specular dots -

3. the diffuse here simulate the physical "dirt" fact, for instance for this material, disable the diffuse map and you'll not be able to recognise what kind of material it is, enable it and you start recognising it's leather (you only "start recognising" because I simplified the material for the PG debug, it lacks proper specular, a little fresnel, etc)

To be able to use only color in diffuse map, we need to draw those "dirt" area in the lightmap (except for shader using also a dirtmap), but once again for many reason it's almost always impossible. Usually, the lightmap is on a different UV set than diffuse, a well defined diffuse will be tiled, a lightmap never. For perfs reasons we need not too high resolution textures, resulting in limited area to draw the whole object's surface, that means less precision for each poly in the ligthmap (no problem at all for lightmapping, it's even sometimes very convenient because it kind of auto smooths the shadows), but this lack of precision make it unusable to draw little details as "bump dirtiness". Also, the lightmap is related to an object (and sometimes even to a group of objects), so if the object can change its material real time, the lightmap need to be enough generic to work with many different materials (and two different kind of material lead to different way for the surface to get dirty...).


Well, I'm not trying to reject your accusations :lol: , but the current diffuse/bump/lightmap combination I'm using is (unfortunatly) mostly the only applicable when realism AND versatilty is required (and that's often the case...)


But I ear you and the fact that you couldn't get rid of the weird effect while tinkering the code. I'll dig into that, create a new PG easier to check, try with same resolution map to see if it's better.

I think there are some other little details in the BJS rendering of the bump and specular we could discuss. See you later ;)

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...