Sebastien Vandenberghe 9 年 前
コミット
fb8b3515ca

+ 8 - 1
src/Materials/Textures/babylon.hdrcubetexture.ts

@@ -104,8 +104,15 @@ module BABYLON {
                 }
                 return results;
             }
+            
+            var mipmapGenerator = null;
+            if (this._noMipmap)
+            {
+                // TODO. Parameterized num level.
+                mipmapGenerator = new BABYLON.Internals.PMREMGenerator(5);
+            }
 
-            this._texture = (<any>this.getScene().getEngine()).createRawCubeTexture(this.url, this.getScene(), this._size, Engine.TEXTUREFORMAT_RGB, Engine.TEXTURETYPE_FLOAT, this._noMipmap, callback);
+            this._texture = (<any>this.getScene().getEngine()).createRawCubeTexture(this.url, this.getScene(), this._size, Engine.TEXTUREFORMAT_RGB, Engine.TEXTURETYPE_FLOAT, this._noMipmap, callback, mipmapGenerator);
         }
 
         public clone(): HDRCubeTexture {

+ 67 - 0
src/Tools/HDR/babylon.tools.pmremgenerator.ts

@@ -1,5 +1,72 @@
 module BABYLON.Internals {
     export class PMREMGenerator {
+        
+        constructor(public levelCount: number) {
+        }
 
+        public generateMipmaps(faces: ArrayBufferView[]): ArrayBufferView[][] {
+            // Prepare a well sized result.
+            var result: ArrayBufferView[][] = [];
+            var totalAngle = Math.PI * 2;
+            var levelBlurAngle = totalAngle / this.levelCount;
+            var currentLevel = 0;
+            
+            // TODO Handle none full float 
+            // / 4 in full float
+            var currentArraySize = faces[0].byteLength / 4;
+            var currentPixelsCount = currentArraySize / 3;
+            var currentCubeFaceSize = Math.sqrt(currentPixelsCount);
+            
+            // Find back the max number of levels in the cube map.
+            var totalLevelCount = Math.log(currentCubeFaceSize) * Math.LOG2E;
+            
+            // Go accross levels.
+            for (let i = 1; i <= this.levelCount; i++) {
+                // Prepare output arrays.
+                result.length++;
+                
+                // Prepare required data.
+                currentLevel++;
+                currentCubeFaceSize = Math.pow(2, totalLevelCount - currentLevel); 
+                currentPixelsCount = currentCubeFaceSize * currentCubeFaceSize * 3;
+                
+                // Go accross faces.
+                for (let j = 0; j < 6; j++) {
+                    // Prepare output arrays.
+                    result[i].length++;
+                    
+                    // TODO Handle none full float.
+                    var data = new Float32Array(currentPixelsCount);
+                    
+                    // Go accross each pixels to fill in.
+                    for (let y = 0; y < currentCubeFaceSize; y++) {
+                        
+                        // Scanline
+                        for (let x = 0; x < currentCubeFaceSize; x++) {
+                            
+                            var color = this.getCosineBlur(faces, x, y, j);
+                            
+                            data[(y * currentCubeFaceSize + x) * 3 + 0] = color.r;
+                            data[(y * currentCubeFaceSize + x) * 3 + 1] = color.g;
+                            data[(y * currentCubeFaceSize + x) * 3 + 2] = color.b;
+                        } 
+                    }
+                    
+                    result[i][j] = data;
+                }    
+            }
+            
+            return result;
+        }
+        
+        private static _tempColor: Color3 = new Color3();
+        
+        private getCosineBlur(faces: ArrayBufferView[], x: number, y:number, faceIndex: number): Color3 {
+            PMREMGenerator._tempColor.r = faceIndex / 6;
+            PMREMGenerator._tempColor.r = faceIndex / 6;
+            PMREMGenerator._tempColor.r = faceIndex / 6;
+            
+            return PMREMGenerator._tempColor;
+        }
     }
 } 

+ 13 - 2
src/babylon.engine.ts

@@ -2159,7 +2159,9 @@
             return texture;
         }
 
-        public createRawCubeTexture(url: string, scene: Scene, size: number, format: number, type: number, noMipmap: boolean, callback: (ArrayBuffer) => ArrayBufferView[]): WebGLTexture {
+        public createRawCubeTexture(url: string, scene: Scene, size: number, format: number, type: number, noMipmap: boolean,
+            callback: (ArrayBuffer) => ArrayBufferView[],
+            mipmmapGenerator: ((faces: ArrayBufferView[]) => ArrayBufferView[][])): WebGLTexture {
             var gl = this._gl;
             var texture = gl.createTexture();
             scene._addPendingData(texture);
@@ -2201,7 +2203,16 @@
                     gl.texImage2D(facesIndex[index], 0, internalFormat, width, height, 0, internalFormat, textureType, faceData);
                 }
 
-                if (!noMipmap && isPot) {
+                if (!noMipmap && isPot && mipmmapGenerator) {
+                    var mipData = mipmmapGenerator(rgbeDataArrays);
+                    for (var level = 1; level <= mipData.length; level++) {
+                        for (var mipFaceIndex = 0; mipFaceIndex < mipData[level - 1].length; mipFaceIndex++) {
+                            var mipSize = Math.pow(2, Math.log(width) * Math.LOG2E - level);
+                            gl.texImage2D(facesIndex[index], level, internalFormat, mipSize, mipSize, 0, internalFormat, textureType, mipData[level - 1][mipFaceIndex]);
+                        }
+                    }
+                }
+                else if (!noMipmap && isPot) {
                     gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
                 }
                 else {