Prechádzať zdrojové kódy

Introducing shaders library

David Catuhe 9 rokov pred
rodič
commit
f0b0ed02ac

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 18 - 24
dist/preview release/babylon.core.js


+ 9 - 5
dist/preview release/babylon.d.ts

@@ -3071,6 +3071,7 @@ declare module BABYLON {
         scale(value: number): Quaternion;
         multiply(q1: Quaternion): Quaternion;
         multiplyToRef(q1: Quaternion, result: Quaternion): Quaternion;
+        multiplyInPlace(q1: Quaternion): Quaternion;
         length(): number;
         normalize(): Quaternion;
         toEulerAngles(): Vector3;
@@ -3436,8 +3437,8 @@ declare module BABYLON {
         freezeWorldMatrix(): void;
         unfreezeWorldMatrix(): void;
         isWorldMatrixFrozen: boolean;
-        rotate(axis: Vector3, amount: number, space: Space): void;
-        translate(axis: Vector3, distance: number, space: Space): void;
+        rotate(axis: Vector3, amount: number, space?: Space): void;
+        translate(axis: Vector3, distance: number, space?: Space): void;
         getAbsolutePosition(): Vector3;
         setAbsolutePosition(absolutePosition: Vector3): void;
         /**
@@ -4272,6 +4273,7 @@ declare module BABYLON {
             height?: number;
             sideOrientation?: number;
             updatable?: boolean;
+            sourcePlane?: Plane;
         }, scene: Scene): Mesh;
         static CreateGround(name: string, options: {
             width?: number;
@@ -4830,6 +4832,7 @@ declare module BABYLON {
         static ConeImpostor: number;
         static CylinderImpostor: number;
         static ConvexHullImpostor: number;
+        static HeightmapImpostor: number;
         static Epsilon: number;
     }
 }
@@ -6582,10 +6585,11 @@ declare module BABYLON {
         runOneStep(delta: number): void;
         setGravity(gravity: Vector3): void;
         registerMesh(mesh: AbstractMesh, impostor: number, options?: PhysicsBodyCreationOptions): any;
-        private _createShape(mesh, impostor, options?);
-        private _createConvexPolyhedron(rawVerts, rawFaces, mesh, options?);
+        private _createShape(mesh, impostor);
+        private _createConvexPolyhedron(rawVerts, rawFaces, mesh);
+        private _createHeightmap(mesh);
         private _addMaterial(friction, restitution);
-        private _createRigidBodyFromShape(shape, mesh, mass, friction, restitution);
+        private _createRigidBodyFromShape(shape, mesh, options);
         registerMeshesAsCompound(parts: PhysicsCompoundBodyPart[], options: PhysicsBodyCreationOptions): any;
         private _unbindBody(body);
         unregisterMesh(mesh: AbstractMesh): void;

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 25 - 33
dist/preview release/babylon.js


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 88 - 28
dist/preview release/babylon.max.js


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 24 - 32
dist/preview release/babylon.noworker.js


+ 1 - 0
dist/preview release/what's new.md

@@ -1,5 +1,6 @@
 - 2.3.0:
   - **Major updates**
+    - Introducing [Shaders Library](https://github.com/BabylonJS/Babylon.js/shadersLibrary) ([deltakosh](https://github.com/deltakosh))
     - New cache mecanism for StandardMaterial ([deltakosh](https://github.com/deltakosh))
     - New Solid Particle System ([jerome](https://github.com/jbousquie))
     - New `StandardMaterial.lightmapTexture` which can be controlled with `StandardMaterial.useLightmapAsShadowMap`. [Demo here](#NEEDDEMO) ([deltakosh](https://github.com/deltakosh))

+ 15 - 0
shadersLibrary/config.json

@@ -0,0 +1,15 @@
+{
+  "materials": [
+    {
+      "file": "shaders/simple/babylon.simpleMaterial.ts",
+      "shaderFiles": [
+        "shaders/simple/simple.vertex.fx",
+        "shaders/simple/simple.fragment.fx"
+      ],
+      "output": "babylon.simpleMaterial.js"
+    }
+  ],
+  "build": {
+    "distOutputDirectory": "dist/"
+  }
+}

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 427 - 0
shadersLibrary/dist/babylon.simpleMaterial.js


+ 68 - 0
shadersLibrary/gulp-srcToVariable.js

@@ -0,0 +1,68 @@
+var through = require('through2');
+var gutil = require('gulp-util');
+var PluginError = gutil.PluginError;
+var path = require('path');
+var File = gutil.File;
+
+// Consts
+const PLUGIN_NAME = 'gulp-srcToVariable';
+
+var srcToVariable = function srcToVariable(varName, asMap, namingCallback) {
+
+    var content;
+    var firstFile;
+
+    namingCallback = namingCallback || function (filename) { return filename; };
+
+    function bufferContents(file, enc, cb) {
+        // ignore empty files
+        if (file.isNull()) {
+            cb();
+            return;
+        }
+
+        // no stream support, only files.
+        if (file.isStream()) {
+            this.emit('error', new PluginError('gulp-concat', 'Streaming not supported'));
+            cb();
+            return;
+        }
+
+        // set first file if not already set
+        if (!firstFile) {
+            firstFile = file;
+        }
+
+        // construct concat instance
+        if (!content) {
+            content = "";
+        }
+        var name = namingCallback(file.relative);
+        content += varName + "['" + name + "'] = " + JSON.stringify(file.contents.toString()) + ";\r\n";
+        cb();
+    }
+
+    function endStream(cb) {
+        if (!firstFile || !content) {
+            cb();
+            return;
+        }
+
+        var joinedPath = path.join(firstFile.base, varName);
+
+        var joinedFile = new File({
+            cwd: firstFile.cwd,
+            base: firstFile.base,
+            path: joinedPath,
+            contents: new Buffer(content)
+        });
+
+        this.push(joinedFile);
+
+        cb();
+    }
+
+    return through.obj(bufferContents, endStream);
+}
+
+module.exports = srcToVariable;

+ 44 - 0
shadersLibrary/gulpfile.js

@@ -0,0 +1,44 @@
+var gulp = require("gulp");
+var uglify = require("gulp-uglify");
+var typescript = require("gulp-typescript");
+var srcToVariable = require("./gulp-srcToVariable");
+var merge2 = require("merge2");
+var concat = require("gulp-concat");
+var rename = require("gulp-rename");
+var cleants = require('gulp-clean-ts-extends');
+var replace = require("gulp-replace");
+
+var config = require("./config.json");
+var extendsSearchRegex = /var\s__extends[\s\S]+?\};/g;
+
+//function to convert the shaders' filenames to variable names.
+function shadersName(filename) {
+    return filename.replace('.fragment', 'Pixel')
+      .replace('.vertex', 'Vertex')
+      .replace('.fx', 'Shader');
+}
+
+/*
+Compiles all typescript files and creating a declaration file.
+*/
+gulp.task('default', function () {
+    var tasks = config.materials.map(function (material) {
+        var js = gulp.src(material.file)
+            .pipe(typescript({
+                noExternalResolve: false,
+                target: 'ES5',
+                declarationFiles: true,
+                typescript: require('typescript')
+            })).js;
+
+        var shader = gulp.src(material.shaderFiles).pipe(srcToVariable("BABYLON.Effect.ShadersStore", true, shadersName));
+
+        return merge2(js, shader)
+            .pipe(cleants())
+            .pipe(replace(extendsSearchRegex, ""))
+            .pipe(concat(material.output))
+            .pipe(gulp.dest(config.build.distOutputDirectory));
+    });
+
+    return tasks;
+});

+ 22 - 0
shadersLibrary/package.json

@@ -0,0 +1,22 @@
+{
+  "name": "BabylonJS_ShadersLibrary",
+  "version": "2.3.0",
+  "description": "Shaders library for Babylon.js",
+  "main": "",
+  "repository": { "url": "https://github.com/BabylonJS/Babylon.js/" },
+  "readme": "https://github.com/BabylonJS/Babylon.js/edit/master/readme.md",
+  "license": "(Apache-2.0)",
+  "devDependencies": {
+    "gulp": "^3.8.11",
+    "gulp-uglify": "~1.4.2",
+    "typescript": "~1.6.2",
+    "gulp-typescript": "~2.9.0",
+    "through2": "~0.6.5",
+    "gulp-util": "~3.0.4",
+    "gulp-concat": "~2.6.0",
+    "merge2": "~0.3.5",
+    "gulp-rename": "~1.2.2",
+    "gulp-clean-ts-extends": "~0.1.1",
+    "gulp-replace": "~0.5.3"
+  }
+}

+ 71 - 0
shadersLibrary/readme.md

@@ -0,0 +1,71 @@
+# Shaders library
+
+## Using a shader form the library
+
+You can find multiple shaders that just works with Babylon.js in *dist* folder. To use then, you only need to reference the associated .js file and use the new provided material:
+
+```
+var simple = new BABYLON.SimpleMaterial("simple", scene);
+sphere.material = simple;
+```
+
+## Adding a new shader to the library
+
+To add a new shader, you have to create your own folder in *shaders* folder. Then you need to add a .ts file an two .fx files:
+* The .ts is the TypeScript code of your shader
+* .fx files: GLSL code for vertex and fragment shaders
+
+The best way to start a new material is to copy/past the *simple* material. This material provides all the features required by a Babylon.js material:
+- Bones support
+- Instances support
+- Support for up to 4 lights
+- Cache support
+- Shadows support
+- Fog support
+- Point rendering support
+- Clip plane support
+
+But you can also start from scratch as you are not forced to support all these features.
+
+## Integrating the shader in the build process
+
+To integrate your new material to the build process, you have to edit the config.sjon file and add an entry in the "materials" section of the file:
+
+```
+{
+  "materials": [
+    {
+      "file": "shaders/simple/babylon.simpleMaterial.ts",
+      "shaderFiles": [
+        "shaders/simple/simple.vertex.fx",
+        "shaders/simple/simple.fragment.fx"
+      ],
+      "output": "babylon.simpleMaterial.js"
+    }
+  ],
+  "build": {
+    "distOutputDirectory": "dist/"
+  }
+}
+```
+
+## Testing your shader
+
+To test your shader, you can use the /test/index.html file by adding a reference to your .js file. Then you will need to update the code to create an instance of your material and reference it in the UI system:
+
+```
+gui.add(options, 'shader', ['standard', 'simple']).onFinishChange(function () {
+					switch (options.shader) {
+						case "simple":
+							currentMaterial = simple;
+							break;
+						default:
+							currentMaterial = std;
+							break;
+					}
+
+					currentMesh.material = currentMaterial;
+				});
+```
+
+This page allows you to test your code with animated meshes, shadows, various kinds of lights and fog. Just use the UI on the right to turn features on and off.

+ 513 - 0
shadersLibrary/shaders/simple/babylon.simpleMaterial.ts

@@ -0,0 +1,513 @@
+/// <reference path="../../../babylon.d.ts"/>
+
+module BABYLON {
+    var maxSimultaneousLights = 4;
+
+    class SimpleMaterialDefines extends MaterialDefines {
+        public DIFFUSE = false;
+        public CLIPPLANE = false;
+        public ALPHATEST = false;
+        public POINTSIZE = false;
+        public FOG = false;
+        public LIGHT0 = false;
+        public LIGHT1 = false;
+        public LIGHT2 = false;
+        public LIGHT3 = false;
+        public SPOTLIGHT0 = false;
+        public SPOTLIGHT1 = false;
+        public SPOTLIGHT2 = false;
+        public SPOTLIGHT3 = false;
+        public HEMILIGHT0 = false;
+        public HEMILIGHT1 = false;
+        public HEMILIGHT2 = false;
+        public HEMILIGHT3 = false;
+        public POINTDIRLIGHT0 = false;
+        public POINTDIRLIGHT1 = false;
+        public POINTDIRLIGHT2 = false;
+        public POINTDIRLIGHT3 = false;
+        public SHADOW0 = false;
+        public SHADOW1 = false;
+        public SHADOW2 = false;
+        public SHADOW3 = false;
+        public SHADOWS = false;
+        public SHADOWVSM0 = false;
+        public SHADOWVSM1 = false;
+        public SHADOWVSM2 = false;
+        public SHADOWVSM3 = false;
+        public SHADOWPCF0 = false;
+        public SHADOWPCF1 = false;
+        public SHADOWPCF2 = false;
+        public SHADOWPCF3 = false;
+        public NORMAL = false;
+        public UV1 = false;
+        public UV2 = false;
+        public VERTEXCOLOR = false;
+        public VERTEXALPHA = false;
+        public BONES = false;
+        public BONES4 = false;
+        public BonesPerMesh = 0;
+        public INSTANCES = false;
+
+        constructor() {
+            super();
+            this._keys = Object.keys(this);
+        }
+    }
+
+    export class SimpleMaterial extends Material {
+        public diffuseTexture: BaseTexture;
+
+        public diffuseColor = new Color3(1, 1, 1);
+        public disableLighting = false;
+
+        private _worldViewProjectionMatrix = Matrix.Zero();
+        private _scaledDiffuse = new Color3();
+        private _renderId: number;
+
+        private _defines = new SimpleMaterialDefines();
+        private _cachedDefines = new SimpleMaterialDefines();
+
+        constructor(name: string, scene: Scene) {
+            super(name, scene);
+
+            this._cachedDefines.BonesPerMesh = -1;
+        }
+
+        public needAlphaBlending(): boolean {
+            return (this.alpha < 1.0);
+        }
+
+        public needAlphaTesting(): boolean {
+            return false;
+        }
+
+        public getAlphaTestTexture(): BaseTexture {
+            return null;
+        }
+
+        // Methods   
+        private _checkCache(scene: Scene, mesh?: AbstractMesh, useInstances?: boolean): boolean {
+            if (!mesh) {
+                return true;
+            }
+
+            if (this._defines.INSTANCES !== useInstances) {
+                return false;
+            }
+
+            if (mesh._materialDefines && mesh._materialDefines.isEqual(this._defines)) {
+                return true;
+            }
+
+            return false;
+        }
+
+        public isReady(mesh?: AbstractMesh, useInstances?: boolean): boolean {
+            if (this.checkReadyOnlyOnce) {
+                if (this._wasPreviouslyReady) {
+                    return true;
+                }
+            }
+
+            var scene = this.getScene();
+
+            if (!this.checkReadyOnEveryCall) {
+                if (this._renderId === scene.getRenderId()) {
+                    if (this._checkCache(scene, mesh, useInstances)) {
+                        return true;
+                    }
+                }
+            }
+
+            var engine = scene.getEngine();
+            var needNormals = false;
+            var needUVs = false;
+
+            this._defines.reset();
+
+            // Textures
+            if (scene.texturesEnabled) {
+                if (this.diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
+                    if (!this.diffuseTexture.isReady()) {
+                        return false;
+                    } else {
+                        needUVs = true;
+                        this._defines.DIFFUSE = true;
+                    }
+                }                
+            }
+
+            // Effect
+            if (scene.clipPlane) {
+                this._defines.CLIPPLANE = true;
+            }
+
+            if (engine.getAlphaTesting()) {
+                this._defines.ALPHATEST = true;
+            }
+
+            // Point size
+            if (this.pointsCloud || scene.forcePointsCloud) {
+                this._defines.POINTSIZE = true;
+            }
+
+            // Fog
+            if (scene.fogEnabled && mesh && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE && this.fogEnabled) {
+                this._defines.FOG = true;
+            }
+
+            var lightIndex = 0;
+            if (scene.lightsEnabled && !this.disableLighting) {
+                for (var index = 0; index < scene.lights.length; index++) {
+                    var light = scene.lights[index];
+
+                    if (!light.isEnabled()) {
+                        continue;
+                    }
+
+                    // Excluded check
+                    if (light._excludedMeshesIds.length > 0) {
+                        for (var excludedIndex = 0; excludedIndex < light._excludedMeshesIds.length; excludedIndex++) {
+                            var excludedMesh = scene.getMeshByID(light._excludedMeshesIds[excludedIndex]);
+
+                            if (excludedMesh) {
+                                light.excludedMeshes.push(excludedMesh);
+                            }
+                        }
+
+                        light._excludedMeshesIds = [];
+                    }
+
+                    // Included check
+                    if (light._includedOnlyMeshesIds.length > 0) {
+                        for (var includedOnlyIndex = 0; includedOnlyIndex < light._includedOnlyMeshesIds.length; includedOnlyIndex++) {
+                            var includedOnlyMesh = scene.getMeshByID(light._includedOnlyMeshesIds[includedOnlyIndex]);
+
+                            if (includedOnlyMesh) {
+                                light.includedOnlyMeshes.push(includedOnlyMesh);
+                            }
+                        }
+
+                        light._includedOnlyMeshesIds = [];
+                    }
+
+                    if (!light.canAffectMesh(mesh)) {
+                        continue;
+                    }
+                    needNormals = true;
+                    this._defines["LIGHT" + lightIndex] = true;
+
+                    var type;
+                    if (light instanceof SpotLight) {
+                        type = "SPOTLIGHT" + lightIndex;
+                    } else if (light instanceof HemisphericLight) {
+                        type = "HEMILIGHT" + lightIndex;
+                    } else {
+                        type = "POINTDIRLIGHT" + lightIndex;
+                    }
+
+                    this._defines[type] = true;
+
+                    // Shadows
+                    if (scene.shadowsEnabled) {
+                        var shadowGenerator = light.getShadowGenerator();
+                        if (mesh && mesh.receiveShadows && shadowGenerator) {
+                            this._defines["SHADOW" + lightIndex] = true;
+
+                            this._defines.SHADOWS = true;
+
+                            if (shadowGenerator.useVarianceShadowMap || shadowGenerator.useBlurVarianceShadowMap) {
+                                this._defines["SHADOWVSM" + lightIndex] = true;
+                            }
+
+                            if (shadowGenerator.usePoissonSampling) {
+                                this._defines["SHADOWPCF" + lightIndex] = true;
+                            }
+                        }
+                    }
+
+                    lightIndex++;
+                    if (lightIndex === maxSimultaneousLights)
+                        break;
+                }
+            }
+
+            // Attribs
+            if (mesh) {
+                if (needNormals && mesh.isVerticesDataPresent(VertexBuffer.NormalKind)) {
+                    this._defines.NORMAL = true;
+                }
+                if (needUVs) {
+                    if (mesh.isVerticesDataPresent(VertexBuffer.UVKind)) {
+                        this._defines.UV1 = true;
+                    }
+                    if (mesh.isVerticesDataPresent(VertexBuffer.UV2Kind)) {
+                        this._defines.UV2 = true;
+                    }
+                }
+                if (mesh.useVertexColors && mesh.isVerticesDataPresent(VertexBuffer.ColorKind)) {
+                    this._defines.VERTEXCOLOR = true;
+
+                    if (mesh.hasVertexAlpha) {
+                        this._defines.VERTEXALPHA = true;
+                    }
+                }
+                if (mesh.useBones && mesh.computeBonesUsingShaders) {
+                    this._defines.BONES = true;
+                    this._defines.BonesPerMesh = (mesh.skeleton.bones.length + 1);
+                    this._defines.BONES4 = true;
+                }
+
+                // Instances
+                if (useInstances) {
+                    this._defines.INSTANCES = true;
+                }
+            }
+
+            // Get correct effect      
+            if (!this._defines.isEqual(this._cachedDefines)) {
+                this._defines.cloneTo(this._cachedDefines);
+
+                scene.resetCachedMaterial();
+
+                // Fallbacks
+                var fallbacks = new EffectFallbacks();             
+                if (this._defines.FOG) {
+                    fallbacks.addFallback(1, "FOG");
+                }
+
+                for (lightIndex = 0; lightIndex < maxSimultaneousLights; lightIndex++) {
+                    if (!this._defines["LIGHT" + lightIndex]) {
+                        continue;
+                    }
+
+                    if (lightIndex > 0) {
+                        fallbacks.addFallback(lightIndex, "LIGHT" + lightIndex);
+                    }
+
+                    if (this._defines["SHADOW" + lightIndex]) {
+                        fallbacks.addFallback(0, "SHADOW" + lightIndex);
+                    }
+
+                    if (this._defines["SHADOWPCF" + lightIndex]) {
+                        fallbacks.addFallback(0, "SHADOWPCF" + lightIndex);
+                    }
+
+                    if (this._defines["SHADOWVSM" + lightIndex]) {
+                        fallbacks.addFallback(0, "SHADOWVSM" + lightIndex);
+                    }
+                }
+             
+                if (this._defines.BONES4) {
+                    fallbacks.addFallback(0, "BONES4");
+                }
+
+                //Attributes
+                var attribs = [VertexBuffer.PositionKind];
+
+                if (this._defines.NORMAL) {
+                    attribs.push(VertexBuffer.NormalKind);
+                }
+
+                if (this._defines.UV1) {
+                    attribs.push(VertexBuffer.UVKind);
+                }
+
+                if (this._defines.UV2) {
+                    attribs.push(VertexBuffer.UV2Kind);
+                }
+
+                if (this._defines.VERTEXCOLOR) {
+                    attribs.push(VertexBuffer.ColorKind);
+                }
+
+                if (this._defines.BONES) {
+                    attribs.push(VertexBuffer.MatricesIndicesKind);
+                    attribs.push(VertexBuffer.MatricesWeightsKind);
+                }
+
+                if (this._defines.INSTANCES) {
+                    attribs.push("world0");
+                    attribs.push("world1");
+                    attribs.push("world2");
+                    attribs.push("world3");
+                }
+
+                // Legacy browser patch
+                var shaderName = "default";
+                if (!scene.getEngine().getCaps().standardDerivatives) {
+                    shaderName = "legacydefault";
+                }
+                var join = this._defines.toString();
+                this._effect = scene.getEngine().createEffect(shaderName,
+                    attribs,
+                    ["world", "view", "viewProjection", "vEyePosition", "vLightsType", "vDiffuseColor",
+                        "vLightData0", "vLightDiffuse0", "vLightSpecular0", "vLightDirection0", "vLightGround0", "lightMatrix0",
+                        "vLightData1", "vLightDiffuse1", "vLightSpecular1", "vLightDirection1", "vLightGround1", "lightMatrix1",
+                        "vLightData2", "vLightDiffuse2", "vLightSpecular2", "vLightDirection2", "vLightGround2", "lightMatrix2",
+                        "vLightData3", "vLightDiffuse3", "vLightSpecular3", "vLightDirection3", "vLightGround3", "lightMatrix3",
+                        "vFogInfos", "vFogColor", "pointSize",
+                        "vDiffuseInfos", 
+                        "mBones",
+                        "vClipPlane", "diffuseMatrix",
+                        "shadowsInfo0", "shadowsInfo1", "shadowsInfo2", "shadowsInfo3"
+                    ],
+                    ["diffuseSampler",
+                        "shadowSampler0", "shadowSampler1", "shadowSampler2", "shadowSampler3"
+                    ],
+                    join, fallbacks, this.onCompiled, this.onError);
+            }
+            if (!this._effect.isReady()) {
+                return false;
+            }
+
+            this._renderId = scene.getRenderId();
+            this._wasPreviouslyReady = true;
+
+            if (mesh) {
+                if (!mesh._materialDefines) {
+                    mesh._materialDefines = new SimpleMaterialDefines();
+                }
+
+                this._defines.cloneTo(mesh._materialDefines);
+            }
+
+            return true;
+        }
+
+        public bindOnlyWorldMatrix(world: Matrix): void {
+            this._effect.setMatrix("world", world);
+        }
+
+        public bind(world: Matrix, mesh?: Mesh): void {
+            var scene = this.getScene();
+
+            // Matrices        
+            this.bindOnlyWorldMatrix(world);
+            this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
+
+            // Bones
+            if (mesh && mesh.useBones && mesh.computeBonesUsingShaders) {
+                this._effect.setMatrices("mBones", mesh.skeleton.getTransformMatrices());
+            }
+
+            if (scene.getCachedMaterial() !== this) {
+                // Textures        
+                if (this.diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {
+                    this._effect.setTexture("diffuseSampler", this.diffuseTexture);
+
+                    this._effect.setFloat2("vDiffuseInfos", this.diffuseTexture.coordinatesIndex, this.diffuseTexture.level);
+                    this._effect.setMatrix("diffuseMatrix", this.diffuseTexture.getTextureMatrix());
+                }
+                // Clip plane
+                if (scene.clipPlane) {
+                    var clipPlane = scene.clipPlane;
+                    this._effect.setFloat4("vClipPlane", clipPlane.normal.x, clipPlane.normal.y, clipPlane.normal.z, clipPlane.d);
+                }
+
+                // Point size
+                if (this.pointsCloud) {
+                    this._effect.setFloat("pointSize", this.pointSize);
+                }
+
+                this._effect.setVector3("vEyePosition", scene._mirroredCameraPosition ? scene._mirroredCameraPosition : scene.activeCamera.position);                
+            }
+
+            this._effect.setColor4("vDiffuseColor", this._scaledDiffuse, this.alpha * mesh.visibility);
+
+            if (scene.lightsEnabled && !this.disableLighting) {
+                var lightIndex = 0;
+                for (var index = 0; index < scene.lights.length; index++) {
+                    var light = scene.lights[index];
+
+                    if (!light.isEnabled()) {
+                        continue;
+                    }
+
+                    if (!light.canAffectMesh(mesh)) {
+                        continue;
+                    }
+
+                    if (light instanceof PointLight) {
+                        // Point Light
+                        light.transferToEffect(this._effect, "vLightData" + lightIndex);
+                    } else if (light instanceof DirectionalLight) {
+                        // Directional Light
+                        light.transferToEffect(this._effect, "vLightData" + lightIndex);
+                    } else if (light instanceof SpotLight) {
+                        // Spot Light
+                        light.transferToEffect(this._effect, "vLightData" + lightIndex, "vLightDirection" + lightIndex);
+                    } else if (light instanceof HemisphericLight) {
+                        // Hemispheric Light
+                        light.transferToEffect(this._effect, "vLightData" + lightIndex, "vLightGround" + lightIndex);
+                    }
+
+                    light.diffuse.scaleToRef(light.intensity, this._scaledDiffuse);
+                    this._effect.setColor4("vLightDiffuse" + lightIndex, this._scaledDiffuse, light.range);
+
+                    // Shadows
+                    if (scene.shadowsEnabled) {
+                        var shadowGenerator = light.getShadowGenerator();
+                        if (mesh.receiveShadows && shadowGenerator) {
+                            this._effect.setMatrix("lightMatrix" + lightIndex, shadowGenerator.getTransformMatrix());
+                            this._effect.setTexture("shadowSampler" + lightIndex, shadowGenerator.getShadowMapForRendering());
+                            this._effect.setFloat3("shadowsInfo" + lightIndex, shadowGenerator.getDarkness(), shadowGenerator.getShadowMap().getSize().width, shadowGenerator.bias);
+                        }
+                    }
+
+                    lightIndex++;
+
+                    if (lightIndex === maxSimultaneousLights)
+                        break;
+                }
+            }
+
+            // View
+            if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) {
+                this._effect.setMatrix("view", scene.getViewMatrix());
+            }
+
+            // Fog
+            if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== Scene.FOGMODE_NONE) {
+                this._effect.setFloat4("vFogInfos", scene.fogMode, scene.fogStart, scene.fogEnd, scene.fogDensity);
+                this._effect.setColor3("vFogColor", scene.fogColor);
+            }
+
+            super.bind(world, mesh);
+        }
+
+        public getAnimatables(): IAnimatable[] {
+            var results = [];
+
+            if (this.diffuseTexture && this.diffuseTexture.animations && this.diffuseTexture.animations.length > 0) {
+                results.push(this.diffuseTexture);
+            }
+
+            return results;
+        }
+
+        public dispose(forceDisposeEffect?: boolean): void {
+            if (this.diffuseTexture) {
+                this.diffuseTexture.dispose();
+            }
+
+            super.dispose(forceDisposeEffect);
+        }
+
+        public clone(name: string): SimpleMaterial {
+            var newStandardMaterial = new SimpleMaterial(name, this.getScene());
+
+            // Base material
+            this.copyTo(newStandardMaterial);
+
+            // Simple material
+            if (this.diffuseTexture && this.diffuseTexture.clone) {
+                newStandardMaterial.diffuseTexture = this.diffuseTexture.clone();
+            }
+
+            newStandardMaterial.diffuseColor = this.diffuseColor.clone();
+            return newStandardMaterial;
+        }
+    }
+} 
+

+ 461 - 0
shadersLibrary/shaders/simple/simple.fragment.fx

@@ -0,0 +1,461 @@
+precision highp float;
+
+// Constants
+uniform vec3 vEyePosition;
+uniform vec4 vDiffuseColor;
+
+// Input
+varying vec3 vPositionW;
+
+#ifdef NORMAL
+varying vec3 vNormalW;
+#endif
+
+#ifdef VERTEXCOLOR
+varying vec4 vColor;
+#endif
+
+// Lights
+#ifdef LIGHT0
+uniform vec4 vLightData0;
+uniform vec4 vLightDiffuse0;
+#ifdef SHADOW0
+varying vec4 vPositionFromLight0;
+uniform sampler2D shadowSampler0;
+uniform vec3 shadowsInfo0;
+#endif
+#ifdef SPOTLIGHT0
+uniform vec4 vLightDirection0;
+#endif
+#ifdef HEMILIGHT0
+uniform vec3 vLightGround0;
+#endif
+#endif
+
+#ifdef LIGHT1
+uniform vec4 vLightData1;
+uniform vec4 vLightDiffuse1;
+#ifdef SHADOW1
+varying vec4 vPositionFromLight1;
+uniform sampler2D shadowSampler1;
+uniform vec3 shadowsInfo1;
+#endif
+#ifdef SPOTLIGHT1
+uniform vec4 vLightDirection1;
+#endif
+#ifdef HEMILIGHT1
+uniform vec3 vLightGround1;
+#endif
+#endif
+
+#ifdef LIGHT2
+uniform vec4 vLightData2;
+uniform vec4 vLightDiffuse2;
+#ifdef SHADOW2
+varying vec4 vPositionFromLight2;
+uniform sampler2D shadowSampler2;
+uniform vec3 shadowsInfo2;
+#endif
+#ifdef SPOTLIGHT2
+uniform vec4 vLightDirection2;
+#endif
+#ifdef HEMILIGHT2
+uniform vec3 vLightGround2;
+#endif
+#endif
+
+#ifdef LIGHT3
+uniform vec4 vLightData3;
+uniform vec4 vLightDiffuse3;
+#ifdef SHADOW3
+varying vec4 vPositionFromLight3;
+uniform sampler2D shadowSampler3;
+uniform vec3 shadowsInfo3;
+#endif
+#ifdef SPOTLIGHT3
+uniform vec4 vLightDirection3;
+#endif
+#ifdef HEMILIGHT3
+uniform vec3 vLightGround3;
+#endif
+#endif
+
+// Samplers
+#ifdef DIFFUSE
+varying vec2 vDiffuseUV;
+uniform sampler2D diffuseSampler;
+uniform vec2 vDiffuseInfos;
+#endif
+
+// Shadows
+#ifdef SHADOWS
+
+float unpack(vec4 color)
+{
+	const vec4 bit_shift = vec4(1.0 / (255.0 * 255.0 * 255.0), 1.0 / (255.0 * 255.0), 1.0 / 255.0, 1.0);
+	return dot(color, bit_shift);
+}
+
+float unpackHalf(vec2 color)
+{
+	return color.x + (color.y / 255.0);
+}
+
+float computeShadow(vec4 vPositionFromLight, sampler2D shadowSampler, float darkness, float bias)
+{
+	vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
+	depth = 0.5 * depth + vec3(0.5);
+	vec2 uv = depth.xy;
+
+	if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)
+	{
+		return 1.0;
+	}
+
+	float shadow = unpack(texture2D(shadowSampler, uv)) + bias;
+
+	if (depth.z > shadow)
+	{
+		return darkness;
+	}
+	return 1.;
+}
+
+float computeShadowWithPCF(vec4 vPositionFromLight, sampler2D shadowSampler, float mapSize, float bias, float darkness)
+{
+	vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
+	depth = 0.5 * depth + vec3(0.5);
+	vec2 uv = depth.xy;
+
+	if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)
+	{
+		return 1.0;
+	}
+
+	float visibility = 1.;
+
+	vec2 poissonDisk[4];
+	poissonDisk[0] = vec2(-0.94201624, -0.39906216);
+	poissonDisk[1] = vec2(0.94558609, -0.76890725);
+	poissonDisk[2] = vec2(-0.094184101, -0.92938870);
+	poissonDisk[3] = vec2(0.34495938, 0.29387760);
+
+	// Poisson Sampling
+	float biasedDepth = depth.z - bias;
+
+	if (unpack(texture2D(shadowSampler, uv + poissonDisk[0] / mapSize)) < biasedDepth) visibility -= 0.25;
+	if (unpack(texture2D(shadowSampler, uv + poissonDisk[1] / mapSize)) < biasedDepth) visibility -= 0.25;
+	if (unpack(texture2D(shadowSampler, uv + poissonDisk[2] / mapSize)) < biasedDepth) visibility -= 0.25;
+	if (unpack(texture2D(shadowSampler, uv + poissonDisk[3] / mapSize)) < biasedDepth) visibility -= 0.25;
+
+	return  min(1.0, visibility + darkness);
+}
+
+// Thanks to http://devmaster.net/
+float linstep(float low, float high, float v) {
+	return clamp((v - low) / (high - low), 0.0, 1.0);
+}
+
+float ChebychevInequality(vec2 moments, float compare, float bias)
+{
+	float p = smoothstep(compare - bias, compare, moments.x);
+	float variance = max(moments.y - moments.x * moments.x, 0.02);
+	float d = compare - moments.x;
+	float p_max = linstep(0.2, 1.0, variance / (variance + d * d));
+
+	return clamp(max(p, p_max), 0.0, 1.0);
+}
+
+float computeShadowWithVSM(vec4 vPositionFromLight, sampler2D shadowSampler, float bias, float darkness)
+{
+	vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
+	depth = 0.5 * depth + vec3(0.5);
+	vec2 uv = depth.xy;
+
+	if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0 || depth.z >= 1.0)
+	{
+		return 1.0;
+	}
+
+	vec4 texel = texture2D(shadowSampler, uv);
+
+	vec2 moments = vec2(unpackHalf(texel.xy), unpackHalf(texel.zw));
+	return min(1.0, 1.0 - ChebychevInequality(moments, depth.z, bias) + darkness);
+}
+#endif
+
+#ifdef CLIPPLANE
+varying float fClipDistance;
+#endif
+
+// Fog
+#ifdef FOG
+
+#define FOGMODE_NONE    0.
+#define FOGMODE_EXP     1.
+#define FOGMODE_EXP2    2.
+#define FOGMODE_LINEAR  3.
+#define E 2.71828
+
+uniform vec4 vFogInfos;
+uniform vec3 vFogColor;
+varying float fFogDistance;
+
+float CalcFogFactor()
+{
+	float fogCoeff = 1.0;
+	float fogStart = vFogInfos.y;
+	float fogEnd = vFogInfos.z;
+	float fogDensity = vFogInfos.w;
+
+	if (FOGMODE_LINEAR == vFogInfos.x)
+	{
+		fogCoeff = (fogEnd - fFogDistance) / (fogEnd - fogStart);
+	}
+	else if (FOGMODE_EXP == vFogInfos.x)
+	{
+		fogCoeff = 1.0 / pow(E, fFogDistance * fogDensity);
+	}
+	else if (FOGMODE_EXP2 == vFogInfos.x)
+	{
+		fogCoeff = 1.0 / pow(E, fFogDistance * fFogDistance * fogDensity * fogDensity);
+	}
+
+	return clamp(fogCoeff, 0.0, 1.0);
+}
+#endif
+
+// Light Computing
+struct lightingInfo
+{
+	vec3 diffuse;
+};
+
+lightingInfo computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, float range) {
+	lightingInfo result;
+
+	vec3 lightVectorW;
+	float attenuation = 1.0;
+	if (lightData.w == 0.)
+	{
+		vec3 direction = lightData.xyz - vPositionW;
+
+		attenuation = max(0., 1.0 - length(direction) / range);
+		lightVectorW = normalize(direction);
+	}
+	else
+	{
+		lightVectorW = normalize(-lightData.xyz);
+	}
+
+	// diffuse
+	float ndl = max(0., dot(vNormal, lightVectorW));
+	result.diffuse = ndl * diffuseColor * attenuation;
+
+	return result;
+}
+
+lightingInfo computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec4 lightDirection, vec3 diffuseColor, float range) {
+	lightingInfo result;
+
+	vec3 direction = lightData.xyz - vPositionW;
+	vec3 lightVectorW = normalize(direction);
+	float attenuation = max(0., 1.0 - length(direction) / range);
+
+	// diffuse
+	float cosAngle = max(0., dot(-lightDirection.xyz, lightVectorW));
+	float spotAtten = 0.0;
+
+	if (cosAngle >= lightDirection.w)
+	{
+		cosAngle = max(0., pow(cosAngle, lightData.w));
+		spotAtten = clamp((cosAngle - lightDirection.w) / (1. - cosAngle), 0.0, 1.0);
+
+		// Diffuse
+		float ndl = max(0., dot(vNormal, -lightDirection.xyz));
+		result.diffuse = ndl * spotAtten * diffuseColor * attenuation;
+
+		return result;
+	}
+
+	result.diffuse = vec3(0.);
+
+	return result;
+}
+
+lightingInfo computeHemisphericLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 groundColor) {
+	lightingInfo result;
+
+	// Diffuse
+	float ndl = dot(vNormal, lightData.xyz) * 0.5 + 0.5;
+	result.diffuse = mix(groundColor, diffuseColor, ndl);
+
+	return result;
+}
+
+void main(void) {
+	// Clip plane
+#ifdef CLIPPLANE
+	if (fClipDistance > 0.0)
+		discard;
+#endif
+
+	vec3 viewDirectionW = normalize(vEyePosition - vPositionW);
+
+	// Base color
+	vec4 baseColor = vec4(1., 1., 1., 1.);
+	vec3 diffuseColor = vDiffuseColor.rgb;
+
+	// Alpha
+	float alpha = vDiffuseColor.a;
+
+#ifdef DIFFUSE
+	baseColor = texture2D(diffuseSampler, vDiffuseUV);
+
+#ifdef ALPHATEST
+	if (baseColor.a < 0.4)
+		discard;
+#endif
+
+	baseColor.rgb *= vDiffuseInfos.y;
+#endif
+
+#ifdef VERTEXCOLOR
+	baseColor.rgb *= vColor.rgb;
+#endif
+
+	// Bump
+#ifdef NORMAL
+	vec3 normalW = normalize(vNormalW);
+#else
+	vec3 normalW = vec3(1.0, 1.0, 1.0);
+#endif
+
+	// Lighting
+	vec3 diffuseBase = vec3(0., 0., 0.);
+	float shadow = 1.;
+
+#ifdef LIGHT0
+#ifdef SPOTLIGHT0
+	lightingInfo info = computeSpotLighting(viewDirectionW, normalW, vLightData0, vLightDirection0, vLightDiffuse0.rgb, vLightDiffuse0.a);
+#endif
+#ifdef HEMILIGHT0
+	lightingInfo info = computeHemisphericLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0.rgb, vLightGround0);
+#endif
+#ifdef POINTDIRLIGHT0
+	lightingInfo info = computeLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0.rgb, vLightDiffuse0.a);
+#endif
+#ifdef SHADOW0
+#ifdef SHADOWVSM0
+	shadow = computeShadowWithVSM(vPositionFromLight0, shadowSampler0, shadowsInfo0.z, shadowsInfo0.x);
+#else
+#ifdef SHADOWPCF0
+	shadow = computeShadowWithPCF(vPositionFromLight0, shadowSampler0, shadowsInfo0.y, shadowsInfo0.z, shadowsInfo0.x);
+#else
+	shadow = computeShadow(vPositionFromLight0, shadowSampler0, shadowsInfo0.x, shadowsInfo0.z);
+#endif
+#endif
+#else
+	shadow = 1.;
+#endif
+	diffuseBase += info.diffuse * shadow;
+#endif
+
+#ifdef LIGHT1
+
+#ifdef SPOTLIGHT1
+	info = computeSpotLighting(viewDirectionW, normalW, vLightData1, vLightDirection1, vLightDiffuse1.rgb, vLightDiffuse1.a);
+#endif
+#ifdef HEMILIGHT1
+	info = computeHemisphericLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1.rgb, vLightGround1);
+#endif
+#ifdef POINTDIRLIGHT1
+	info = computeLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1.rgb, vLightDiffuse1.a);
+#endif
+#ifdef SHADOW1
+#ifdef SHADOWVSM1
+	shadow = computeShadowWithVSM(vPositionFromLight1, shadowSampler1, shadowsInfo1.z, shadowsInfo1.x);
+#else
+#ifdef SHADOWPCF1
+	shadow = computeShadowWithPCF(vPositionFromLight1, shadowSampler1, shadowsInfo1.y, shadowsInfo1.z, shadowsInfo1.x);
+#else
+	shadow = computeShadow(vPositionFromLight1, shadowSampler1, shadowsInfo1.x, shadowsInfo1.z);
+#endif
+#endif
+#else
+	shadow = 1.;
+#endif
+	diffuseBase += info.diffuse * shadow;
+
+#endif
+
+#ifdef LIGHT2
+#ifdef SPOTLIGHT2
+	info = computeSpotLighting(viewDirectionW, normalW, vLightData2, vLightDirection2, vLightDiffuse2.rgb, vLightDiffuse2.a);
+#endif
+#ifdef HEMILIGHT2
+	info = computeHemisphericLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2.rgb, vLightGround2);
+#endif
+#ifdef POINTDIRLIGHT2
+	info = computeLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2.rgb, vLightDiffuse2.a);
+#endif
+#ifdef SHADOW2
+#ifdef SHADOWVSM2
+	shadow = computeShadowWithVSM(vPositionFromLight2, shadowSampler2, shadowsInfo2.z, shadowsInfo2.x);
+#else
+#ifdef SHADOWPCF2
+	shadow = computeShadowWithPCF(vPositionFromLight2, shadowSampler2, shadowsInfo2.y, shadowsInfo2.z, shadowsInfo2.x);
+#else
+	shadow = computeShadow(vPositionFromLight2, shadowSampler2, shadowsInfo2.x, shadowsInfo2.z);
+#endif	
+#endif	
+#else
+	shadow = 1.;
+#endif
+	diffuseBase += info.diffuse * shadow;
+
+#endif
+
+#ifdef LIGHT3
+
+#ifdef SPOTLIGHT3
+	info = computeSpotLighting(viewDirectionW, normalW, vLightData3, vLightDirection3, vLightDiffuse3.rgb, vLightDiffuse3.a);
+#endif
+#ifdef HEMILIGHT3
+	info = computeHemisphericLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3.rgb, vLightGround3);
+#endif
+#ifdef POINTDIRLIGHT3
+	info = computeLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3.rgb, vLightDiffuse3.a);
+#endif
+#ifdef SHADOW3
+#ifdef SHADOWVSM3
+	shadow = computeShadowWithVSM(vPositionFromLight3, shadowSampler3, shadowsInfo3.z, shadowsInfo3.x);
+#else
+#ifdef SHADOWPCF3
+	shadow = computeShadowWithPCF(vPositionFromLight3, shadowSampler3, shadowsInfo3.y, shadowsInfo3.z, shadowsInfo3.x);
+#else
+	shadow = computeShadow(vPositionFromLight3, shadowSampler3, shadowsInfo3.x, shadowsInfo3.z);
+#endif	
+#endif	
+#else
+	shadow = 1.;
+#endif
+	diffuseBase += info.diffuse * shadow;
+#endif
+
+#ifdef VERTEXALPHA
+	alpha *= vColor.a;
+#endif
+
+	vec3 finalDiffuse = clamp(diffuseBase * diffuseColor, 0.0, 1.0) * baseColor.rgb;
+
+	// Composition
+	vec4 color = vec4(finalDiffuse * baseAmbientColor + finalSpecular + reflectionColor, alpha);
+
+#ifdef FOG
+	float fog = CalcFogFactor();
+	color.rgb = fog * color.rgb + (1.0 - fog) * vFogColor;
+#endif
+
+	gl_FragColor = color;
+}

+ 179 - 0
shadersLibrary/shaders/simple/simple.vertex.fx

@@ -0,0 +1,179 @@
+precision highp float;
+
+// Attributes
+attribute vec3 position;
+#ifdef NORMAL
+attribute vec3 normal;
+#endif
+#ifdef UV1
+attribute vec2 uv;
+#endif
+#ifdef UV2
+attribute vec2 uv2;
+#endif
+#ifdef VERTEXCOLOR
+attribute vec4 color;
+#endif
+#ifdef BONES
+attribute vec4 matricesIndices;
+attribute vec4 matricesWeights;
+#endif
+
+// Uniforms
+
+#ifdef INSTANCES
+attribute vec4 world0;
+attribute vec4 world1;
+attribute vec4 world2;
+attribute vec4 world3;
+#else
+uniform mat4 world;
+#endif
+
+uniform mat4 view;
+uniform mat4 viewProjection;
+
+#ifdef DIFFUSE
+varying vec2 vDiffuseUV;
+uniform mat4 diffuseMatrix;
+uniform vec2 vDiffuseInfos;
+#endif
+
+#ifdef BUMP
+varying vec2 vBumpUV;
+uniform vec2 vBumpInfos;
+uniform mat4 bumpMatrix;
+#endif
+
+#ifdef BONES
+uniform mat4 mBones[BonesPerMesh];
+#endif
+
+#ifdef POINTSIZE
+uniform float pointSize;
+#endif
+
+// Output
+varying vec3 vPositionW;
+#ifdef NORMAL
+varying vec3 vNormalW;
+#endif
+
+#ifdef VERTEXCOLOR
+varying vec4 vColor;
+#endif
+
+#ifdef CLIPPLANE
+uniform vec4 vClipPlane;
+varying float fClipDistance;
+#endif
+
+#ifdef FOG
+varying float fFogDistance;
+#endif
+
+#ifdef SHADOWS
+#ifdef LIGHT0
+uniform mat4 lightMatrix0;
+varying vec4 vPositionFromLight0;
+#endif
+#ifdef LIGHT1
+uniform mat4 lightMatrix1;
+varying vec4 vPositionFromLight1;
+#endif
+#ifdef LIGHT2
+uniform mat4 lightMatrix2;
+varying vec4 vPositionFromLight2;
+#endif
+#ifdef LIGHT3
+uniform mat4 lightMatrix3;
+varying vec4 vPositionFromLight3;
+#endif
+#endif
+
+void main(void) {
+	mat4 finalWorld;
+
+#ifdef INSTANCES
+	finalWorld = mat4(world0, world1, world2, world3);
+#else
+	finalWorld = world;
+#endif
+
+#ifdef BONES
+	mat4 m0 = mBones[int(matricesIndices.x)] * matricesWeights.x;
+	mat4 m1 = mBones[int(matricesIndices.y)] * matricesWeights.y;
+	mat4 m2 = mBones[int(matricesIndices.z)] * matricesWeights.z;
+
+#ifdef BONES4
+	mat4 m3 = mBones[int(matricesIndices.w)] * matricesWeights.w;
+	finalWorld = finalWorld * (m0 + m1 + m2 + m3);
+#else
+	finalWorld = finalWorld * (m0 + m1 + m2);
+#endif 
+
+#endif
+	gl_Position = viewProjection * finalWorld * vec4(position, 1.0);
+
+	vec4 worldPos = finalWorld * vec4(position, 1.0);
+	vPositionW = vec3(worldPos);
+
+#ifdef NORMAL
+	vNormalW = normalize(vec3(finalWorld * vec4(normal, 0.0)));
+#endif
+
+	// Texture coordinates
+#ifndef UV1
+	vec2 uv = vec2(0., 0.);
+#endif
+#ifndef UV2
+	vec2 uv2 = vec2(0., 0.);
+#endif
+
+#ifdef DIFFUSE
+	if (vDiffuseInfos.x == 0.)
+	{
+		vDiffuseUV = vec2(diffuseMatrix * vec4(uv, 1.0, 0.0));
+	}
+	else
+	{
+		vDiffuseUV = vec2(diffuseMatrix * vec4(uv2, 1.0, 0.0));
+	}
+#endif
+
+	// Clip plane
+#ifdef CLIPPLANE
+	fClipDistance = dot(worldPos, vClipPlane);
+#endif
+
+	// Fog
+#ifdef FOG
+	fFogDistance = (view * worldPos).z;
+#endif
+
+	// Shadows
+#ifdef SHADOWS
+#ifdef LIGHT0
+	vPositionFromLight0 = lightMatrix0 * worldPos;
+#endif
+#ifdef LIGHT1
+	vPositionFromLight1 = lightMatrix1 * worldPos;
+#endif
+#ifdef LIGHT2
+	vPositionFromLight2 = lightMatrix2 * worldPos;
+#endif
+#ifdef LIGHT3
+	vPositionFromLight3 = lightMatrix3 * worldPos;
+#endif
+#endif
+
+	// Vertex color
+#ifdef VERTEXCOLOR
+	vColor = color;
+#endif
+
+	// Point size
+#ifdef POINTSIZE
+	gl_PointSize = pointSize;
+#endif
+}

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 95 - 0
shadersLibrary/test/dat.gui.min.js


+ 199 - 0
shadersLibrary/test/index.html

@@ -0,0 +1,199 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<title>Shaders Library</title>
+	<script src="dat.gui.min.js"></script>
+	<script src="../../babylon.max.js"></script>
+	<script src="../dist/babylon.simpleMaterial.js"></script>
+
+	<style>
+		html, body {
+			width: 100%;
+			height: 100%;
+			padding: 0;
+			margin: 0;
+			overflow: hidden;
+		}
+
+		#renderCanvas {
+			width: 100%;
+			height: 100%;
+		}
+
+		#fps {
+			position: absolute;
+			background-color: black;
+			border: 2px solid red;
+			text-align: center;
+			font-size: 16px;
+			color: white;
+			top: 15px;
+			left: 10px;
+			width: 60px;
+			height: 20px;
+		}
+	</style>
+</head>
+<body>
+	<div id="fps">0</div>
+	<canvas id="renderCanvas"></canvas>
+
+	<script>
+		if (BABYLON.Engine.isSupported()) {
+			var canvas = document.getElementById("renderCanvas");
+			var engine = new BABYLON.Engine(canvas, true);
+			var divFps = document.getElementById("fps");
+
+			var scene = new BABYLON.Scene(engine);
+
+			var camera = new BABYLON.ArcRotateCamera("Camera", Math.PI / 2, Math.PI / 6, 50, BABYLON.Vector3.Zero(), scene);
+			camera.attachControl(canvas, true);
+
+			// Lights
+			var hemisphericLight = new BABYLON.HemisphericLight("hemi", new BABYLON.Vector3(0, 1, 0), scene);
+			var pointLight = new BABYLON.PointLight("point", new BABYLON.Vector3(100, 100, 10), scene);
+			pointLight.setEnabled(false);
+			var directionalLight = new BABYLON.DirectionalLight("directional", new BABYLON.Vector3(1, 0.2, 0), scene);
+			directionalLight.setEnabled(false);
+			var spotLight = new BABYLON.SpotLight("spot", new BABYLON.Vector3(0, -30, 0), new BABYLON.Vector3(0, 1, 0), 1.1, 1, scene);
+			spotLight.setEnabled(false);
+
+			// Create meshes
+			var sphere = BABYLON.Mesh.CreateSphere("sphere", 32, 30.0, scene);
+			var plane = BABYLON.MeshBuilder.CreateBox("plane", { width: 30, height: 1, depth:30 }, scene);
+			plane.setEnabled(false);
+
+			var currentMesh = sphere;
+
+			// Rabbit
+			var rabbit;
+			BABYLON.SceneLoader.ImportMesh("Rabbit", "meshes/", "Rabbit.babylon", scene, function (newMeshes, particleSystems, skeletons) {
+				rabbit = newMeshes[1];
+				rabbit.setEnabled(false);
+				rabbit.scaling = new BABYLON.Vector3(0.4, 0.4, 0.4);
+				scene.beginAnimation(skeletons[0], 0, 100, true, 0.8);
+
+				// Shadow caster
+				var shadowCaster = BABYLON.Mesh.CreateTorus("torus", 4, 2, 30, scene, false);
+				shadowCaster.setEnabled(false);
+				shadowCaster.position = new BABYLON.Vector3(-20, -10, 0);
+
+				var shadowGenerator = new BABYLON.ShadowGenerator(1024, directionalLight);
+				shadowGenerator.getShadowMap().renderList.push(shadowCaster);
+				shadowGenerator.usePoissonSampling = true;
+
+				// Register a render loop to repeatedly render the scene
+				var angle = 0;
+				engine.runRenderLoop(function () {
+					scene.render();
+					divFps.innerHTML = engine.getFps().toFixed() + " fps";
+
+					shadowCaster.position.x = 20 * Math.sin(angle);
+					shadowCaster.position.y = 20 * Math.cos(angle);
+					shadowCaster.position.z = 20 * Math.cos(angle);
+
+					shadowCaster.rotation.x += 0.01;
+					shadowCaster.rotation.y += 0.01;
+
+					angle += 0.01;
+				});
+
+				// Resize
+				window.addEventListener("resize", function () {
+					engine.resize();
+				});
+
+				// Fog
+				scene.fogMode = BABYLON.Scene.FOGMODE_NONE;
+				scene.fogDensity = 0.01;
+
+				// Create shaders
+				var std = new BABYLON.StandardMaterial("std", scene);
+				std.diffuseTexture = new BABYLON.Texture("textures/amiga.jpg", scene);
+				std.diffuseTexture.uScale = 5;
+				std.diffuseTexture.vScale = 5;
+
+				var simple = new BABYLON.SimpleMaterial("simple", scene);
+				simple.diffuseTexture = new BABYLON.Texture("textures/amiga.jpg", scene);
+				simple.diffuseTexture.uScale = 5;
+				simple.diffuseTexture.vScale = 5;
+
+				// Default to std
+				var currentMaterial = std;
+				sphere.material = std;
+
+				//UI
+				var gui = new dat.GUI();
+				var options = {
+					shader: "standard",
+					mesh: "sphere",
+					hemisphericLight: true,
+					pointLight: false,
+					directionalLight: false,
+					castShadows: false,
+					spotLight: false,
+					fog: false
+				}
+
+				gui.add(options, 'shader', ['standard', 'simple']).onFinishChange(function () {
+					switch (options.shader) {
+						case "simple":
+							currentMaterial = simple;
+							break;
+						default:
+							currentMaterial = std;
+							break;
+					}
+
+					currentMesh.material = currentMaterial;
+				});
+
+				gui.add(options, 'mesh', ['sphere', 'plane', 'rabbit']).onFinishChange(function () {
+					currentMesh.setEnabled(false);
+					switch (options.mesh) {
+						case "sphere":
+							currentMesh = sphere;
+							break;
+						case "plane":
+							currentMesh = plane;
+							break;
+						case "rabbit":
+							currentMesh = rabbit;
+							break;
+					}
+					currentMesh.setEnabled(true);
+					currentMesh.material = currentMaterial;
+				});
+
+				gui.add(options, 'hemisphericLight').onChange(function () {
+					hemisphericLight.setEnabled(options.hemisphericLight);
+				});
+
+				gui.add(options, 'pointLight').onChange(function () {
+					pointLight.setEnabled(options.pointLight);
+				});
+
+				gui.add(options, 'spotLight').onChange(function () {
+					spotLight.setEnabled(options.spotLight);
+				});
+
+				var f1 = gui.addFolder('directionalLight');
+				f1.add(options, 'directionalLight').onChange(function () {
+					directionalLight.setEnabled(options.directionalLight);
+					shadowCaster.setEnabled(options.directionalLight && options.castShadows);
+				});
+
+				f1.add(options, 'castShadows').onChange(function () {
+					shadowCaster.setEnabled(options.directionalLight && options.castShadows);
+					currentMesh.receiveShadows = true;
+				});
+
+				gui.add(options, 'fog').onChange(function () {
+					scene.fogMode = options.fog ? BABYLON.Scene.FOGMODE_EXP : BABYLON.Scene.FOGMODE_NONE;
+				});
+			});
+		}
+
+	</script>
+</body>
+</html>

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 1 - 0
shadersLibrary/test/meshes/Rabbit.babylon


BIN
shadersLibrary/test/textures/amiga.jpg


+ 1 - 1
src/Cameras/babylon.arcRotateCamera.js

@@ -177,7 +177,7 @@ var BABYLON;
                     }
                     switch (pointers.count) {
                         case 1:
-                            if (this.panningSensibility !== 0 && ((_this._isCtrlPushed && useCtrlForPanning) || (!useCtrlForPanning && _this._isRightClick))) {
+                            if (_this.panningSensibility !== 0 && ((_this._isCtrlPushed && useCtrlForPanning) || (!useCtrlForPanning && _this._isRightClick))) {
                                 _this.inertialPanningX += -(evt.clientX - cacheSoloPointer.x) / _this.panningSensibility;
                                 _this.inertialPanningY += (evt.clientY - cacheSoloPointer.y) / _this.panningSensibility;
                             }

+ 3 - 2
src/Cameras/babylon.arcRotateCamera.ts

@@ -634,8 +634,8 @@
                 case Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_CROSSEYED:
                 case Camera.RIG_MODE_STEREOSCOPIC_OVERUNDER:
                 case Camera.RIG_MODE_VR:
-                    var camLeft = <ArcRotateCamera> this._rigCameras[0];
-                    var camRight = <ArcRotateCamera> this._rigCameras[1];
+                    var camLeft = <ArcRotateCamera>this._rigCameras[0];
+                    var camRight = <ArcRotateCamera>this._rigCameras[1];
                     camLeft.alpha = this.alpha - this._cameraRigParams.stereoHalfAngle;
                     camRight.alpha = this.alpha + this._cameraRigParams.stereoHalfAngle;
                     camLeft.beta = camRight.beta = this.beta;
@@ -647,3 +647,4 @@
     }
 } 
 
+

+ 2 - 1
src/Math/babylon.math.ts

@@ -1539,7 +1539,7 @@
 
             return this;
         }
-        
+
         public multiplyInPlace(q1: Quaternion): Quaternion {
             this.multiplyToRef(q1, this);
 
@@ -3548,3 +3548,4 @@
 }
 
 
+

+ 1 - 0
src/Mesh/babylon.abstractMesh.ts

@@ -1046,3 +1046,4 @@
 }
 
 
+

+ 5 - 4
src/Mesh/babylon.meshBuilder.ts

@@ -303,13 +303,13 @@
             var vertexData = VertexData.CreatePlane(options);
 
             vertexData.applyToMesh(plane, options.updatable);
-            
-            if(options.sourcePlane) {
+
+            if (options.sourcePlane) {
                 plane.translate(options.sourcePlane.normal, options.sourcePlane.d);
-                
+
                 var product = Math.acos(Vector3.Dot(options.sourcePlane.normal, Axis.Z));
                 var vectorProduct = Vector3.Cross(Axis.Z, options.sourcePlane.normal);
-                
+
                 plane.rotate(vectorProduct, product);
             }
 
@@ -793,3 +793,4 @@
     }
 }
 
+

+ 12 - 11
src/Physics/Plugins/babylon.cannonJSPlugin.ts

@@ -37,7 +37,7 @@
                 registeredMesh.mesh.position.z = bodyZ + registeredMesh.delta.z;
 
                 registeredMesh.mesh.rotationQuaternion.copyFrom(registeredMesh.body.quaternion);
-                if(registeredMesh.deltaRotation) {
+                if (registeredMesh.deltaRotation) {
                     registeredMesh.mesh.rotationQuaternion.multiplyInPlace(registeredMesh.deltaRotation);
                 }
             }
@@ -103,7 +103,7 @@
                 case PhysicsEngine.HeightmapImpostor:
                     returnValue = this._createHeightmap(mesh);
                     break;
-                    
+
             }
 
             mesh.rotationQuaternion = oldQuaternion;
@@ -133,7 +133,7 @@
 
             return shape;
         }
-        
+
         private _createHeightmap(mesh: AbstractMesh) {
             var pos = mesh.getVerticesData(BABYLON.VertexBuffer.PositionKind);
 
@@ -150,7 +150,7 @@
             //array size
             var arraySize = -1;
             for (var i = 0; i < pos.length; i = i + 3) {
-                if (pos[i+2] === pos[2]) {
+                if (pos[i + 2] === pos[2]) {
                     arraySize++;
                 } else {
                     break;
@@ -158,13 +158,13 @@
             }
 
             //calculate element size
-            var elementSize = dim * 2/ arraySize;
+            var elementSize = dim * 2 / arraySize;
             
             //calculate the matrix for cannon's heightfield
             for (var i = 0; i < pos.length; i = i + 3) {
-                var x = Math.round((pos[i + 0]) / elementSize + arraySize / 2 ) ;
-                var z = Math.round(((pos[i + 2]) / elementSize - arraySize / 2) * -1 ) ;
-                if(!matrix[x]) {
+                var x = Math.round((pos[i + 0]) / elementSize + arraySize / 2);
+                var z = Math.round(((pos[i + 2]) / elementSize - arraySize / 2) * -1);
+                if (!matrix[x]) {
                     matrix[x] = [];
                 }
                 matrix[x][z] = pos[i + 1];
@@ -176,7 +176,7 @@
             
             //For future reference, needed for body transformation
             shape.dim = dim;
-            
+
             return shape;
         }
 
@@ -327,8 +327,8 @@
                     body.position.set(center.x, center.y, center.z);
 
                     body.quaternion.copy(mesh.rotationQuaternion);
-                    
-                    if(registeredMesh.deltaRotation) {
+
+                    if (registeredMesh.deltaRotation) {
                         var tmpQ = new CANNON.Quaternion(-0.7071067811865475, 0, 0, 0.7071067811865475);
                         body.quaternion = body.quaternion.mult(tmpQ);
                     }
@@ -389,3 +389,4 @@
 }
 
 
+

+ 1 - 0
src/Physics/babylon.physicsEngine.ts

@@ -105,3 +105,4 @@
         public static Epsilon = 0.001;
     }
 }
+