Explorar o código

Added first PBR version to material library

David catuhe %!s(int64=9) %!d(string=hai) anos
pai
achega
b18667e152

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 18 - 18
dist/preview release/babylon.core.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 662 - 681
dist/preview release/babylon.d.ts


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 26 - 26
dist/preview release/babylon.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 25 - 226
dist/preview release/babylon.max.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 25 - 25
dist/preview release/babylon.noworker.js


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

@@ -6,6 +6,7 @@
       - Fire material: http://doc.babylonjs.com/extensions/fire ([julien-moreau](https://github.com/julien-moreau))
       - Normal material: http://doc.babylonjs.com/extensions/normal ([temechon](https://github.com/temechon))
       - Lava Material: http://doc.babylonjs.com/extensions/lava ([temechon](https://github.com/temechon))
+      - PBR Material: http://doc.babylonjs.com/extensions/pbr ([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` ([deltakosh](https://github.com/deltakosh))

+ 10 - 0
materialsLibrary/config.json

@@ -1,5 +1,15 @@
 {
   "materials": [
+     {
+      "file": "materials/pbr/babylon.pbrMaterial.ts",
+      "shaderFiles": [
+        "materials/pbr/pbr.vertex.fx",
+        "materials/pbr/pbr.fragment.fx",
+        "materials/pbr/legacypbr.vertex.fx",
+        "materials/pbr/legacypbr.fragment.fx"
+      ],
+      "output": "babylon.pbrMaterial.js"
+    },
     {
       "file": "materials/normal/babylon.normalMaterial.ts",
       "shaderFiles": [

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 905 - 0
materialsLibrary/dist/babylon.pbrMaterial.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 3 - 0
materialsLibrary/dist/babylon.pbrMaterial.min.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1 - 0
materialsLibrary/dist/babylon.terrainMaterial.min.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1106 - 0
materialsLibrary/materials/pbr/babylon.pbrMaterial.ts


+ 671 - 0
materialsLibrary/materials/pbr/legacypbr.fragment.fx

@@ -0,0 +1,671 @@
+precision mediump float;
+
+// Constants
+#define RECIPROCAL_PI2 0.15915494
+
+uniform vec3 vEyePosition;
+uniform vec3 vAmbientColor;
+uniform vec4 vDiffuseColor;
+
+// PBR CUSTOM CONTROLS
+uniform vec4 vPBRLightingIntensity;
+uniform vec4 vPBRShadowIntensity;
+uniform vec4 vPBRCameraInfos;
+
+uniform vec4 vPBROverloadedIntensity;
+uniform vec3 vPBROverloadedAmbient;
+uniform vec3 vPBROverloadedDiffuse;
+uniform vec3 vPBROverloadedSpecular;
+uniform vec3 vPBROverloadedEmissive;
+uniform vec3 vPBROverloadedSmoothness;
+
+// PBR CUSTOM CONSTANTS
+const float kPi = 3.1415926535897932384626433832795;
+
+// PBR HELPER METHODS
+float Square(float value)
+{
+    return value * value;
+}
+
+float getLuminance(vec3 color)
+{
+    return clamp(dot(color, vec3(0.2126, 0.7152, 0.0722)), 0., 1.);
+}
+
+float convertRoughnessToAverageSlope(float roughness)
+{
+    // Calculate AlphaG as square of roughness; add epsilon to avoid numerical issues
+    const float kMinimumVariance = 0.0005;
+    float alphaG = Square(roughness) + kMinimumVariance;
+    return alphaG;
+}
+
+// From Microfacet Models for Refraction through Rough Surfaces, Walter et al. 2007
+float smithVisibilityG1_TrowbridgeReitzGGX(float dot, float alphaG)
+{
+    float tanSquared = (1.0 - dot * dot) / (dot * dot);
+    return 2.0 / (1.0 + sqrt(1.0 + alphaG * alphaG * tanSquared));
+}
+
+float smithVisibilityG_TrowbridgeReitzGGX_Walter(float NdotL, float NdotV, float alphaG)
+{
+    return smithVisibilityG1_TrowbridgeReitzGGX(NdotL, alphaG) * smithVisibilityG1_TrowbridgeReitzGGX(NdotV, alphaG);
+}
+
+// Trowbridge-Reitz (GGX)
+// Generalised Trowbridge-Reitz with gamma power=2.0
+float normalDistributionFunction_TrowbridgeReitzGGX(float NdotH, float alphaG)
+{
+    // Note: alphaG is average slope (gradient) of the normals in slope-space.
+    // It is also the (trigonometric) tangent of the median distribution value, i.e. 50% of normals have
+    // a tangent (gradient) closer to the macrosurface than this slope.
+    float a2 = Square(alphaG);
+    float d = NdotH * NdotH * (a2 - 1.0) + 1.0;
+    return a2 / (kPi * d * d);
+}
+
+vec3 fresnelSchlickGGX(float VdotH, vec3 reflectance0, vec3 reflectance90)
+{
+    return reflectance0 + (reflectance90 - reflectance0) * pow(clamp(1.0 - VdotH, 0., 1.), 5.0);
+}
+
+// Cook Torance Specular computation.
+vec3 computeSpecularTerm(float NdotH, float NdotL, float NdotV, float VdotH, float roughness, vec3 specularColor)
+{
+    float alphaG = convertRoughnessToAverageSlope(roughness);
+    float distribution = normalDistributionFunction_TrowbridgeReitzGGX(NdotH, alphaG);
+    float visibility = smithVisibilityG_TrowbridgeReitzGGX_Walter(NdotL, NdotV, alphaG);
+    visibility /= (4.0 * NdotL * NdotV); // Cook Torance Denominator  integated in viibility to avoid issues when visibility function changes.
+
+    vec3 fresnel = fresnelSchlickGGX(VdotH, specularColor, vec3(1., 1., 1.));
+
+    float specTerm = max(0., visibility * distribution) * NdotL;
+    return fresnel * specTerm;
+}
+
+float computeDiffuseTerm(float NdotL, float NdotV, float VdotH, float roughness)
+{
+    // Diffuse fresnel falloff as per Disney principled BRDF, and in the spirit of
+    // of general coupled diffuse/specular models e.g. Ashikhmin Shirley.
+    float diffuseFresnelNV = pow(clamp(1.0 - NdotL, 0.000001, 1.), 5.0);
+    float diffuseFresnelNL = pow(clamp(1.0 - NdotV, 0.000001, 1.), 5.0);
+    float diffuseFresnel90 = 0.5 + 2.0 * VdotH * VdotH * roughness;
+    float diffuseFresnelTerm =
+        (1.0 + (diffuseFresnel90 - 1.0) * diffuseFresnelNL) *
+        (1.0 + (diffuseFresnel90 - 1.0) * diffuseFresnelNV);
+
+    return diffuseFresnelTerm * NdotL;
+}
+
+float computeDefaultGlossiness(float glossiness, vec3 specularColor)
+{
+    if (glossiness == 0.)
+    {
+        float kSpecularNoAlphaWorkflow_SmoothnessMax = 0.95;
+
+        float specularLuminance = getLuminance(specularColor);
+        float specularLuma = sqrt(specularLuminance);
+        glossiness = specularLuma * kSpecularNoAlphaWorkflow_SmoothnessMax;
+    }
+    return glossiness;
+}
+
+vec3 toLinearSpace(vec3 color)
+{
+    return vec3(pow(color.r, 2.2), pow(color.g, 2.2), pow(color.b, 2.2));
+}
+
+vec3 toGammaSpace(vec3 color)
+{
+    return vec3(pow(color.r, 1.0 / 2.2), pow(color.g, 1.0 / 2.2), pow(color.b, 1.0 / 2.2));
+}
+
+vec3 toneMaps(vec3 color)
+{
+    color = max(color, 0.0);
+
+    // TONE MAPPING / EXPOSURE
+    color.rgb = color.rgb * vPBRCameraInfos.x;
+
+    float tuning = 1.5; // TODO: sync up so e.g. 18% greys are matched to exposure appropriately
+    vec3 tonemapped = 1.0 - exp2(-color.rgb * tuning); // simple local photographic tonemapper
+    color.rgb = mix(color.rgb, tonemapped, 1.0);
+    return color;
+}
+
+vec4 contrasts(vec4 color)
+{
+    color = clamp(color, 0.0, 1.0);
+
+    vec3 resultHighContrast = color.rgb * color.rgb * (3.0 - 2.0 * color.rgb);
+    float contrast = vPBRCameraInfos.y;
+    if (contrast < 1.0)
+    {
+        // Decrease contrast: interpolate towards zero-contrast image (flat grey)
+        color.rgb = mix(vec3(0.5, 0.5, 0.5), color.rgb, contrast);
+    }
+    else
+    {
+        // Increase contrast: apply simple shoulder-toe high contrast curve
+        color.rgb = mix(color.rgb, resultHighContrast, contrast - 1.0);
+    }
+
+    return color;
+}
+// END PBR HELPER METHODS
+
+#ifdef SPECULARTERM
+uniform vec4 vSpecularColor;
+#endif
+uniform vec3 vEmissiveColor;
+
+// 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 SPECULARTERM
+uniform vec3 vLightSpecular0;
+#endif
+#ifdef SHADOW0
+#if defined(SPOTLIGHT0) || defined(DIRLIGHT0)
+varying vec4 vPositionFromLight0;
+uniform sampler2D shadowSampler0;
+#else
+uniform samplerCube shadowSampler0;
+#endif
+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 SPECULARTERM
+uniform vec3 vLightSpecular1;
+#endif
+#ifdef SHADOW1
+#if defined(SPOTLIGHT1) || defined(DIRLIGHT1)
+varying vec4 vPositionFromLight1;
+uniform sampler2D shadowSampler1;
+#else
+uniform samplerCube shadowSampler1;
+#endif
+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 SPECULARTERM
+uniform vec3 vLightSpecular2;
+#endif
+#ifdef SHADOW2
+#if defined(SPOTLIGHT2) || defined(DIRLIGHT2)
+varying vec4 vPositionFromLight2;
+uniform sampler2D shadowSampler2;
+#else
+uniform samplerCube shadowSampler2;
+#endif
+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 SPECULARTERM
+uniform vec3 vLightSpecular3;
+#endif
+#ifdef SHADOW3
+#if defined(SPOTLIGHT3) || defined(DIRLIGHT3)
+varying vec4 vPositionFromLight3;
+uniform sampler2D shadowSampler3;
+#else
+uniform samplerCube shadowSampler3;
+#endif
+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
+
+#ifdef AMBIENT
+varying vec2 vAmbientUV;
+uniform sampler2D ambientSampler;
+uniform vec2 vAmbientInfos;
+#endif
+
+#ifdef OPACITY	
+varying vec2 vOpacityUV;
+uniform sampler2D opacitySampler;
+uniform vec2 vOpacityInfos;
+#endif
+
+#ifdef EMISSIVE
+varying vec2 vEmissiveUV;
+uniform vec2 vEmissiveInfos;
+uniform sampler2D emissiveSampler;
+#endif
+
+#ifdef LIGHTMAP
+varying vec2 vLightmapUV;
+uniform vec2 vLightmapInfos;
+uniform sampler2D lightmapSampler;
+#endif
+
+#if defined(SPECULAR) && defined(SPECULARTERM)
+varying vec2 vSpecularUV;
+uniform vec2 vSpecularInfos;
+uniform sampler2D specularSampler;
+#endif
+
+#ifdef CLIPPLANE
+varying float fClipDistance;
+#endif
+
+// Light Computing
+struct lightingInfo
+{
+    vec3 diffuse;
+#ifdef SPECULARTERM
+    vec3 specular;
+#endif
+};
+
+lightingInfo computeLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, float range, float roughness, float NdotV) {
+    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
+    vec3 H = normalize(viewDirectionW + lightVectorW);
+    float NdotL = max(0.00000000001, dot(vNormal, lightVectorW));
+    float VdotH = clamp(0.00000000001, 1.0, dot(viewDirectionW, H));
+
+    float diffuseTerm = computeDiffuseTerm(NdotL, NdotV, VdotH, roughness);
+    result.diffuse = diffuseTerm * diffuseColor * attenuation;
+
+#ifdef SPECULARTERM
+    // Specular
+    float NdotH = max(0.00000000001, dot(vNormal, H));
+
+    vec3 specTerm = computeSpecularTerm(NdotH, NdotL, NdotV, VdotH, roughness, specularColor);
+    result.specular = specTerm * specularColor * attenuation;
+#endif
+
+    return result;
+}
+
+lightingInfo computeSpotLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec4 lightDirection, vec3 diffuseColor, vec3 specularColor, float range, float roughness, float NdotV) {
+    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.0000001, 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
+        vec3 H = normalize(viewDirectionW - lightDirection.xyz);
+        float NdotL = max(0.00000000001, dot(vNormal, -lightDirection.xyz));
+        float VdotH = clamp(dot(viewDirectionW, H), 0.00000000001, 1.0);
+
+        float diffuseTerm = computeDiffuseTerm(NdotL, NdotV, VdotH, roughness);
+        result.diffuse = diffuseTerm * diffuseColor * attenuation * spotAtten;
+
+#ifdef SPECULARTERM
+        // Specular
+        float NdotH = max(0.00000000001, dot(vNormal, H));
+
+        vec3 specTerm = computeSpecularTerm(NdotH, NdotL, NdotV, VdotH, roughness, specularColor);
+        result.specular = specTerm * specularColor * attenuation * spotAtten;
+#endif
+
+        return result;
+    }
+
+    result.diffuse = vec3(0.);
+#ifdef SPECULARTERM
+    result.specular = vec3(0.);
+#endif
+
+    return result;
+}
+
+lightingInfo computeHemisphericLighting(vec3 viewDirectionW, vec3 vNormal, vec4 lightData, vec3 diffuseColor, vec3 specularColor, vec3 groundColor, float roughness, float NdotV) {
+    lightingInfo result;
+
+    vec3 lightVectorW = normalize(-lightData.xyz);
+
+    // Diffuse
+    float ndl = dot(vNormal, lightData.xyz) * 0.5 + 0.5;
+    result.diffuse = mix(groundColor, diffuseColor, ndl);
+
+#ifdef SPECULARTERM
+    // Specular
+    vec3 H = normalize(viewDirectionW + lightVectorW);
+    float NdotH = max(0.00000000001, dot(vNormal, H));
+    float NdotL = max(0.00000000001, ndl);
+    float VdotH = clamp(0.00000000001, 1.0, dot(viewDirectionW, H));
+
+    vec3 specTerm = computeSpecularTerm(NdotH, NdotL, NdotV, VdotH, roughness, specularColor);
+    result.specular = specTerm * specularColor;
+#endif
+
+    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);
+    baseColor = vec4(toLinearSpace(baseColor.rgb), baseColor.a);
+
+#ifdef ALPHATEST
+    if (baseColor.a < 0.4)
+        discard;
+#endif
+
+#ifdef ALPHAFROMDIFFUSE
+    alpha *= baseColor.a;
+#endif
+
+    baseColor.rgb *= vDiffuseInfos.y;
+#endif
+
+    baseColor.rgb = mix(baseColor.rgb, vPBROverloadedDiffuse, vPBROverloadedIntensity.y);
+
+#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
+
+    // Ambient color
+    vec3 baseAmbientColor = vec3(1., 1., 1.);
+
+#ifdef AMBIENT
+    baseAmbientColor = texture2D(ambientSampler, vAmbientUV).rgb * vAmbientInfos.y;
+    baseAmbientColor.rgb = mix(baseAmbientColor.rgb, vPBROverloadedAmbient, vPBROverloadedIntensity.x);
+#endif
+
+    // Specular map
+#ifdef SPECULARTERM
+    float glossiness = vSpecularColor.a;
+    vec3 specularColor = vSpecularColor.rgb;
+
+#ifdef SPECULAR
+    vec4 specularMapColor = texture2D(specularSampler, vSpecularUV);
+    specularColor *= toLinearSpace(specularMapColor.rgb);
+#ifdef GLOSSINESS
+    glossiness = specularMapColor.a;
+#endif
+#endif
+    specularColor.rgb = mix(specularColor.rgb, vPBROverloadedSpecular, vPBROverloadedIntensity.z);
+    glossiness = computeDefaultGlossiness(glossiness, specularColor);
+    glossiness = mix(glossiness, vPBROverloadedSmoothness.x, vPBROverloadedSmoothness.y);
+    #else
+    float glossiness = 0.;
+    glossiness = mix(glossiness, vPBROverloadedSmoothness.x, vPBROverloadedSmoothness.y);
+    vec3 specularColor = vec3(0., 0., 0);
+    specularColor.rgb = mix(specularColor.rgb, vPBROverloadedSpecular, vPBROverloadedIntensity.z);
+#endif
+
+    // Apply Energy Conservation.
+    float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
+    baseColor.rgb = (1. - reflectance) * baseColor.rgb;
+
+    // Compute Specular Fresnel + Reflectance.
+    float NdotV = max(0.00000000001, dot(normalW, viewDirectionW));
+
+    // Adapt glossiness.
+    glossiness = clamp(glossiness, 0., 1.) * 0.98;
+
+    // Call rough to not conflict with previous one.
+    float rough = clamp(1. - glossiness, 0.000001, 1.0);
+
+    // Lighting
+    vec3 diffuseBase = vec3(0., 0., 0.);
+    vec3 shadowedOnly = vPBROverloadedDiffuse;
+#ifdef SPECULARTERM
+    vec3 specularBase = vec3(0., 0., 0.);
+#endif
+    float shadow = 1.;
+
+#ifdef LIGHT0
+#ifndef SPECULARTERM
+    vec3 vLightSpecular0 = vec3(0.0);
+#endif
+#ifdef SPOTLIGHT0
+    lightingInfo info = computeSpotLighting(viewDirectionW, normalW, vLightData0, vLightDirection0, vLightDiffuse0.rgb, vLightSpecular0, vLightDiffuse0.a, rough, NdotV);
+#endif
+#ifdef HEMILIGHT0
+    lightingInfo info = computeHemisphericLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0.rgb, vLightSpecular0, vLightGround0, rough, NdotV);
+#endif
+#if defined(POINTLIGHT0) || defined(DIRLIGHT0)
+    lightingInfo info = computeLighting(viewDirectionW, normalW, vLightData0, vLightDiffuse0.rgb, vLightSpecular0, vLightDiffuse0.a, rough, NdotV);
+#endif
+
+    shadow = 1.;
+    diffuseBase += info.diffuse * shadow;
+    shadowedOnly *= shadow;
+
+#ifdef SPECULARTERM
+    specularBase += info.specular * shadow;
+#endif
+#endif
+
+#ifdef LIGHT1
+#ifndef SPECULARTERM
+    vec3 vLightSpecular1 = vec3(0.0);
+#endif
+#ifdef SPOTLIGHT1
+    info = computeSpotLighting(viewDirectionW, normalW, vLightData1, vLightDirection1, vLightDiffuse1.rgb, vLightSpecular1, vLightDiffuse1.a, rough, NdotV);
+#endif
+#ifdef HEMILIGHT1
+    info = computeHemisphericLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1.rgb, vLightSpecular1, vLightGround1, rough, NdotV);
+#endif
+#if defined(POINTLIGHT1) || defined(DIRLIGHT1)
+    info = computeLighting(viewDirectionW, normalW, vLightData1, vLightDiffuse1.rgb, vLightSpecular1, vLightDiffuse1.a, rough, NdotV);
+#endif
+
+    shadow = 1.;
+    diffuseBase += info.diffuse * shadow;
+    shadowedOnly *= shadow;
+
+#ifdef SPECULARTERM
+    specularBase += info.specular * shadow;
+#endif
+#endif
+
+#ifdef LIGHT2
+#ifndef SPECULARTERM
+    vec3 vLightSpecular2 = vec3(0.0);
+#endif
+#ifdef SPOTLIGHT2
+    info = computeSpotLighting(viewDirectionW, normalW, vLightData2, vLightDirection2, vLightDiffuse2.rgb, vLightSpecular2, vLightDiffuse2.a, rough, NdotV);
+#endif
+#ifdef HEMILIGHT2
+    info = computeHemisphericLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2.rgb, vLightSpecular2, vLightGround2, rough, NdotV);
+#endif
+#if defined(POINTLIGHT2) || defined(DIRLIGHT2)
+    info = computeLighting(viewDirectionW, normalW, vLightData2, vLightDiffuse2.rgb, vLightSpecular2, vLightDiffuse2.a, rough, NdotV);
+#endif
+
+    shadow = 1.;
+    diffuseBase += info.diffuse * shadow;
+    shadowedOnly *= shadow;
+
+#ifdef SPECULARTERM
+    specularBase += info.specular * shadow;
+#endif
+#endif
+
+#ifdef LIGHT3
+#ifndef SPECULARTERM
+    vec3 vLightSpecular3 = vec3(0.0);
+#endif
+#ifdef SPOTLIGHT3
+    info = computeSpotLighting(viewDirectionW, normalW, vLightData3, vLightDirection3, vLightDiffuse3.rgb, vLightSpecular3, vLightDiffuse3.a, rough, NdotV);
+#endif
+#ifdef HEMILIGHT3
+    info = computeHemisphericLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3.rgb, vLightSpecular3, vLightGround3, rough, NdotV);
+#endif
+#if defined(POINTLIGHT3) || defined(DIRLIGHT3)
+    info = computeLighting(viewDirectionW, normalW, vLightData3, vLightDiffuse3.rgb, vLightSpecular3, vLightDiffuse3.a, rough, NdotV);
+#endif
+
+    shadow = 1.;
+    diffuseBase += info.diffuse * shadow;
+    shadowedOnly *= shadow;
+
+#ifdef SPECULARTERM
+    specularBase += info.specular * shadow;
+#endif
+#endif
+
+    // Reflection
+    vec3 reflectionColor = vec3(0., 0., 0.);
+
+#ifdef OPACITY
+    vec4 opacityMap = texture2D(opacitySampler, vOpacityUV);
+
+#ifdef OPACITYRGB
+    opacityMap.rgb = opacityMap.rgb * vec3(0.3, 0.59, 0.11);
+    alpha *= (opacityMap.x + opacityMap.y + opacityMap.z)* vOpacityInfos.y;
+#else
+    alpha *= opacityMap.a * vOpacityInfos.y;
+#endif
+
+#endif
+
+#ifdef VERTEXALPHA
+    alpha *= vColor.a;
+#endif
+
+    // Emissive
+    vec3 emissiveColor = vEmissiveColor;
+#ifdef EMISSIVE
+    vec3 emissiveColorTex = texture2D(emissiveSampler, vEmissiveUV).rgb;
+    emissiveColor = toLinearSpace(emissiveColorTex.rgb) * emissiveColor * vEmissiveInfos.y;
+    emissiveColor = mix(emissiveColor, vPBROverloadedEmissive, vPBROverloadedIntensity.w);
+#endif
+
+    // Composition
+#ifdef EMISSIVEASILLUMINATION
+    vec3 finalDiffuse = max(diffuseBase * diffuseColor + vAmbientColor, 0.0) * baseColor.rgb;
+#else
+    #ifdef LINKEMISSIVEWITHDIFFUSE
+        vec3 finalDiffuse = clamp((diffuseBase + emissiveColor) * diffuseColor + vAmbientColor, 0.0, 1.0) * baseColor.rgb;
+    #else
+        vec3 finalDiffuse = clamp(diffuseBase * diffuseColor + emissiveColor + vAmbientColor, 0.0, 1.0) * baseColor.rgb;
+    #endif
+#endif
+
+#ifdef SPECULARTERM
+    vec3 finalSpecular = specularBase * specularColor;
+#else
+    vec3 finalSpecular = vec3(0.0);
+#endif
+
+#ifdef SPECULAROVERALPHA
+    alpha = clamp(alpha + dot(finalSpecular, vec3(0.3, 0.59, 0.11)), 0., 1.);
+#endif
+
+    // Composition
+#ifdef EMISSIVEASILLUMINATION
+    vec4 color = vec4(finalDiffuse * baseAmbientColor * vPBRLightingIntensity.x + finalSpecular * vPBRLightingIntensity.x + reflectionColor * vPBRLightingIntensity.z + emissiveColor * vPBRLightingIntensity.y, alpha);
+#else
+    vec4 color = vec4(finalDiffuse * baseAmbientColor + finalSpecular + reflectionColor, alpha);
+#endif
+
+    color = max(color, 0.0);
+
+    color.rgb = toneMaps(color.rgb);
+    color.rgb = toGammaSpace(color.rgb);
+    color = contrasts(color);
+
+    color.rgb = mix(color.rgb, shadowedOnly, (1.0 - vPBRShadowIntensity.y));
+
+    gl_FragColor = color;
+}

+ 169 - 0
materialsLibrary/materials/pbr/legacypbr.vertex.fx

@@ -0,0 +1,169 @@
+precision mediump float;
+
+// Attributes
+attribute vec3 position;
+attribute vec3 normal;
+#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
+uniform mat4 world;
+uniform mat4 view;
+uniform mat4 viewProjection;
+
+#ifdef DIFFUSE
+varying vec2 vDiffuseUV;
+uniform mat4 diffuseMatrix;
+uniform vec2 vDiffuseInfos;
+#endif
+
+#ifdef AMBIENT
+varying vec2 vAmbientUV;
+uniform mat4 ambientMatrix;
+uniform vec2 vAmbientInfos;
+#endif
+
+#ifdef OPACITY
+varying vec2 vOpacityUV;
+uniform mat4 opacityMatrix;
+uniform vec2 vOpacityInfos;
+#endif
+
+#ifdef EMISSIVE
+varying vec2 vEmissiveUV;
+uniform vec2 vEmissiveInfos;
+uniform mat4 emissiveMatrix;
+#endif
+
+#if defined(SPECULAR) && defined(SPECULARTERM)
+varying vec2 vSpecularUV;
+uniform vec2 vSpecularInfos;
+uniform mat4 specularMatrix;
+#endif
+
+#ifdef BONES
+uniform mat4 mBones[BonesPerMesh];
+#endif
+
+// Output
+varying vec3 vPositionW;
+varying vec3 vNormalW;
+
+#ifdef VERTEXCOLOR
+varying vec4 vColor;
+#endif
+
+#ifdef CLIPPLANE
+uniform vec4 vClipPlane;
+varying float fClipDistance;
+#endif
+
+void main(void) {
+	mat4 finalWorld;
+
+#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 = world * (m0 + m1 + m2 + m3);
+#else
+	finalWorld = world * (m0 + m1 + m2);
+#endif 
+
+#else
+	finalWorld = world;
+#endif
+
+	gl_Position = viewProjection * finalWorld * vec4(position, 1.0);
+
+	vec4 worldPos = finalWorld * vec4(position, 1.0);
+	vPositionW = vec3(worldPos);
+	vNormalW = normalize(vec3(finalWorld * vec4(normal, 0.0)));
+
+	// 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
+
+#ifdef AMBIENT
+	if (vAmbientInfos.x == 0.)
+	{
+		vAmbientUV = vec2(ambientMatrix * vec4(uv, 1.0, 0.0));
+	}
+	else
+	{
+		vAmbientUV = vec2(ambientMatrix * vec4(uv2, 1.0, 0.0));
+	}
+#endif
+
+#ifdef OPACITY
+	if (vOpacityInfos.x == 0.)
+	{
+		vOpacityUV = vec2(opacityMatrix * vec4(uv, 1.0, 0.0));
+	}
+	else
+	{
+		vOpacityUV = vec2(opacityMatrix * vec4(uv2, 1.0, 0.0));
+	}
+#endif
+
+#ifdef EMISSIVE
+	if (vEmissiveInfos.x == 0.)
+	{
+		vEmissiveUV = vec2(emissiveMatrix * vec4(uv, 1.0, 0.0));
+	}
+	else
+	{
+		vEmissiveUV = vec2(emissiveMatrix * vec4(uv2, 1.0, 0.0));
+	}
+#endif
+
+#if defined(SPECULAR) && defined(SPECULARTERM)
+	if (vSpecularInfos.x == 0.)
+	{
+		vSpecularUV = vec2(specularMatrix * vec4(uv, 1.0, 0.0));
+	}
+	else
+	{
+		vSpecularUV = vec2(specularMatrix * vec4(uv2, 1.0, 0.0));
+	}
+#endif
+
+	// Clip plane
+#ifdef CLIPPLANE
+	fClipDistance = dot(worldPos, vClipPlane);
+#endif
+
+	// Vertex color
+#ifdef VERTEXCOLOR
+	vColor = color;
+#endif
+}

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 1218 - 0
materialsLibrary/materials/pbr/pbr.fragment.fx


+ 291 - 0
materialsLibrary/materials/pbr/pbr.vertex.fx

@@ -0,0 +1,291 @@
+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 AMBIENT
+varying vec2 vAmbientUV;
+uniform mat4 ambientMatrix;
+uniform vec2 vAmbientInfos;
+#endif
+
+#ifdef OPACITY
+varying vec2 vOpacityUV;
+uniform mat4 opacityMatrix;
+uniform vec2 vOpacityInfos;
+#endif
+
+#ifdef EMISSIVE
+varying vec2 vEmissiveUV;
+uniform vec2 vEmissiveInfos;
+uniform mat4 emissiveMatrix;
+#endif
+
+#ifdef LIGHTMAP
+varying vec2 vLightmapUV;
+uniform vec2 vLightmapInfos;
+uniform mat4 lightmapMatrix;
+#endif
+
+#if defined(SPECULAR) && defined(SPECULARTERM)
+varying vec2 vSpecularUV;
+uniform vec2 vSpecularInfos;
+uniform mat4 specularMatrix;
+#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
+#if defined(SPOTLIGHT0) || defined(DIRLIGHT0)
+uniform mat4 lightMatrix0;
+varying vec4 vPositionFromLight0;
+#endif
+#if defined(SPOTLIGHT1) || defined(DIRLIGHT1)
+uniform mat4 lightMatrix1;
+varying vec4 vPositionFromLight1;
+#endif
+#if defined(SPOTLIGHT2) || defined(DIRLIGHT2)
+uniform mat4 lightMatrix2;
+varying vec4 vPositionFromLight2;
+#endif
+#if defined(SPOTLIGHT3) || defined(DIRLIGHT3)
+uniform mat4 lightMatrix3;
+varying vec4 vPositionFromLight3;
+#endif
+#endif
+
+#ifdef REFLECTIONMAP_SKYBOX
+varying vec3 vPositionUVW;
+#endif
+
+#ifdef REFLECTIONMAP_EQUIRECTANGULAR
+varying vec3 vDirectionW;
+#endif
+
+void main(void) {
+    mat4 finalWorld;
+
+#ifdef REFLECTIONMAP_SKYBOX
+    vPositionUVW = position;
+#endif 
+
+#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
+
+#ifdef REFLECTIONMAP_EQUIRECTANGULAR
+    vDirectionW = normalize(vec3(finalWorld * vec4(position, 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
+
+#ifdef AMBIENT
+    if (vAmbientInfos.x == 0.)
+    {
+        vAmbientUV = vec2(ambientMatrix * vec4(uv, 1.0, 0.0));
+    }
+    else
+    {
+        vAmbientUV = vec2(ambientMatrix * vec4(uv2, 1.0, 0.0));
+    }
+#endif
+
+#ifdef OPACITY
+    if (vOpacityInfos.x == 0.)
+    {
+        vOpacityUV = vec2(opacityMatrix * vec4(uv, 1.0, 0.0));
+    }
+    else
+    {
+        vOpacityUV = vec2(opacityMatrix * vec4(uv2, 1.0, 0.0));
+    }
+#endif
+
+#ifdef EMISSIVE
+    if (vEmissiveInfos.x == 0.)
+    {
+        vEmissiveUV = vec2(emissiveMatrix * vec4(uv, 1.0, 0.0));
+    }
+    else
+    {
+        vEmissiveUV = vec2(emissiveMatrix * vec4(uv2, 1.0, 0.0));
+    }
+#endif
+
+#ifdef LIGHTMAP
+    if (vLightmapInfos.x == 0.)
+    {
+        vLightmapUV = vec2(lightmapMatrix * vec4(uv, 1.0, 0.0));
+    }
+    else
+    {
+        vLightmapUV = vec2(lightmapMatrix * vec4(uv2, 1.0, 0.0));
+    }
+#endif
+
+#if defined(SPECULAR) && defined(SPECULARTERM)
+    if (vSpecularInfos.x == 0.)
+    {
+        vSpecularUV = vec2(specularMatrix * vec4(uv, 1.0, 0.0));
+    }
+    else
+    {
+        vSpecularUV = vec2(specularMatrix * vec4(uv2, 1.0, 0.0));
+    }
+#endif
+
+#ifdef BUMP
+    if (vBumpInfos.x == 0.)
+    {
+        vBumpUV = vec2(bumpMatrix * vec4(uv, 1.0, 0.0));
+    }
+    else
+    {
+        vBumpUV = vec2(bumpMatrix * 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
+#if defined(SPOTLIGHT0) || defined(DIRLIGHT0)
+    vPositionFromLight0 = lightMatrix0 * worldPos;
+#endif
+#if defined(SPOTLIGHT1) || defined(DIRLIGHT1)
+    vPositionFromLight1 = lightMatrix1 * worldPos;
+#endif
+#if defined(SPOTLIGHT2) || defined(DIRLIGHT2)
+    vPositionFromLight2 = lightMatrix2 * worldPos;
+#endif
+#if defined(SPOTLIGHT3) || defined(DIRLIGHT3)
+    vPositionFromLight3 = lightMatrix3 * worldPos;
+#endif
+#endif
+
+    // Vertex color
+#ifdef VERTEXCOLOR
+    vColor = color;
+#endif
+
+    // Point size
+#ifdef POINTSIZE
+    gl_PointSize = pointSize;
+#endif
+}

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 145 - 281
materialsLibrary/test/babylon.max.js


+ 7 - 1
materialsLibrary/test/index.html

@@ -10,6 +10,7 @@
 	<script src="../dist/babylon.fireMaterial.js"></script>
     <script src="../dist/babylon.lavaMaterial.js"></script>
 	<script src="../dist/babylon.terrainMaterial.js"></script>
+	<script src="../dist/babylon.pbrMaterial.js"></script>
 
 	<style>
 		html, body {
@@ -202,6 +203,8 @@
 				terrain.diffuseTexture2.uScale = terrain.diffuseTexture2.vScale = 10;
 				terrain.diffuseTexture3.uScale = terrain.diffuseTexture3.vScale = 10;
 				
+				var pbr = new BABYLON.PBRMaterial("pbr", scene);
+				
 				// Default to std
 				var currentMaterial = std;
 				sphere.material = std;				
@@ -221,7 +224,7 @@
 					skybox: false
 				}
 
-				gui.add(options, 'material', ['standard', 'simple', 'water', 'fire', 'lava', 'normal', 'terrain']).onFinishChange(function () {
+				gui.add(options, 'material', ['standard', 'simple', 'water', 'fire', 'lava', 'normal', 'terrain', 'pbr']).onFinishChange(function () {
 					water.enableRenderTargets(false);
 					
 					switch (options.material) {
@@ -245,6 +248,9 @@
 						case "terrain":
 							currentMaterial = terrain;
 							break;
+						case "pbr":
+							currentMaterial = pbr;
+							break;							
 						default:
 							currentMaterial = std;
 							break;

+ 0 - 223
src/Materials/babylon.pbrMaterial.js

@@ -1,223 +0,0 @@
-var __extends = (this && this.__extends) || function (d, b) {
-    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
-    function __() { this.constructor = d; }
-    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
-};
-var BABYLON;
-(function (BABYLON) {
-    var maxSimultaneousLights = 4;
-    var PBRMaterialDefines = (function (_super) {
-        __extends(PBRMaterialDefines, _super);
-        function PBRMaterialDefines() {
-            _super.call(this);
-            this.ALBEDO = false;
-            this.CLIPPLANE = false;
-            this.ALPHATEST = false;
-            this.FOG = false;
-            this.NORMAL = false;
-            this.UV1 = false;
-            this.UV2 = false;
-            this.VERTEXCOLOR = false;
-            this.VERTEXALPHA = false;
-            this.NUM_BONE_INFLUENCERS = 0;
-            this.BonesPerMesh = 0;
-            this.INSTANCES = false;
-            this.POINTSIZE = false;
-            this._keys = Object.keys(this);
-        }
-        return PBRMaterialDefines;
-    })(BABYLON.MaterialDefines);
-    var PBRMaterial = (function (_super) {
-        __extends(PBRMaterial, _super);
-        function PBRMaterial(name, scene) {
-            _super.call(this, name, scene);
-            this.albedoColor = new BABYLON.Color3(1, 1, 1);
-            this._worldViewProjectionMatrix = BABYLON.Matrix.Zero();
-            this._globalAmbientColor = new BABYLON.Color3(0, 0, 0);
-            this._scaledDiffuse = new BABYLON.Color3();
-            this._scaledSpecular = new BABYLON.Color3();
-            this._defines = new PBRMaterialDefines();
-            this._cachedDefines = new PBRMaterialDefines();
-            this._cachedDefines.BonesPerMesh = -1;
-        }
-        PBRMaterial.prototype.needAlphaBlending = function () {
-            return this.alpha < 1.0;
-        };
-        PBRMaterial.prototype.needAlphaTesting = function () {
-            return false;
-        };
-        PBRMaterial.prototype.getAlphaTestTexture = function () {
-            return null;
-        };
-        // Methods   
-        PBRMaterial.prototype.isReady = function (mesh, useInstances) {
-            if (this.checkReadyOnlyOnce) {
-                if (this._wasPreviouslyReady) {
-                    return true;
-                }
-            }
-            var scene = this.getScene();
-            if (!this.checkReadyOnEveryCall) {
-                if (this._renderId === scene.getRenderId()) {
-                    return true;
-                }
-            }
-            var engine = scene.getEngine();
-            var needNormals = false;
-            var needUVs = false;
-            this._defines.reset();
-            // Textures
-            if (scene.texturesEnabled) {
-            }
-            // 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 !== BABYLON.Scene.FOGMODE_NONE && this.fogEnabled) {
-                this._defines.FOG = true;
-            }
-            // Lights
-            // Attribs
-            if (mesh) {
-                if (needNormals && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.NormalKind)) {
-                    this._defines.NORMAL = true;
-                }
-                if (needUVs) {
-                    if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UVKind)) {
-                        this._defines.UV1 = true;
-                    }
-                    if (mesh.isVerticesDataPresent(BABYLON.VertexBuffer.UV2Kind)) {
-                        this._defines.UV2 = true;
-                    }
-                }
-                if (mesh.useVertexColors && mesh.isVerticesDataPresent(BABYLON.VertexBuffer.ColorKind)) {
-                    this._defines.VERTEXCOLOR = true;
-                    if (mesh.hasVertexAlpha) {
-                        this._defines.VERTEXALPHA = true;
-                    }
-                }
-                if (mesh.useBones && mesh.computeBonesUsingShaders) {
-                    this._defines.NUM_BONE_INFLUENCERS = mesh.numBoneInfluencers;
-                    this._defines.BonesPerMesh = (mesh.skeleton.bones.length + 1);
-                }
-                // 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 BABYLON.EffectFallbacks();
-                if (this._defines.FOG) {
-                    fallbacks.addFallback(1, "FOG");
-                }
-                //Attributes
-                var attribs = [BABYLON.VertexBuffer.PositionKind];
-                if (this._defines.NORMAL) {
-                    attribs.push(BABYLON.VertexBuffer.NormalKind);
-                }
-                if (this._defines.UV1) {
-                    attribs.push(BABYLON.VertexBuffer.UVKind);
-                }
-                if (this._defines.UV2) {
-                    attribs.push(BABYLON.VertexBuffer.UV2Kind);
-                }
-                if (this._defines.VERTEXCOLOR) {
-                    attribs.push(BABYLON.VertexBuffer.ColorKind);
-                }
-                if (this._defines.NUM_BONE_INFLUENCERS > 0) {
-                    attribs.push(BABYLON.VertexBuffer.MatricesIndicesKind);
-                    attribs.push(BABYLON.VertexBuffer.MatricesWeightsKind);
-                    if (this._defines.NUM_BONE_INFLUENCERS > 4) {
-                        attribs.push(BABYLON.VertexBuffer.MatricesIndicesExtraKind);
-                        attribs.push(BABYLON.VertexBuffer.MatricesWeightsExtraKind);
-                    }
-                }
-                if (this._defines.INSTANCES) {
-                    attribs.push("world0");
-                    attribs.push("world1");
-                    attribs.push("world2");
-                    attribs.push("world3");
-                }
-                // Legacy browser patch
-                var join = this._defines.toString();
-                this._effect = scene.getEngine().createEffect("pbr", attribs, ["world", "view", "viewProjection", "vEyePosition", "vAlbedoColor",
-                    "vFogInfos", "vFogColor", "pointSize",
-                    "mBones",
-                    "vClipPlane",
-                ], [], join, fallbacks, this.onCompiled, this.onError);
-            }
-            if (!this._effect.isReady()) {
-                return false;
-            }
-            this._renderId = scene.getRenderId();
-            this._wasPreviouslyReady = true;
-            return true;
-        };
-        PBRMaterial.prototype.bindOnlyWorldMatrix = function (world) {
-            this._effect.setMatrix("world", world);
-        };
-        PBRMaterial.prototype.bind = function (world, mesh) {
-            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) {
-                // Clip plane
-                if (scene.clipPlane) {
-                    var clipPlane = scene.clipPlane;
-                    this._effect.setFloat4("vClipPlane", clipPlane.normal.x, clipPlane.normal.y, clipPlane.normal.z, clipPlane.d);
-                }
-                this._effect.setVector3("vEyePosition", scene.activeCamera.position);
-            }
-            // Point size
-            if (this.pointsCloud) {
-                this._effect.setFloat("pointSize", this.pointSize);
-            }
-            // Colors
-            this._effect.setColor4("vAlbedoColor", this.albedoColor, this.alpha * mesh.visibility);
-            // View
-            if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== BABYLON.Scene.FOGMODE_NONE) {
-                this._effect.setMatrix("view", scene.getViewMatrix());
-            }
-            // Fog
-            if (scene.fogEnabled && mesh.applyFog && scene.fogMode !== BABYLON.Scene.FOGMODE_NONE) {
-                this._effect.setFloat4("vFogInfos", scene.fogMode, scene.fogStart, scene.fogEnd, scene.fogDensity);
-                this._effect.setColor3("vFogColor", scene.fogColor);
-            }
-            _super.prototype.bind.call(this, world, mesh);
-        };
-        PBRMaterial.prototype.getAnimatables = function () {
-            var results = [];
-            return results;
-        };
-        PBRMaterial.prototype.dispose = function (forceDisposeEffect) {
-            _super.prototype.dispose.call(this, forceDisposeEffect);
-        };
-        PBRMaterial.prototype.clone = function (name) {
-            var newPBRMaterial = new PBRMaterial(name, this.getScene());
-            // Base material
-            this.copyTo(newPBRMaterial);
-            // PBRMaterial material
-            newPBRMaterial.albedoColor = this.albedoColor.clone();
-            return newPBRMaterial;
-        };
-        return PBRMaterial;
-    })(BABYLON.Material);
-    BABYLON.PBRMaterial = PBRMaterial;
-})(BABYLON || (BABYLON = {}));

+ 0 - 275
src/Materials/babylon.pbrMaterial.ts

@@ -1,275 +0,0 @@
-module BABYLON {
-    var maxSimultaneousLights = 4;
-
-    class PBRMaterialDefines extends MaterialDefines {
-        public ALBEDO = false;
-        public CLIPPLANE = false;
-        public ALPHATEST = false;
-        public FOG = false;
-        public NORMAL = false;
-        public UV1 = false;
-        public UV2 = false;
-        public VERTEXCOLOR = false;
-        public VERTEXALPHA = false;
-        public NUM_BONE_INFLUENCERS = 0;
-        public BonesPerMesh = 0;
-        public INSTANCES = false;
-        public POINTSIZE = false;
-
-        constructor() {
-            super();
-            this._keys = Object.keys(this);
-        }
-    }
-
-    export class PBRMaterial extends Material {
-        public albedoColor = new Color3(1, 1, 1);
-
-        private _worldViewProjectionMatrix = Matrix.Zero();
-        private _globalAmbientColor = new Color3(0, 0, 0);
-        private _scaledDiffuse = new Color3();
-        private _scaledSpecular = new Color3();
-        private _renderId: number;
-
-        private _defines = new PBRMaterialDefines();
-        private _cachedDefines = new PBRMaterialDefines();
-
-        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   
-        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()) {
-                    return true;
-                }
-            }
-
-            var engine = scene.getEngine();
-            var needNormals = false;
-            var needUVs = false;
-
-            this._defines.reset();
-
-            // Textures
-            if (scene.texturesEnabled) {        
-            }
-
-            // 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;
-            }
-            
-            // Lights
-
-            // 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.NUM_BONE_INFLUENCERS = mesh.numBoneInfluencers;
-                    this._defines.BonesPerMesh = (mesh.skeleton.bones.length + 1);
-                }
-
-                // 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");
-                }             
-
-
-                //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.NUM_BONE_INFLUENCERS > 0) {
-                    attribs.push(VertexBuffer.MatricesIndicesKind);
-                    attribs.push(VertexBuffer.MatricesWeightsKind);
-                    if (this._defines.NUM_BONE_INFLUENCERS > 4) {
-                        attribs.push(VertexBuffer.MatricesIndicesExtraKind);
-                        attribs.push(VertexBuffer.MatricesWeightsExtraKind);
-                    }
-                }
-
-                if (this._defines.INSTANCES) {
-                    attribs.push("world0");
-                    attribs.push("world1");
-                    attribs.push("world2");
-                    attribs.push("world3");
-                }
-
-                // Legacy browser patch
-                var join = this._defines.toString();
-                this._effect = scene.getEngine().createEffect("pbr",
-                    attribs,
-                    ["world", "view", "viewProjection", "vEyePosition", "vAlbedoColor",                        
-                        "vFogInfos", "vFogColor", "pointSize",
-                        "mBones",
-                        "vClipPlane",
-                    ],
-                    [],
-                    join, fallbacks, this.onCompiled, this.onError);
-            }
-            if (!this._effect.isReady()) {
-                return false;
-            }
-
-            this._renderId = scene.getRenderId();
-            this._wasPreviouslyReady = true;
-            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) {
-                // Clip plane
-                if (scene.clipPlane) {
-                    var clipPlane = scene.clipPlane;
-                    this._effect.setFloat4("vClipPlane", clipPlane.normal.x, clipPlane.normal.y, clipPlane.normal.z, clipPlane.d);
-                }
-                
-                this._effect.setVector3("vEyePosition", scene.activeCamera.position);              
-            }
-
-            // Point size
-            if (this.pointsCloud) {
-                this._effect.setFloat("pointSize", this.pointSize);
-            }
-
-            // Colors
-            this._effect.setColor4("vAlbedoColor", this.albedoColor, this.alpha * mesh.visibility);
-      
-            // 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 = [];         
-
-            return results;
-        }
-
-        public dispose(forceDisposeEffect?: boolean): void {        
-            super.dispose(forceDisposeEffect);
-        }
-
-        public clone(name: string): PBRMaterial {
-            var newPBRMaterial = new PBRMaterial(name, this.getScene());
-
-            // Base material
-            this.copyTo(newPBRMaterial);
-
-            // PBRMaterial material
-            newPBRMaterial.albedoColor = this.albedoColor.clone();
-
-            return newPBRMaterial;
-        }
-
-        // Statics
-        // Flags used to enable or disable a type of texture for all PBR Materials
-    }
-} 

+ 24 - 0
src/Math/babylon.math.js

@@ -1,5 +1,7 @@
 var BABYLON;
 (function (BABYLON) {
+    var ToGammaSpace = 1 / 2.2;
+    var ToLinearSpace = 2.2;
     var Color3 = (function () {
         function Color3(r, g, b) {
             if (r === void 0) { r = 0; }
@@ -97,6 +99,28 @@ var BABYLON;
             var intB = (this.b * 255) | 0;
             return "#" + BABYLON.Tools.ToHex(intR) + BABYLON.Tools.ToHex(intG) + BABYLON.Tools.ToHex(intB);
         };
+        Color3.prototype.toLinearSpace = function () {
+            var convertedColor = new Color3();
+            this.toLinearSpaceToRef(convertedColor);
+            return convertedColor;
+        };
+        Color3.prototype.toLinearSpaceToRef = function (convertedColor) {
+            convertedColor.r = Math.pow(this.r, ToLinearSpace);
+            convertedColor.g = Math.pow(this.g, ToLinearSpace);
+            convertedColor.b = Math.pow(this.b, ToLinearSpace);
+            return this;
+        };
+        Color3.prototype.toGammaSpace = function () {
+            var convertedColor = new Color3();
+            this.toGammaSpaceToRef(convertedColor);
+            return convertedColor;
+        };
+        Color3.prototype.toGammaSpaceToRef = function (convertedColor) {
+            convertedColor.r = Math.pow(this.r, ToGammaSpace);
+            convertedColor.g = Math.pow(this.g, ToGammaSpace);
+            convertedColor.b = Math.pow(this.b, ToGammaSpace);
+            return this;
+        };
         // Statics
         Color3.FromHexString = function (hex) {
             if (hex.substring(0, 1) !== "#" || hex.length !== 7) {

+ 31 - 0
src/Math/babylon.math.ts

@@ -2,6 +2,9 @@
 
     declare var SIMD;
 
+    const ToGammaSpace = 1 / 2.2;
+    const ToLinearSpace = 2.2;
+
     export class Color3 {
         constructor(public r: number = 0, public g: number = 0, public b: number = 0) {
         }
@@ -123,6 +126,34 @@
             return "#" + Tools.ToHex(intR) + Tools.ToHex(intG) + Tools.ToHex(intB);
         }
 
+        public toLinearSpace(): Color3 {
+            var convertedColor = new Color3();
+            this.toLinearSpaceToRef(convertedColor);
+            return convertedColor;
+        }
+
+        public toLinearSpaceToRef(convertedColor: Color3): Color3 {
+            convertedColor.r = Math.pow(this.r, ToLinearSpace);
+            convertedColor.g = Math.pow(this.g, ToLinearSpace);
+            convertedColor.b = Math.pow(this.b, ToLinearSpace);
+
+            return this;
+        }
+
+        public toGammaSpace(): Color3 {
+            var convertedColor = new Color3();
+            this.toGammaSpaceToRef(convertedColor);
+            return convertedColor;
+        }
+
+        public toGammaSpaceToRef(convertedColor: Color3): Color3 {
+            convertedColor.r = Math.pow(this.r, ToGammaSpace);
+            convertedColor.g = Math.pow(this.g, ToGammaSpace);
+            convertedColor.b = Math.pow(this.b, ToGammaSpace);
+
+            return this;
+        }
+
         // Statics
         public static FromHexString(hex: string): Color3 {
             if (hex.substring(0, 1) !== "#" || hex.length !== 7) {

+ 0 - 91
src/Shaders/pbr.fragment.fx

@@ -1,91 +0,0 @@
-precision highp float;
-
-// Constants
-uniform vec3 vEyePosition;
-uniform vec4 vAlbedoColor;
-
-// Input
-varying vec3 vPositionW;
-
-#ifdef NORMAL
-varying vec3 vNormalW;
-#endif
-
-#ifdef VERTEXCOLOR
-varying vec4 vColor;
-#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
-
-void main(void) {
-	// Clip plane
-#ifdef CLIPPLANE
-	if (fClipDistance > 0.0)
-		discard;
-#endif
-
-	vec3 viewDirectionW = normalize(vEyePosition - vPositionW);
-
-	// Base color
-	vec3 baseColor = vAlbedoColor.rgb;
-
-	// Alpha
-	float alpha = vAlbedoColor.a;
-
-#ifdef VERTEXCOLOR
-	baseColor *= vColor.rgb;
-#endif
-
-#ifdef VERTEXALPHA
-	alpha *= vColor.a;
-#endif
-
-	// Composition
-    vec4 color = vec4(clamp(baseColor, 0.0, 1.0), alpha);
-
-#ifdef FOG
-	float fog = CalcFogFactor();
-	color.rgb = fog * color.rgb + (1.0 - fog) * vFogColor;
-#endif
-
-	gl_FragColor = color;
-}

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

@@ -1,138 +0,0 @@
-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
-#if NUM_BONE_INFLUENCERS > 0
-
-	// having bone influencers implies you have bones
-	uniform mat4 mBones[BonesPerMesh];
-
-	attribute vec4 matricesIndices;
-	attribute vec4 matricesWeights;
-	#if NUM_BONE_INFLUENCERS > 4
-		attribute vec4 matricesIndicesExtra;
-		attribute vec4 matricesWeightsExtra;
-	#endif
-#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 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
-
-void main(void) {
-#ifdef INSTANCES
-	mat4 finalWorld = mat4(world0, world1, world2, world3);
-#else
-	mat4 finalWorld = world;
-#endif
-
-#if NUM_BONE_INFLUENCERS > 0
-	mat4 influence;
-	influence = mBones[int(matricesIndices[0])] * matricesWeights[0];
-
-	#if NUM_BONE_INFLUENCERS > 1
-		influence += mBones[int(matricesIndices[1])] * matricesWeights[1];
-	#endif	
-	#if NUM_BONE_INFLUENCERS > 2
-		influence += mBones[int(matricesIndices[2])] * matricesWeights[2];
-	#endif	
-	#if NUM_BONE_INFLUENCERS > 3
-		influence += mBones[int(matricesIndices[3])] * matricesWeights[3];
-	#endif	
-	
-	#if NUM_BONE_INFLUENCERS > 4
-		influence += mBones[int(matricesIndicesExtra[0])] * matricesWeightsExtra[0];
-	#endif	
-	#if NUM_BONE_INFLUENCERS > 5
-		influence += mBones[int(matricesIndicesExtra[1])] * matricesWeightsExtra[1];
-	#endif	
-	#if NUM_BONE_INFLUENCERS > 6
-		influence += mBones[int(matricesIndicesExtra[2])] * matricesWeightsExtra[2];
-	#endif	
-	#if NUM_BONE_INFLUENCERS > 7
-		influence += mBones[int(matricesIndicesExtra[3])] * matricesWeightsExtra[3];
-	#endif	
-
-	finalWorld = finalWorld * influence;
-#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
-
-	// Clip plane
-#ifdef CLIPPLANE
-	fClipDistance = dot(worldPos, vClipPlane);
-#endif
-
-	// Fog
-#ifdef FOG
-	fFogDistance = (view * worldPos).z;
-#endif
-
-	// Vertex color
-#ifdef VERTEXCOLOR
-	vColor = color;
-#endif
-
-	// Point size
-#ifdef POINTSIZE
-	gl_PointSize = pointSize;
-#endif
-}