diff --git a/examples/js/ShaderSkin.js b/examples/js/ShaderSkin.js
index 316e6bd20b8c71..01e02f7431b47f 100644
--- a/examples/js/ShaderSkin.js
+++ b/examples/js/ShaderSkin.js
@@ -80,35 +80,11 @@ THREE.ShaderSkin = {
"varying vec3 vNormal;",
"varying vec2 vUv;",
- "uniform vec3 ambientLightColor;",
-
- "#if MAX_DIR_LIGHTS > 0",
-
- "uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];",
- "uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];",
-
- "#endif",
-
- "#if MAX_HEMI_LIGHTS > 0",
-
- "uniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];",
- "uniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];",
- "uniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ];",
-
- "#endif",
-
- "#if MAX_POINT_LIGHTS > 0",
-
- "uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];",
- "uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
- "uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
- "uniform float pointLightDecay[ MAX_POINT_LIGHTS ];",
-
- "#endif",
-
"varying vec3 vViewPosition;",
THREE.ShaderChunk[ "common" ],
+ THREE.ShaderChunk[ "bsdfs" ],
+ THREE.ShaderChunk[ "lights_pars" ],
THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
THREE.ShaderChunk[ "fog_pars_fragment" ],
THREE.ShaderChunk[ "bumpmap_pars_fragment" ],
@@ -198,9 +174,9 @@ THREE.ShaderSkin = {
"for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
- "vec3 lVector = pointLightPosition[ i ] + vViewPosition.xyz;",
+ "vec3 lVector = pointLights[ i ].position + vViewPosition.xyz;",
- "float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecay[i] );",
+ "float attenuation = calcLightAttenuation( length( lVector ), pointLights[ i ].distance, pointLights[ i ].decay );",
"lVector = normalize( lVector );",
@@ -210,8 +186,8 @@ THREE.ShaderSkin = {
"float pointSpecularWeight = KS_Skin_Specular( normal, lVector, viewerDirection, uRoughness, uSpecularBrightness );",
- "totalDiffuseLight += pointLightColor[ i ] * ( pointDiffuseWeight * attenuation );",
- "totalSpecularLight += pointLightColor[ i ] * specular * ( pointSpecularWeight * specularStrength * attenuation );",
+ "totalDiffuseLight += pointLight[ i ].color * ( pointDiffuseWeight * attenuation );",
+ "totalSpecularLight += pointLight[ i ].color * specular * ( pointSpecularWeight * specularStrength * attenuation );",
"}",
@@ -223,7 +199,7 @@ THREE.ShaderSkin = {
"for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {",
- "vec3 dirVector = directionalLightDirection[ i ];",
+ "vec3 dirVector = directionalLights[ i ].direction;",
"float dirDiffuseWeightFull = max( dot( normal, dirVector ), 0.0 );",
"float dirDiffuseWeightHalf = max( 0.5 * dot( normal, dirVector ) + 0.5, 0.0 );",
@@ -231,8 +207,8 @@ THREE.ShaderSkin = {
"float dirSpecularWeight = KS_Skin_Specular( normal, dirVector, viewerDirection, uRoughness, uSpecularBrightness );",
- "totalDiffuseLight += directionalLightColor[ i ] * dirDiffuseWeight;",
- "totalSpecularLight += directionalLightColor[ i ] * ( dirSpecularWeight * specularStrength );",
+ "totalDiffuseLight += directionalLights[ i ].color * dirDiffuseWeight;",
+ "totalSpecularLight += directionalLights[ i ].color * ( dirSpecularWeight * specularStrength );",
"}",
@@ -394,21 +370,10 @@ THREE.ShaderSkin = {
"varying vec3 vNormal;",
"varying vec2 vUv;",
- "uniform vec3 ambientLightColor;",
-
- "#if MAX_DIR_LIGHTS > 0",
- "uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];",
- "uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];",
- "#endif",
-
- "#if MAX_POINT_LIGHTS > 0",
- "uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];",
- "varying vec4 vPointLight[ MAX_POINT_LIGHTS ];",
- "#endif",
-
"varying vec3 vViewPosition;",
THREE.ShaderChunk[ "common" ],
+ THREE.ShaderChunk[ "lights_pars" ],
THREE.ShaderChunk[ "fog_pars_fragment" ],
"float fresnelReflectance( vec3 H, vec3 V, float F0 ) {",
@@ -490,12 +455,12 @@ THREE.ShaderSkin = {
"#if MAX_POINT_LIGHTS > 0",
"for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
-
- "vec3 pointVector = normalize( vPointLight[ i ].xyz );",
- "float attenuation = vPointLight[ i ].w;",
-
+
+ "vec3 pointVector = normalize( pointLights[ i ].direction );",
+ "float attenuation = calcLightAttenuation( length( lVector ), pointLights[ i ].distance, pointLights[ i ].decay );",
+
"float pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );",
-
+
"totalDiffuseLight += pointLightColor[ i ] * ( pointDiffuseWeight * attenuation );",
"if ( passID == 1 ) {",
@@ -516,17 +481,18 @@ THREE.ShaderSkin = {
"for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {",
- "vec3 dirVector = directionalLightDirection[ i ];",
+ "vec3 dirVector = directionalLights[ i ].direction;",
"float dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );",
- "totalDiffuseLight += directionalLightColor[ i ] * dirDiffuseWeight;",
+
+ "totalDiffuseLight += directionalLights[ i ].color * dirDiffuseWeight;",
"if ( passID == 1 ) {",
"float dirSpecularWeight = KS_Skin_Specular( normal, dirVector, viewerDirection, uRoughness, uSpecularBrightness );",
- "totalSpecularLight += directionalLightColor[ i ] * mSpecular.xyz * dirSpecularWeight;",
+ "totalSpecularLight += directionalLights[ i ].color * mSpecular.xyz * dirSpecularWeight;",
"}",
@@ -607,16 +573,6 @@ THREE.ShaderSkin = {
"varying vec3 vNormal;",
"varying vec2 vUv;",
- "#if MAX_POINT_LIGHTS > 0",
-
- "uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
- "uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
- "uniform float pointLightDecay[ MAX_POINT_LIGHTS ];",
-
- "varying vec4 vPointLight[ MAX_POINT_LIGHTS ];",
-
- "#endif",
-
"varying vec3 vViewPosition;",
THREE.ShaderChunk[ "common" ],
@@ -633,24 +589,6 @@ THREE.ShaderSkin = {
"vUv = uv;",
- // point lights
-
- "#if MAX_POINT_LIGHTS > 0",
-
- "for( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {",
-
- "vec3 lVector = pointLightPosition[ i ] - vViewPosition;",
-
- "float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecay[i] );",
-
- "lVector = normalize( lVector );",
-
- "vPointLight[ i ] = vec4( lVector, attenuation );",
-
- "}",
-
- "#endif",
-
// displacement mapping
"#ifdef VERTEX_TEXTURES",
@@ -675,16 +613,6 @@ THREE.ShaderSkin = {
"varying vec3 vNormal;",
"varying vec2 vUv;",
- "#if MAX_POINT_LIGHTS > 0",
-
- "uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
- "uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
- "uniform float pointLightDecay[ MAX_POINT_LIGHTS ];",
-
- "varying vec4 vPointLight[ MAX_POINT_LIGHTS ];",
-
- "#endif",
-
"varying vec3 vViewPosition;",
THREE.ShaderChunk[ "common" ],
@@ -701,24 +629,6 @@ THREE.ShaderSkin = {
"vUv = uv;",
- // point lights
-
- "#if MAX_POINT_LIGHTS > 0",
-
- "for( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {",
-
- "vec3 lVector = pointLightPosition[ i ] - vViewPosition;",
-
- "float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecay[i] );",
-
- "lVector = normalize( lVector );",
-
- "vPointLight[ i ] = vec4( lVector, attenuation );",
-
- "}",
-
- "#endif",
-
"gl_Position = vec4( uv.x * 2.0 - 1.0, uv.y * 2.0 - 1.0, 0.0, 1.0 );",
"}"
diff --git a/examples/js/ShaderTerrain.js b/examples/js/ShaderTerrain.js
index 97da9304371a3e..87d2c37779778b 100644
--- a/examples/js/ShaderTerrain.js
+++ b/examples/js/ShaderTerrain.js
@@ -86,33 +86,11 @@ THREE.ShaderTerrain = {
"uniform vec3 ambientLightColor;",
- "#if MAX_DIR_LIGHTS > 0",
-
- "uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];",
- "uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];",
-
- "#endif",
-
- "#if MAX_HEMI_LIGHTS > 0",
-
- "uniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];",
- "uniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];",
- "uniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ];",
-
- "#endif",
-
- "#if MAX_POINT_LIGHTS > 0",
-
- "uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];",
- "uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
- "uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
- "uniform float pointLightDecay[ MAX_POINT_LIGHTS ];",
-
- "#endif",
-
"varying vec3 vViewPosition;",
THREE.ShaderChunk[ "common" ],
+ THREE.ShaderChunk[ "bsdfs" ],
+ THREE.ShaderChunk[ "lights_pars" ],
THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
THREE.ShaderChunk[ "fog_pars_fragment" ],
@@ -168,9 +146,9 @@ THREE.ShaderTerrain = {
"for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
- "vec3 lVector = pointLightPosition[ i ] + vViewPosition.xyz;",
+ "vec3 lVector = pointLights[ i ].position + vViewPosition.xyz;",
- "float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecay[i] );",
+ "float attenuation = calcLightAttenuation( length( lVector ), pointLights[ i ].distance, pointLights[ i ].decay );",
"lVector = normalize( lVector );",
@@ -181,8 +159,8 @@ THREE.ShaderTerrain = {
"float pointSpecularWeight = specularTex.r * max( pow( pointDotNormalHalf, shininess ), 0.0 );",
- "totalDiffuseLight += attenuation * pointLightColor[ i ] * pointDiffuseWeight;",
- "totalSpecularLight += attenuation * pointLightColor[ i ] * specular * pointSpecularWeight * pointDiffuseWeight;",
+ "totalDiffuseLight += attenuation * pointLights[ i ].color * pointDiffuseWeight;",
+ "totalSpecularLight += attenuation * pointLights[ i ].color * specular * pointSpecularWeight * pointDiffuseWeight;",
"}",
@@ -197,7 +175,7 @@ THREE.ShaderTerrain = {
"for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {",
- "vec3 dirVector = directionalLightDirection[ i ];",
+ "vec3 dirVector = directionalLights[ i ].direction;",
"vec3 dirHalfVector = normalize( dirVector + viewPosition );",
"float dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );",
@@ -205,8 +183,8 @@ THREE.ShaderTerrain = {
"float dirSpecularWeight = specularTex.r * max( pow( dirDotNormalHalf, shininess ), 0.0 );",
- "totalDiffuseLight += directionalLightColor[ i ] * dirDiffuseWeight;",
- "totalSpecularLight += directionalLightColor[ i ] * specular * dirSpecularWeight * dirDiffuseWeight;",
+ "totalDiffuseLight += directionalLights[ i ].color * dirDiffuseWeight;",
+ "totalSpecularLight += directionalLights[ i ].color * specular * dirSpecularWeight * dirDiffuseWeight;",
"}",
@@ -228,7 +206,7 @@ THREE.ShaderTerrain = {
"float dotProduct = dot( normal, lVector );",
"float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;",
- "totalDiffuseLight += mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );",
+ "totalDiffuseLight += mix( hemisphereLights[ i ].groundColor, hemisphereLights[ i ].skyColor, hemiDiffuseWeight );",
// specular (sky light)
@@ -246,7 +224,7 @@ THREE.ShaderTerrain = {
"float hemiDotNormalHalfGround = 0.5 * dot( normal, hemiHalfVectorGround ) + 0.5;",
"hemiSpecularWeight += specularTex.r * max( pow( hemiDotNormalHalfGround, shininess ), 0.0 );",
- "totalSpecularLight += specular * mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight ) * hemiSpecularWeight * hemiDiffuseWeight;",
+ "totalSpecularLight += specular * mix( hemisphereLights[ i ].groundColor, hemisphereLights[ i ].skyColor, hemiDiffuseWeight ) * hemiSpecularWeight * hemiDiffuseWeight;",
"}",
diff --git a/examples/webgl_animation_skinning_morph.html b/examples/webgl_animation_skinning_morph.html
index a9f6854fb22e8c..b0d861f1e9204e 100644
--- a/examples/webgl_animation_skinning_morph.html
+++ b/examples/webgl_animation_skinning_morph.html
@@ -150,6 +150,8 @@
var loader = new THREE.JSONLoader();
loader.load( "models/skinned/knight.js", function ( geometry, materials ) {
+ console.log( 'materials', materials );
+
createScene( geometry, materials, 0, FLOOR, -300, 60 )
} );
diff --git a/examples/webgl_lights_pointlights.html b/examples/webgl_lights_pointlights.html
index 2fca727f9503e5..829c8d173b5f97 100644
--- a/examples/webgl_lights_pointlights.html
+++ b/examples/webgl_lights_pointlights.html
@@ -72,7 +72,7 @@
var callback = function( geometry ) {
- object = new THREE.Mesh( geometry, new THREE.MeshPhongMaterial( { color: 0x555555, specular: 0xffffff, shininess: 50 } ) );
+ object = new THREE.Mesh( geometry, new THREE.MeshPhongMaterial( { color: 0x555555, specular: 0x111111, shininess: 50 } ) );
object.scale.x = object.scale.y = object.scale.z = 0.80;
scene.add( object );
diff --git a/examples/webgl_materials_lambert_variations.html b/examples/webgl_materials_lambert_variations.html
index a1e7fb99829e8b..89d8d9e6e152e2 100644
--- a/examples/webgl_materials_lambert_variations.html
+++ b/examples/webgl_materials_lambert_variations.html
@@ -88,8 +88,7 @@
var geometry = new THREE.SphereBufferGeometry( sphereRadius, 32, 16 );
-
- for( var alpha = 0; alpha <= 1.0; alpha += stepSize ) {
+ for( var alpha = 0, alphaIndex = 0; alpha <= 1.0; alpha += stepSize, alphaIndex ++ ) {
var baseColor = new THREE.Color().setHSL( alpha, 0.5, 0.5 );
@@ -97,15 +96,21 @@
reflectionCube = null;
}
- for( var beta = 0; beta <= 1.0; beta += stepSize ) {
+ for( var beta = 0, betaIndex = 0; beta <= 1.0; beta += stepSize, betaIndex ++ ) {
var reflectivity = beta;
+ var side = THREE.FrontSide;
+ if( ( betaIndex % 2 ) === 0 ) {
+ side = THREE.DoubleSide;
+ }
+
for( var gamma = 0; gamma <= 1.0; gamma += stepSize ) {
var diffuseColor = baseColor.clone().multiplyScalar( gamma );
- var material = new THREE.MeshLambertMaterial( { map: imgTexture, color: diffuseColor, reflectivity: reflectivity, shading: THREE.SmoothShading, envMap: reflectionCube } )
+ var material = new THREE.MeshLambertMaterial( { map: imgTexture, color: diffuseColor,
+ reflectivity: reflectivity, envMap: reflectionCube, side: side } )
var mesh = new THREE.Mesh( geometry, material );
diff --git a/examples/webgl_shaders_tonemapping.html b/examples/webgl_shaders_tonemapping.html
index 2b861bc74a584d..954822eec3d30a 100644
--- a/examples/webgl_shaders_tonemapping.html
+++ b/examples/webgl_shaders_tonemapping.html
@@ -37,7 +37,7 @@
Adaptive Tone Mapping
-
+
@@ -158,6 +158,9 @@
fragmentShader: [
+ THREE.ShaderChunk[ "common" ],
+ THREE.ShaderChunk[ "bsdfs" ],
+ THREE.ShaderChunk[ "lights_pars" ],
THREE.ShaderChunk[ "lights_phong_pars_fragment" ],
"void main() {",
@@ -169,12 +172,12 @@
"for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {",
- "vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );",
+ "vec4 lDirection = viewMatrix * vec4( directionalLights[i].direction, 0.0 );",
"vec3 dirVector = normalize( lDirection.xyz );",
"float dotProduct = dot( viewPosition, dirVector );",
"dotProduct = 1.0 * max( dotProduct, 0.0 ) + (1.0 - max( -dot( normal, dirVector ), 0.0 ));",
"dotProduct *= dotProduct;",
- "dirDiffuse += max( 0.5 * dotProduct, 0.0 ) * directionalLightColor[ i ];",
+ "dirDiffuse += max( 0.5 * dotProduct, 0.0 ) * directionalLights[i].color;",
"}",
"#endif",
diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js
index c6c5f3dfee2f72..65cea6a35f943b 100644
--- a/src/renderers/WebGLRenderer.js
+++ b/src/renderers/WebGLRenderer.js
@@ -2011,27 +2011,10 @@ THREE.WebGLRenderer = function ( parameters ) {
function refreshUniformsLights ( uniforms, lights ) {
uniforms.ambientLightColor.value = lights.ambient;
-
- uniforms.directionalLightColor.value = lights.directional.colors;
- uniforms.directionalLightDirection.value = lights.directional.positions;
-
- uniforms.pointLightColor.value = lights.point.colors;
- uniforms.pointLightPosition.value = lights.point.positions;
- uniforms.pointLightDistance.value = lights.point.distances;
- uniforms.pointLightDecay.value = lights.point.decays;
-
- uniforms.spotLightColor.value = lights.spot.colors;
- uniforms.spotLightPosition.value = lights.spot.positions;
- uniforms.spotLightDistance.value = lights.spot.distances;
- uniforms.spotLightDirection.value = lights.spot.directions;
- uniforms.spotLightAngleCos.value = lights.spot.anglesCos;
- uniforms.spotLightExponent.value = lights.spot.exponents;
- uniforms.spotLightDecay.value = lights.spot.decays;
-
- uniforms.hemisphereLightSkyColor.value = lights.hemi.skyColors;
- uniforms.hemisphereLightGroundColor.value = lights.hemi.groundColors;
- uniforms.hemisphereLightDirection.value = lights.hemi.positions;
-
+ uniforms.directionalLights.value = lights.directional;
+ uniforms.pointLights.value = lights.point;
+ uniforms.spotLights.value = lights.spot;
+ uniforms.hemisphereLights.value = lights.hemi;
}
// If uniforms are marked as clean, they don't need to be loaded to the GPU.
@@ -2040,25 +2023,10 @@ THREE.WebGLRenderer = function ( parameters ) {
uniforms.ambientLightColor.needsUpdate = value;
- uniforms.directionalLightColor.needsUpdate = value;
- uniforms.directionalLightDirection.needsUpdate = value;
-
- uniforms.pointLightColor.needsUpdate = value;
- uniforms.pointLightPosition.needsUpdate = value;
- uniforms.pointLightDistance.needsUpdate = value;
- uniforms.pointLightDecay.needsUpdate = value;
-
- uniforms.spotLightColor.needsUpdate = value;
- uniforms.spotLightPosition.needsUpdate = value;
- uniforms.spotLightDistance.needsUpdate = value;
- uniforms.spotLightDirection.needsUpdate = value;
- uniforms.spotLightAngleCos.needsUpdate = value;
- uniforms.spotLightExponent.needsUpdate = value;
- uniforms.spotLightDecay.needsUpdate = value;
-
- uniforms.hemisphereLightSkyColor.needsUpdate = value;
- uniforms.hemisphereLightGroundColor.needsUpdate = value;
- uniforms.hemisphereLightDirection.needsUpdate = value;
+ uniforms.directionalLights.needsUpdate = value;
+ uniforms.pointLights.needsUpdate = value;
+ uniforms.spotLights.needsUpdate = value;
+ uniforms.hemisphereLights.needsUpdate = value;
}
@@ -2254,6 +2222,72 @@ THREE.WebGLRenderer = function ( parameters ) {
break;
+ case 's':
+
+ // TODO: Optimize this.
+ for( var propertyName in uniform.properties ) {
+
+ var property = uniform.properties[ propertyName ];
+ var locationProperty = location[ propertyName ];
+ var valueProperty = value[ propertyName ];
+
+ switch( property.type ) {
+ case 'f':
+ _gl.uniform1f( locationProperty, valueProperty );
+ break;
+ case 'v2':
+ _gl.uniform2f( locationProperty, valueProperty.x, valueProperty.y );
+ break;
+ case 'v3':
+ _gl.uniform3f( locationProperty, valueProperty.x, valueProperty.y, valueProperty.z );
+ break;
+ case 'v4':
+ _gl.uniform4f( locationProperty, valueProperty.x, valueProperty.y, valueProperty.z, valueProperty.w );
+ break;
+ case 'c':
+ _gl.uniform3f( locationProperty, valueProperty.r, valueProperty.g, valueProperty.b );
+ break;
+ };
+
+ }
+
+ break;
+
+ case 'sa':
+
+ // TODO: Optimize this.
+ for( var i = 0; i < value.length; i ++ ) {
+
+ for( var propertyName in uniform.properties ) {
+
+ var property = uniform.properties[ propertyName ];
+ var locationProperty = location[ i ][ propertyName ];
+ var valueProperty = value[i][ propertyName ];
+
+ switch( property.type ) {
+ case 'f':
+ _gl.uniform1f( locationProperty, valueProperty );
+ break;
+ case 'v2':
+ _gl.uniform2f( locationProperty, valueProperty.x, valueProperty.y );
+ break;
+ case 'v3':
+ _gl.uniform3f( locationProperty, valueProperty.x, valueProperty.y, valueProperty.z );
+ break;
+ case 'v4':
+ _gl.uniform4f( locationProperty, valueProperty.x, valueProperty.y, valueProperty.z, valueProperty.w );
+ break;
+ case 'c':
+ _gl.uniform3f( locationProperty, valueProperty.r, valueProperty.g, valueProperty.b );
+ break;
+ };
+
+ }
+
+ }
+
+ break;
+
case 'iv1':
// flat array of integers (JS or typed array)
@@ -2496,60 +2530,22 @@ THREE.WebGLRenderer = function ( parameters ) {
}
- function setColorLinear( array, offset, color, intensity ) {
-
- array[ offset + 0 ] = color.r * intensity;
- array[ offset + 1 ] = color.g * intensity;
- array[ offset + 2 ] = color.b * intensity;
-
- }
-
function setupLights ( lights, camera ) {
var l, ll, light,
r = 0, g = 0, b = 0,
- color, skyColor, groundColor,
+ color,
intensity,
distance,
zlights = _lights,
- viewMatrix = camera.matrixWorldInverse,
-
- dirColors = zlights.directional.colors,
- dirPositions = zlights.directional.positions,
-
- pointColors = zlights.point.colors,
- pointPositions = zlights.point.positions,
- pointDistances = zlights.point.distances,
- pointDecays = zlights.point.decays,
-
- spotColors = zlights.spot.colors,
- spotPositions = zlights.spot.positions,
- spotDistances = zlights.spot.distances,
- spotDirections = zlights.spot.directions,
- spotAnglesCos = zlights.spot.anglesCos,
- spotExponents = zlights.spot.exponents,
- spotDecays = zlights.spot.decays,
-
- hemiSkyColors = zlights.hemi.skyColors,
- hemiGroundColors = zlights.hemi.groundColors,
- hemiPositions = zlights.hemi.positions,
-
- dirLength = 0,
- pointLength = 0,
- spotLength = 0,
- hemiLength = 0,
-
- dirCount = 0,
- pointCount = 0,
- spotCount = 0,
- hemiCount = 0,
+ viewMatrix = camera.matrixWorldInverse;
- dirOffset = 0,
- pointOffset = 0,
- spotOffset = 0,
- hemiOffset = 0;
+ zlights.directional = [];
+ zlights.point = [];
+ zlights.spot = [];
+ zlights.hemi = [];
for ( l = 0, ll = lights.length; l < ll; l ++ ) {
@@ -2569,122 +2565,119 @@ THREE.WebGLRenderer = function ( parameters ) {
} else if ( light instanceof THREE.DirectionalLight ) {
- dirCount += 1;
-
- if ( ! light.visible ) continue;
-
- _direction.setFromMatrixPosition( light.matrixWorld );
- _vector3.setFromMatrixPosition( light.target.matrixWorld );
- _direction.sub( _vector3 );
- _direction.transformDirection( viewMatrix );
+ if( ! light.__webglUniforms ) {
+ light.__webglUniforms = {
+ direction: new THREE.Vector3(),
+ color: new THREE.Color()
+ }
+ }
- dirOffset = dirLength * 3;
+ var lightUniforms = light.__webglUniforms;
+ zlights.directional.push( lightUniforms );
- dirPositions[ dirOffset + 0 ] = _direction.x;
- dirPositions[ dirOffset + 1 ] = _direction.y;
- dirPositions[ dirOffset + 2 ] = _direction.z;
+ if ( ! light.visible ) {
+ lightUniforms.color.setRGB( 0, 0, 0 );
+ continue;
+ }
- setColorLinear( dirColors, dirOffset, color, intensity );
+ lightUniforms.direction.setFromMatrixPosition( light.matrixWorld );
+ _vector3.setFromMatrixPosition( light.target.matrixWorld );
+ lightUniforms.direction.sub( _vector3 );
+ lightUniforms.direction.transformDirection( viewMatrix );
- dirLength += 1;
+ lightUniforms.color.copy( light.color ).multiplyScalar( light.intensity );
} else if ( light instanceof THREE.PointLight ) {
- pointCount += 1;
-
- if ( ! light.visible ) continue;
-
- pointOffset = pointLength * 3;
-
- setColorLinear( pointColors, pointOffset, color, intensity );
+ if( ! light.__webglUniforms ) {
+ light.__webglUniforms = {
+ position: new THREE.Vector3(),
+ color: new THREE.Color(),
+ distance: 0,
+ decay: 0
+ }
+ }
- _vector3.setFromMatrixPosition( light.matrixWorld );
- _vector3.applyMatrix4( viewMatrix );
+ var lightUniforms = light.__webglUniforms;
+ zlights.point.push( lightUniforms );
- pointPositions[ pointOffset + 0 ] = _vector3.x;
- pointPositions[ pointOffset + 1 ] = _vector3.y;
- pointPositions[ pointOffset + 2 ] = _vector3.z;
+ if ( ! light.visible ) {
+ lightUniforms.color.setRGB( 0, 0, 0 );
+ continue;
+ }
- // distance is 0 if decay is 0, because there is no attenuation at all.
- pointDistances[ pointLength ] = distance;
- pointDecays[ pointLength ] = ( light.distance === 0 ) ? 0.0 : light.decay;
+ lightUniforms.position.setFromMatrixPosition( light.matrixWorld );
+ lightUniforms.position.applyMatrix4( viewMatrix );
- pointLength += 1;
+ lightUniforms.color.copy( light.color ).multiplyScalar( light.intensity );
+ lightUniforms.distance = light.distance;
+ lightUniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay;
} else if ( light instanceof THREE.SpotLight ) {
- spotCount += 1;
-
- if ( ! light.visible ) continue;
-
- spotOffset = spotLength * 3;
+ if( ! light.__webglUniforms ) {
+ light.__webglUniforms = {
+ position: new THREE.Vector3(),
+ direction: new THREE.Vector3(),
+ color: new THREE.Color(),
+ distance: 0,
+ decay: 0,
+ angleCos: 0
+ }
+ }
- setColorLinear( spotColors, spotOffset, color, intensity );
+ var lightUniforms = light.__webglUniforms;
+ zlights.spot.push( lightUniforms );
- _direction.setFromMatrixPosition( light.matrixWorld );
- _vector3.copy( _direction ).applyMatrix4( viewMatrix );
+ if ( ! light.visible ) {
+ lightUniforms.color.setRGB( 0, 0, 0 );
+ continue;
+ }
- spotPositions[ spotOffset + 0 ] = _vector3.x;
- spotPositions[ spotOffset + 1 ] = _vector3.y;
- spotPositions[ spotOffset + 2 ] = _vector3.z;
+ lightUniforms.position.setFromMatrixPosition( light.matrixWorld );
+ lightUniforms.position.applyMatrix4( viewMatrix );
- spotDistances[ spotLength ] = distance;
+ lightUniforms.color.copy( color ).multiplyScalar( intensity );
+ lightUniforms.distance = distance;
+ lightUniforms.direction.setFromMatrixPosition( light.matrixWorld );
_vector3.setFromMatrixPosition( light.target.matrixWorld );
- _direction.sub( _vector3 );
- _direction.transformDirection( viewMatrix );
+ lightUniforms.direction.sub( _vector3 );
+ lightUniforms.direction.transformDirection( viewMatrix );
- spotDirections[ spotOffset + 0 ] = _direction.x;
- spotDirections[ spotOffset + 1 ] = _direction.y;
- spotDirections[ spotOffset + 2 ] = _direction.z;
-
- spotAnglesCos[ spotLength ] = Math.cos( light.angle );
- spotExponents[ spotLength ] = light.exponent;
- spotDecays[ spotLength ] = ( light.distance === 0 ) ? 0.0 : light.decay;
-
- spotLength += 1;
+ lightUniforms.angleCos = Math.cos( light.angle );
+ lightUniforms.exponent = light.exponent;
+ lightUniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay;
} else if ( light instanceof THREE.HemisphereLight ) {
- hemiCount += 1;
-
- if ( ! light.visible ) continue;
-
- _direction.setFromMatrixPosition( light.matrixWorld );
- _direction.transformDirection( viewMatrix );
-
- hemiOffset = hemiLength * 3;
+ if( ! light.__webglUniforms ) {
+ light.__webglUniforms = {
+ direction: new THREE.Vector3(),
+ skyColor: new THREE.Color(),
+ groundColor: new THREE.Color()
+ }
+ }
- hemiPositions[ hemiOffset + 0 ] = _direction.x;
- hemiPositions[ hemiOffset + 1 ] = _direction.y;
- hemiPositions[ hemiOffset + 2 ] = _direction.z;
+ var lightUniforms = light.__webglUniforms;
+ zlights.hemi.push( lightUniforms );
- skyColor = light.color;
- groundColor = light.groundColor;
+ if ( ! light.visible ) {
+ lightUniforms.skyColor.setRGB( 0, 0, 0 );
+ continue;
+ }
- setColorLinear( hemiSkyColors, hemiOffset, skyColor, intensity );
- setColorLinear( hemiGroundColors, hemiOffset, groundColor, intensity );
+ lightUniforms.direction.setFromMatrixPosition( light.matrixWorld );
+ lightUniforms.direction.transformDirection( viewMatrix );
+ lightUniforms.direction.normalize();
- hemiLength += 1;
+ lightUniforms.skyColor.copy( light.color ).multiplyScalar( intensity );
+ lightUniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity );
}
}
- // null eventual remains from removed lights
- // (this is to avoid if in shader)
-
- for ( l = dirLength * 3, ll = Math.max( dirColors.length, dirCount * 3 ); l < ll; l ++ ) dirColors[ l ] = 0.0;
- for ( l = pointLength * 3, ll = Math.max( pointColors.length, pointCount * 3 ); l < ll; l ++ ) pointColors[ l ] = 0.0;
- for ( l = spotLength * 3, ll = Math.max( spotColors.length, spotCount * 3 ); l < ll; l ++ ) spotColors[ l ] = 0.0;
- for ( l = hemiLength * 3, ll = Math.max( hemiSkyColors.length, hemiCount * 3 ); l < ll; l ++ ) hemiSkyColors[ l ] = 0.0;
- for ( l = hemiLength * 3, ll = Math.max( hemiGroundColors.length, hemiCount * 3 ); l < ll; l ++ ) hemiGroundColors[ l ] = 0.0;
-
- zlights.directional.length = dirLength;
- zlights.point.length = pointLength;
- zlights.spot.length = spotLength;
- zlights.hemi.length = hemiLength;
-
zlights.ambient[ 0 ] = r;
zlights.ambient[ 1 ] = g;
zlights.ambient[ 2 ] = b;
diff --git a/src/renderers/shaders/ShaderChunk/aomap_fragment.glsl b/src/renderers/shaders/ShaderChunk/aomap_fragment.glsl
index 2f444dbf69515c..fa3d189c6bab28 100644
--- a/src/renderers/shaders/ShaderChunk/aomap_fragment.glsl
+++ b/src/renderers/shaders/ShaderChunk/aomap_fragment.glsl
@@ -1,5 +1,5 @@
#ifdef USE_AOMAP
- totalAmbientLight *= ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;
+ indirectReflectedLight.diffuse *= ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;
#endif
diff --git a/src/renderers/shaders/ShaderChunk/bsdfs.glsl b/src/renderers/shaders/ShaderChunk/bsdfs.glsl
new file mode 100644
index 00000000000000..ef4f7aeebde4ea
--- /dev/null
+++ b/src/renderers/shaders/ShaderChunk/bsdfs.glsl
@@ -0,0 +1,149 @@
+float calcLightAttenuation( float lightDistance, float cutoffDistance, float decayExponent ) {
+
+ if ( decayExponent > 0.0 ) {
+
+ return pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );
+
+ }
+
+ return 1.0;
+
+}
+
+
+vec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {
+
+ // factor of 1/PI in BRDF omitted as incoming light intensity is scaled up by PI because it is considered a punctual light source
+
+ return diffuseColor;
+
+} // validated
+
+
+vec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {
+
+ // Original approximation by Christophe Schlick '94
+ //;float fresnel = pow( 1.0 - dotLH, 5.0 );
+
+ // Optimized variant (presented by Epic at SIGGRAPH '13)
+ float fresnel = exp2( ( -5.55437 * dotLH - 6.98316 ) * dotLH );
+
+ return ( 1.0 - specularColor ) * fresnel + specularColor;
+
+} // validated
+
+
+// Microfacet Models for Refraction through Rough Surfaces - equation (34)
+// http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html
+// alpha is "roughness squared" in Disney’s reparameterization
+float G_GGX_Smith( in float alpha, in float dotNL, in float dotNV ) {
+
+ // geometry term = G(l)⋅G(v) / 4(n⋅l)(n⋅v)
+
+ float a2 = alpha * alpha;
+
+ float gl = dotNL + pow( a2 + ( 1.0 - a2 ) * dotNL * dotNL, 0.5 );
+
+ float gv = dotNV + pow( a2 + ( 1.0 - a2 ) * dotNV * dotNV, 0.5 );
+
+ return 1.0 / ( gl * gv );
+
+} // validated
+
+
+// Microfacet Models for Refraction through Rough Surfaces - equation (33)
+// http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html
+// alpha is "roughness squared" in Disney’s reparameterization
+float D_GGX( in float alpha, in float dotNH ) {
+
+ // factor of 1/PI in distribution term omitted as incoming light intensity is scaled up by PI because it is considered a punctual light source
+
+ float a2 = alpha * alpha;
+
+ float denom = dotNH * dotNH * ( a2 - 1.0 ) + 1.0; // avoid alpha = 0 with dotNH = 1
+
+ return a2 / ( denom * denom );
+
+}
+
+
+// GGX Distribution, Schlick Fresnel, GGX-Smith Visibility
+vec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {
+
+ // factor of 1/PI in BRDF omitted (normally it is in D_GGX) as incoming light intensity is scaled up by PI because it is considered a punctual light source
+
+ float alpha = roughness * roughness; // UE4's roughness
+
+ vec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );
+
+ float dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );
+ float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );
+ float dotNH = saturate( dot( geometry.normal, halfDir ) );
+ float dotLH = saturate( dot( incidentLight.direction, halfDir ) );
+
+ vec3 F = F_Schlick( specularColor, dotLH );
+
+ float G = G_GGX_Smith( alpha, dotNL, dotNV );
+
+ float D = D_GGX( alpha, dotNH );
+
+ return F * ( G * D );
+
+} // validated
+
+
+// ref: https://www.unrealengine.com/blog/physically-based-shading-on-mobile - environmentBRDF for GGX on mobile
+vec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, vec3 specularColor, float roughness ) {
+
+ float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );
+
+ const vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );
+
+ const vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );
+
+ vec4 r = roughness * c0 + c1;
+
+ float a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;
+
+ vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;
+
+ return specularColor * AB.x + AB.y;
+
+} // validated
+
+
+float G_BlinnPhong_Implicit( /* in float dotNL, in float dotNV */ ) {
+
+ // geometry term is (n dot l)(n dot v) / 4(n dot l)(n dot v)
+ return 0.25;
+
+}
+
+float D_BlinnPhong( const in float shininess, const in float dotNH ) {
+
+ // factor of 1/PI in distribution term omitted as incoming light intensity is scaled up by PI because it is considered a punctual light source
+
+ return ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );
+
+}
+
+vec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {
+
+ // factor of 1/PI in BRDF omitted (normally it is in D_BlinnPhong) as incoming light intensity is scaled up by PI because it is considered a punctual light source
+
+ vec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );
+
+ //float dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );
+ //float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );
+ float dotNH = saturate( dot( geometry.normal, halfDir ) );
+ float dotLH = saturate( dot( incidentLight.direction, halfDir ) );
+
+ vec3 F = F_Schlick( specularColor, dotLH );
+
+ float G = G_BlinnPhong_Implicit( /* dotNL, dotNV */ );
+
+ float D = D_BlinnPhong( shininess, dotNH );
+
+ return F * ( G * D );
+
+} // validated
\ No newline at end of file
diff --git a/src/renderers/shaders/ShaderChunk/common.glsl b/src/renderers/shaders/ShaderChunk/common.glsl
index 3b00e0d5cb88db..642f55ce526d90 100644
--- a/src/renderers/shaders/ShaderChunk/common.glsl
+++ b/src/renderers/shaders/ShaderChunk/common.glsl
@@ -1,5 +1,6 @@
#define PI 3.14159
#define PI2 6.28318
+#define RECIPROCAL_PI 0.31830988618
#define RECIPROCAL_PI2 0.15915494
#define LOG2 1.442695
#define EPSILON 1e-6
@@ -7,6 +8,26 @@
#define saturate(a) clamp( a, 0.0, 1.0 )
#define whiteCompliment(a) ( 1.0 - saturate( a ) )
+float average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }
+
+
+struct IncidentLight {
+ vec3 color;
+ vec3 direction;
+};
+
+struct ReflectedLight {
+ vec3 specular;
+ vec3 diffuse;
+};
+
+struct GeometricContext {
+ vec3 position;
+ vec3 normal;
+ vec3 viewDir;
+};
+
+
vec3 transformDirection( in vec3 normal, in mat4 matrix ) {
return normalize( ( matrix * vec4( normal, 0.0 ) ).xyz );
@@ -40,148 +61,6 @@ vec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 poi
}
-float calcLightAttenuation( float lightDistance, float cutoffDistance, float decayExponent ) {
-
- if ( decayExponent > 0.0 ) {
-
- return pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );
-
- }
-
- return 1.0;
-
-}
-
-vec3 F_Schlick( in vec3 specularColor, in float dotLH ) {
-
- // Original approximation by Christophe Schlick '94
- //;float fresnel = pow( 1.0 - dotLH, 5.0 );
-
- // Optimized variant (presented by Epic at SIGGRAPH '13)
- float fresnel = exp2( ( -5.55437 * dotLH - 6.98316 ) * dotLH );
-
- return ( 1.0 - specularColor ) * fresnel + specularColor;
-
-}
-
-float G_BlinnPhong_Implicit( /* in float dotNL, in float dotNV */ ) {
-
- // geometry term is (n⋅l)(n⋅v) / 4(n⋅l)(n⋅v)
-
- return 0.25;
-
-}
-
-float D_BlinnPhong( in float shininess, in float dotNH ) {
-
- // factor of 1/PI in distribution term omitted
-
- return ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );
-
-}
-
-vec3 BRDF_BlinnPhong( in vec3 specularColor, in float shininess, in vec3 normal, in vec3 lightDir, in vec3 viewDir ) {
-
- vec3 halfDir = normalize( lightDir + viewDir );
-
- //float dotNL = saturate( dot( normal, lightDir ) );
- //float dotNV = saturate( dot( normal, viewDir ) );
- float dotNH = saturate( dot( normal, halfDir ) );
- float dotLH = saturate( dot( lightDir, halfDir ) );
-
- vec3 F = F_Schlick( specularColor, dotLH );
-
- float G = G_BlinnPhong_Implicit( /* dotNL, dotNV */ );
-
- float D = D_BlinnPhong( shininess, dotNH );
-
- return F * G * D;
-
-}
-
-// Microfacet Models for Refraction through Rough Surfaces - equation (34)
-// http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html
-// alpha is "roughness squared" in Disney’s reparameterization
-float G_GGX_Smith( in float alpha, in float dotNL, in float dotNV ) {
-
- // geometry term = G(l)⋅G(v) / 4(n⋅l)(n⋅v)
-
- float a2 = alpha * alpha;
-
- float gl = dotNL + pow( a2 + ( 1.0 - a2 ) * dotNL * dotNL, 0.5 );
-
- float gv = dotNV + pow( a2 + ( 1.0 - a2 ) * dotNV * dotNV, 0.5 );
-
- return 1.0 / ( gl * gv );
-
-}
-
-// Microfacet Models for Refraction through Rough Surfaces - equation (33)
-// http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html
-// alpha is "roughness squared" in Disney’s reparameterization
-float D_GGX( in float alpha, in float dotNH ) {
-
- // factor of 1/PI in distribution term omitted
-
- float a2 = alpha * alpha;
-
- float denom = dotNH * dotNH * ( a2 - 1.0 ) + 1.0; // avoid alpha = 0 with dotNH = 1
-
- return a2 / ( denom * denom );
-
-}
-
-// GGX Distribution, Schlick Fresnel, GGX-Smith Visibility
-vec3 BRDF_GGX( in vec3 specularColor, in float roughness, in vec3 normal, in vec3 lightDir, in vec3 viewDir ) {
-
- // factor of 1/PI in BRDF omitted
-
- float alpha = roughness * roughness; // UE4's roughness
-
- vec3 halfDir = normalize( lightDir + viewDir );
-
- float dotNL = saturate( dot( normal, lightDir ) );
- float dotNV = saturate( dot( normal, viewDir ) );
- float dotNH = saturate( dot( normal, halfDir ) );
- float dotLH = saturate( dot( lightDir, halfDir ) );
-
- vec3 F = F_Schlick( specularColor, dotLH );
-
- float G = G_GGX_Smith( alpha, dotNL, dotNV );
-
- float D = D_GGX( alpha, dotNH );
-
- return F * G * D;
-
-}
-
-vec3 BRDF_Lambert( in vec3 diffuseColor ) {
-
- // factor of 1/PI in BRDF omitted
-
- return diffuseColor;
-
-}
-
-// ref: https://www.unrealengine.com/blog/physically-based-shading-on-mobile - environmentBRDF for GGX on mobile
-vec3 envBRDFApprox( vec3 specularColor, float roughness, in vec3 normal, in vec3 viewDir ) {
-
- float dotNV = saturate( dot( normal, viewDir ) );
-
- const vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );
-
- const vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );
-
- vec4 r = roughness * c0 + c1;
-
- float a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;
-
- vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;
-
- return specularColor * AB.x + AB.y;
-
-}
-
vec3 inputToLinear( in vec3 a ) {
#ifdef GAMMA_INPUT
diff --git a/src/renderers/shaders/ShaderChunk/envmap_physical_fragment.glsl b/src/renderers/shaders/ShaderChunk/envmap_physical_fragment.glsl
deleted file mode 100644
index c50a7f9a9af1c3..00000000000000
--- a/src/renderers/shaders/ShaderChunk/envmap_physical_fragment.glsl
+++ /dev/null
@@ -1,63 +0,0 @@
-#ifdef USE_ENVMAP
-
- float reflectivityFactor = reflectivity; // fix add map - replace specular strength?
-
- vec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );
-
- // Transforming Normal Vectors with the Inverse Transformation
- vec3 worldNormal = inverseTransformDirection( normal, viewMatrix );
-
- #ifdef ENVMAP_MODE_REFLECTION
-
- vec3 reflectVec = reflect( cameraToVertex, worldNormal );
-
- #else
-
- vec3 reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );
-
- #endif
-
- #ifdef DOUBLE_SIDED
-
- float flipNormal = ( float( gl_FrontFacing ) * 2.0 - 1.0 );
-
- #else
-
- float flipNormal = 1.0;
-
- #endif
-
- #ifdef ENVMAP_TYPE_CUBE
-
- #if defined( TEXTURE_CUBE_LOD_EXT )
-
- float bias = pow( roughness, 0.5 ) * 7.0; // from bhouston - there are other models for this calculation (roughness; not roughnesFactor)
-
- vec4 envMapColor = textureCubeLodEXT( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ), bias );
-
- #else
-
- vec4 envMapColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );
-
- #endif
-
- #elif defined( ENVMAP_TYPE_EQUIREC )
-
- vec2 sampleUV;
- sampleUV.y = saturate( flipNormal * reflectVec.y * 0.5 + 0.5 );
- sampleUV.x = atan( flipNormal * reflectVec.z, flipNormal * reflectVec.x ) * RECIPROCAL_PI2 + 0.5;
- vec4 envMapColor = texture2D( envMap, sampleUV );
-
- #elif defined( ENVMAP_TYPE_SPHERE )
-
- vec3 reflectView = flipNormal * normalize((viewMatrix * vec4( reflectVec, 0.0 )).xyz + vec3(0.0,0.0,1.0));
- vec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );
-
- #endif
-
- envMapColor.rgb = inputToLinear( envMapColor.rgb );
-
- outgoingLight += envBRDFApprox( specularColor, roughnessFactor, normal, viewDir ) * envMapColor.rgb * envMapIntensity * reflectivityFactor;
-
-#endif
-
diff --git a/src/renderers/shaders/ShaderChunk/hemilight_fragment.glsl b/src/renderers/shaders/ShaderChunk/hemilight_fragment.glsl
deleted file mode 100644
index e6899b2a6c8cc1..00000000000000
--- a/src/renderers/shaders/ShaderChunk/hemilight_fragment.glsl
+++ /dev/null
@@ -1,18 +0,0 @@
-#if MAX_HEMI_LIGHTS > 0
-
- for ( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {
-
- vec3 lightDir = hemisphereLightDirection[ i ];
-
- float dotProduct = dot( normal, lightDir );
-
- float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;
-
- vec3 lightColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );
-
- totalAmbientLight += lightColor;
-
- }
-
-#endif
-
diff --git a/src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl b/src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl
deleted file mode 100644
index 803ab91a6e5f0c..00000000000000
--- a/src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl
+++ /dev/null
@@ -1,5 +0,0 @@
-#ifdef USE_LIGHTMAP
-
- totalAmbientLight += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;
-
-#endif
diff --git a/src/renderers/shaders/ShaderChunk/lights_lambert_vertex.glsl b/src/renderers/shaders/ShaderChunk/lights_lambert_vertex.glsl
index 66c995f2c77118..1b4b80a163b691 100644
--- a/src/renderers/shaders/ShaderChunk/lights_lambert_vertex.glsl
+++ b/src/renderers/shaders/ShaderChunk/lights_lambert_vertex.glsl
@@ -1,35 +1,22 @@
-vLightFront = vec3( 0.0 );
+vec3 diffuse = vec3( 1.0 );
-#ifdef DOUBLE_SIDED
-
- vLightBack = vec3( 0.0 );
-
-#endif
-
-vec3 normal = normalize( transformedNormal );
+GeometricContext geometry = GeometricContext( mvPosition.xyz, normalize( transformedNormal ), normalize( -mvPosition.xyz ) );
+GeometricContext backGeometry = GeometricContext( geometry.position, -geometry.normal, geometry.viewDir );
#if MAX_POINT_LIGHTS > 0
for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {
- vec3 lightColor = pointLightColor[ i ];
-
- vec3 lVector = pointLightPosition[ i ] - mvPosition.xyz;
- vec3 lightDir = normalize( lVector );
-
- // attenuation
-
- float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecay[ i ] );
-
- // diffuse
+ IncidentLight directLight = getPointDirectLight( pointLights[ i ], geometry );
- float dotProduct = dot( normal, lightDir );
+ float dotNL = dot( geometry.normal, directLight.direction );
+ vec3 directLightColor_Diffuse = directLight.color * BRDF_Diffuse_Lambert( diffuse );
- vLightFront += lightColor * attenuation * saturate( dotProduct );
+ vLightFront += saturate( dotNL ) * directLightColor_Diffuse;
#ifdef DOUBLE_SIDED
- vLightBack += lightColor * attenuation * saturate( - dotProduct );
+ vLightBack += saturate( -dotNL ) * directLightColor_Diffuse;
#endif
@@ -41,38 +28,18 @@ vec3 normal = normalize( transformedNormal );
for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {
- vec3 lightColor = spotLightColor[ i ];
-
- vec3 lightPosition = spotLightPosition[ i ];
- vec3 lVector = lightPosition - mvPosition.xyz;
- vec3 lightDir = normalize( lVector );
-
- float spotEffect = dot( spotLightDirection[ i ], lightDir );
-
- if ( spotEffect > spotLightAngleCos[ i ] ) {
-
- spotEffect = saturate( pow( saturate( spotEffect ), spotLightExponent[ i ] ) );
-
- // attenuation
-
- float attenuation = calcLightAttenuation( length( lVector ), spotLightDistance[ i ], spotLightDecay[ i ] );
-
- attenuation *= spotEffect;
+ IncidentLight directLight = getSpotDirectLight( spotLights[ i ], geometry );
- // diffuse
+ float dotNL = dot( geometry.normal, directLight.direction );
+ vec3 directLightColor_Diffuse = directLight.color * BRDF_Diffuse_Lambert( diffuse );
- float dotProduct = dot( normal, lightDir );
+ vLightFront += saturate( dotNL ) * directLightColor_Diffuse;
- vLightFront += lightColor * attenuation * saturate( dotProduct );
-
- #ifdef DOUBLE_SIDED
-
- vLightBack += lightColor * attenuation * saturate( - dotProduct );
-
- #endif
+ #ifdef DOUBLE_SIDED
- }
+ vLightBack += saturate( -dotNL ) * directLightColor_Diffuse;
+ #endif
}
#endif
@@ -81,19 +48,16 @@ vec3 normal = normalize( transformedNormal );
for ( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {
- vec3 lightColor = directionalLightColor[ i ];
-
- vec3 lightDir = directionalLightDirection[ i ];
-
- // diffuse
+ IncidentLight directLight = getDirectionalDirectLight( directionalLights[ i ], geometry );
- float dotProduct = dot( normal, lightDir );
+ float dotNL = dot( geometry.normal, directLight.direction );
+ vec3 directLightColor_Diffuse = directLight.color * BRDF_Diffuse_Lambert( diffuse );
- vLightFront += lightColor * saturate( dotProduct );
+ vLightFront += saturate( dotNL ) * directLightColor_Diffuse;
#ifdef DOUBLE_SIDED
- vLightBack += lightColor * saturate( - dotProduct );
+ vLightBack += saturate( -dotNL ) * directLightColor_Diffuse;
#endif
@@ -101,28 +65,33 @@ vec3 normal = normalize( transformedNormal );
#endif
-#if MAX_HEMI_LIGHTS > 0
+ {
+ // dotNL is always one, and diffuseColor is vec3(1.0), thus the result is equivalent to summing indirectDiffuse lights
+ //float frontDotNL = saturate( dot( geometry.normal, frontIndirectLight.direction ) );
+ //vLightFront += frontDotNL * frontIndirectLight.color * BRDF_Diffuse_Lambert( diffuse );
+
+ vLightFront += ambientLightColor;
- for ( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {
-
- vec3 lightDir = hemisphereLightDirection[ i ];
+ #ifdef DOUBLE_SIDED
+
+ vLightBack += ambientLightColor;
- // diffuse
+ #endif
- float dotProduct = dot( normal, lightDir );
+ #if MAX_HEMI_LIGHTS > 0
- float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;
+ for ( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {
- vLightFront += mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );
+ vLightFront += getHemisphereIndirectLightColor( hemisphereLights[ i ], geometry );
- #ifdef DOUBLE_SIDED
+ #ifdef DOUBLE_SIDED
+
+ vLightBack += getHemisphereIndirectLightColor( hemisphereLights[ i ], backGeometry );
- float hemiDiffuseWeightBack = - 0.5 * dotProduct + 0.5;
+ #endif
- vLightBack += mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeightBack );
+ }
#endif
- }
-
-#endif
+ }
\ No newline at end of file
diff --git a/src/renderers/shaders/ShaderChunk/lights_pars.glsl b/src/renderers/shaders/ShaderChunk/lights_pars.glsl
index 13acc458dd5a58..67abcf6127d239 100644
--- a/src/renderers/shaders/ShaderChunk/lights_pars.glsl
+++ b/src/renderers/shaders/ShaderChunk/lights_pars.glsl
@@ -1,35 +1,167 @@
+uniform vec3 ambientLightColor;
+
+
#if MAX_DIR_LIGHTS > 0
- uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];
- uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];
+ struct DirectionalLight {
+ vec3 direction;
+ vec3 color;
+ };
-#endif
+ uniform DirectionalLight directionalLights[ MAX_DIR_LIGHTS ];
-#if MAX_HEMI_LIGHTS > 0
+ IncidentLight getDirectionalDirectLight( const in DirectionalLight directionalLight, const in GeometricContext geometry ) {
- uniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];
- uniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];
- uniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ];
+ IncidentLight directLight;
+
+ directLight.color = directionalLight.color;
+ directLight.direction = directionalLight.direction;
+
+ return directLight;
+ }
#endif
+
#if MAX_POINT_LIGHTS > 0
- uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];
- uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];
- uniform float pointLightDistance[ MAX_POINT_LIGHTS ];
- uniform float pointLightDecay[ MAX_POINT_LIGHTS ];
+ struct PointLight {
+ vec3 position;
+ vec3 color;
+ float distance;
+ float decay;
+ };
+
+ uniform PointLight pointLights[ MAX_POINT_LIGHTS ];
+
+ IncidentLight getPointDirectLight( const in PointLight pointLight, const in GeometricContext geometry ) {
+
+ IncidentLight directLight;
+
+ vec3 lVector = pointLight.position - geometry.position;
+ directLight.direction = normalize( lVector );
+
+ directLight.color = pointLight.color;
+ directLight.color *= calcLightAttenuation( length( lVector ), pointLight.distance, pointLight.decay );
+
+ return directLight;
+ }
#endif
+
#if MAX_SPOT_LIGHTS > 0
- uniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];
- uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];
- uniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];
- uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];
- uniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ];
- uniform float spotLightExponent[ MAX_SPOT_LIGHTS ];
- uniform float spotLightDecay[ MAX_SPOT_LIGHTS ];
+ struct SpotLight {
+ vec3 position;
+ vec3 direction;
+ vec3 color;
+ float distance;
+ float decay;
+ float angleCos;
+ float exponent;
+ };
+
+ uniform SpotLight spotLights[ MAX_SPOT_LIGHTS ];
+
+ IncidentLight getSpotDirectLight( const in SpotLight spotLight, const in GeometricContext geometry ) {
+
+ IncidentLight directLight;
+
+ vec3 lVector = spotLight.position - geometry.position;
+ directLight.direction = normalize( lVector );
+
+ float spotEffect = dot( spotLight.direction, directLight.direction );
+ spotEffect = saturate( pow( saturate( spotEffect ), spotLight.exponent ) );
+
+ directLight.color = spotLight.color;
+ directLight.color *= ( spotEffect * calcLightAttenuation( length( lVector ), spotLight.distance, spotLight.decay ) );
+
+ return directLight;
+ }
#endif
+
+
+#if MAX_HEMI_LIGHTS > 0
+
+ struct HemisphereLight {
+ vec3 direction;
+ vec3 skyColor;
+ vec3 groundColor;
+ };
+
+ uniform HemisphereLight hemisphereLights[ MAX_HEMI_LIGHTS ];
+
+ vec3 getHemisphereIndirectLightColor( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {
+
+ float dotNL = dot( geometry.normal, hemiLight.direction );
+ float hemiDiffuseWeight = 0.5 * dotNL + 0.5;
+
+ return mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );
+
+ }
+
+#endif
+
+
+#if defined( USE_ENVMAP ) && defined( PHYSICAL )
+
+ vec3 getSpecularLightProbeIndirectLightColor( /*const in SpecularLightProbe specularLightProbe,*/ const in GeometricContext geometry, const in float lodLevel ) {
+
+ #ifdef ENVMAP_MODE_REFLECTION
+
+ vec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );
+
+ #else
+
+ vec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );
+
+ #endif
+
+ #ifdef DOUBLE_SIDED
+
+ float flipNormal = ( float( gl_FrontFacing ) * 2.0 - 1.0 );
+
+ #else
+
+ float flipNormal = 1.0;
+
+ #endif
+
+ reflectVec = inverseTransformDirection( reflectVec, viewMatrix );
+
+ #ifdef ENVMAP_TYPE_CUBE
+
+ #if defined( TEXTURE_CUBE_LOD_EXT )
+
+ vec4 envMapColor = textureCubeLodEXT( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ), lodLevel );
+
+ #else
+
+ vec4 envMapColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );
+
+ #endif
+
+ #elif defined( ENVMAP_TYPE_EQUIREC )
+
+ vec2 sampleUV;
+ sampleUV.y = saturate( flipNormal * reflectVec.y * 0.5 + 0.5 );
+ sampleUV.x = atan( flipNormal * reflectVec.z, flipNormal * reflectVec.x ) * RECIPROCAL_PI2 + 0.5;
+ vec4 envMapColor = texture2D( envMap, sampleUV );
+
+ #elif defined( ENVMAP_TYPE_SPHERE )
+
+ vec3 reflectView = flipNormal * normalize((viewMatrix * vec4( reflectVec, 0.0 )).xyz + vec3(0.0,0.0,1.0));
+ vec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );
+
+ #endif
+
+ envMapColor.rgb = inputToLinear( envMapColor.rgb );
+
+ return envMapColor.rgb * reflectivity;
+
+ }
+
+#endif
+
diff --git a/src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl b/src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl
index 4bf3415b65f807..51b5c12886bef0 100644
--- a/src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl
+++ b/src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl
@@ -1,99 +1,10 @@
-vec3 viewDir = normalize( vViewPosition );
+BlinnPhongMaterial material;
+material.specularColor = specular;
+material.specularShininess = shininess;
+material.diffuseColor = diffuseColor.rgb;
-vec3 totalDiffuseLight = vec3( 0.0 );
-vec3 totalSpecularLight = vec3( 0.0 );
+#ifdef METAL
-#if MAX_POINT_LIGHTS > 0
+ material.diffuseColor = vec3( 0.0 );
- for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {
-
- vec3 lightColor = pointLightColor[ i ];
-
- vec3 lightPosition = pointLightPosition[ i ];
- vec3 lVector = lightPosition + vViewPosition.xyz;
- vec3 lightDir = normalize( lVector );
-
- // attenuation
-
- float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecay[ i ] );
-
- // diffuse
-
- float cosineTerm = saturate( dot( normal, lightDir ) );
-
- totalDiffuseLight += lightColor * attenuation * cosineTerm;
-
- // specular
-
- vec3 brdf = BRDF_BlinnPhong( specular, shininess, normal, lightDir, viewDir );
-
- totalSpecularLight += brdf * specularStrength * lightColor * attenuation * cosineTerm;
-
-
- }
-
-#endif
-
-#if MAX_SPOT_LIGHTS > 0
-
- for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {
-
- vec3 lightColor = spotLightColor[ i ];
-
- vec3 lightPosition = spotLightPosition[ i ];
- vec3 lVector = lightPosition + vViewPosition.xyz;
- vec3 lightDir = normalize( lVector );
-
- float spotEffect = dot( spotLightDirection[ i ], lightDir );
-
- if ( spotEffect > spotLightAngleCos[ i ] ) {
-
- spotEffect = saturate( pow( saturate( spotEffect ), spotLightExponent[ i ] ) );
-
- // attenuation
-
- float attenuation = calcLightAttenuation( length( lVector ), spotLightDistance[ i ], spotLightDecay[ i ] );
-
- attenuation *= spotEffect;
-
- // diffuse
-
- float cosineTerm = saturate( dot( normal, lightDir ) );
-
- totalDiffuseLight += lightColor * attenuation * cosineTerm;
-
- // specular
-
- vec3 brdf = BRDF_BlinnPhong( specular, shininess, normal, lightDir, viewDir );
-
- totalSpecularLight += brdf * specularStrength * lightColor * attenuation * cosineTerm;
-
- }
-
- }
-
-#endif
-
-#if MAX_DIR_LIGHTS > 0
-
- for ( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {
-
- vec3 lightColor = directionalLightColor[ i ];
-
- vec3 lightDir = directionalLightDirection[ i ];
-
- // diffuse
-
- float cosineTerm = saturate( dot( normal, lightDir ) );
-
- totalDiffuseLight += lightColor * cosineTerm;
-
- // specular
-
- vec3 brdf = BRDF_BlinnPhong( specular, shininess, normal, lightDir, viewDir );
-
- totalSpecularLight += brdf * specularStrength * lightColor * cosineTerm;
-
- }
-
-#endif
+#endif
\ No newline at end of file
diff --git a/src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl b/src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl
index 109bc9fc7c23ba..f3e18c4ab86a03 100644
--- a/src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl
+++ b/src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl
@@ -1,5 +1,3 @@
-uniform vec3 ambientLightColor;
-
#if MAX_SPOT_LIGHTS > 0 || defined( USE_ENVMAP )
varying vec3 vWorldPosition;
@@ -13,3 +11,34 @@ varying vec3 vViewPosition;
varying vec3 vNormal;
#endif
+
+
+struct BlinnPhongMaterial {
+ vec3 diffuseColor;
+ float specularShininess;
+ vec3 specularColor;
+};
+
+void BlinnPhongMaterial_RE_DirectLight( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight directReflectedLight ) {
+
+ float dotNL = saturate( dot( geometry.normal, directLight.direction ) );
+
+ directReflectedLight.diffuse += dotNL * directLight.color * BRDF_Diffuse_Lambert( material.diffuseColor );
+
+ directReflectedLight.specular += dotNL * directLight.color * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess );
+
+}
+
+#define Material_RE_DirectLight BlinnPhongMaterial_RE_DirectLight
+
+void BlinnPhongMaterial_RE_IndirectDiffuseLight( const in vec3 indirectDiffuseColor, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight indirectReflectedLight ) {
+
+ //float dotNL = saturate( dot( geometry.normal, indirectLight.direction ) ); not required because result is always 1.0
+
+ indirectReflectedLight.diffuse += indirectDiffuseColor * BRDF_Diffuse_Lambert( material.diffuseColor );
+
+}
+
+#define Material_RE_IndirectDiffuseLight BlinnPhongMaterial_RE_IndirectDiffuseLight
+
+#define Material_LightProbeLOD( material ) (0)
diff --git a/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl b/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl
index 5275a780c3e471..49883408aef27e 100644
--- a/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl
+++ b/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl
@@ -1,112 +1,4 @@
-vec3 viewDir = normalize( vViewPosition );
-
-vec3 totalDiffuseLight = vec3( 0.0 );
-vec3 totalSpecularLight = vec3( 0.0 );
-
-
-// roughness linear remapping
-
-roughnessFactor = roughnessFactor * 0.5 + 0.5; // disney's remapping of [ 0, 1 ] roughness to [ 0.5, 1 ]
-
-
-// metalness effect on color
-
-vec3 specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );
-
-diffuseColor.rgb *= ( 1.0 - metalnessFactor );
-
-
-#if MAX_POINT_LIGHTS > 0
-
- for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {
-
- vec3 lightColor = pointLightColor[ i ];
-
- vec3 lightPosition = pointLightPosition[ i ];
- vec3 lVector = lightPosition + vViewPosition.xyz;
- vec3 lightDir = normalize( lVector );
-
- // attenuation
-
- float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecay[ i ] );
-
- // diffuse
-
- float cosineTerm = saturate( dot( normal, lightDir ) );
-
- totalDiffuseLight += lightColor * attenuation * cosineTerm;
-
- // specular
-
- vec3 brdf = BRDF_GGX( specularColor, roughnessFactor, normal, lightDir, viewDir );
-
- totalSpecularLight += brdf * specularStrength * lightColor * attenuation * cosineTerm;
-
-
- }
-
-#endif
-
-#if MAX_SPOT_LIGHTS > 0
-
- for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {
-
- vec3 lightColor = spotLightColor[ i ];
-
- vec3 lightPosition = spotLightPosition[ i ];
- vec3 lVector = lightPosition + vViewPosition.xyz;
- vec3 lightDir = normalize( lVector );
-
- float spotEffect = dot( spotLightDirection[ i ], lightDir );
-
- if ( spotEffect > spotLightAngleCos[ i ] ) {
-
- spotEffect = saturate( pow( saturate( spotEffect ), spotLightExponent[ i ] ) );
-
- // attenuation
-
- float attenuation = calcLightAttenuation( length( lVector ), spotLightDistance[ i ], spotLightDecay[ i ] );
-
- attenuation *= spotEffect;
-
- // diffuse
-
- float cosineTerm = saturate( dot( normal, lightDir ) );
-
- totalDiffuseLight += lightColor * attenuation * cosineTerm;
-
- // specular
-
- vec3 brdf = BRDF_GGX( specularColor, roughnessFactor, normal, lightDir, viewDir );
-
- totalSpecularLight += brdf * specularStrength * lightColor * attenuation * cosineTerm;
-
- }
-
- }
-
-#endif
-
-#if MAX_DIR_LIGHTS > 0
-
- for ( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {
-
- vec3 lightColor = directionalLightColor[ i ];
-
- vec3 lightDir = directionalLightDirection[ i ];
-
- // diffuse
-
- float cosineTerm = saturate( dot( normal, lightDir ) );
-
- totalDiffuseLight += lightColor * cosineTerm;
-
- // specular
-
- vec3 brdf = BRDF_GGX( specularColor, roughnessFactor, normal, lightDir, viewDir );
-
- totalSpecularLight += brdf * specularStrength * lightColor * cosineTerm;
-
- }
-
-#endif
+PhysicalMaterial material;
+material.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );
+material.specularRoughness = roughnessFactor * 0.5 + 0.5; // disney's remapping of [ 0, 1 ] roughness to [ 0.5, 1 ]
+material.specularColor = mix( vec3( 0.04 ) * reflectivity, diffuseColor.rgb, metalnessFactor );
diff --git a/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl b/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl
new file mode 100644
index 00000000000000..aec3d056f4ffb7
--- /dev/null
+++ b/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl
@@ -0,0 +1,42 @@
+struct PhysicalMaterial {
+ vec3 diffuseColor;
+ float specularRoughness;
+ vec3 specularColor;
+ float clearCoatWeight;
+ float clearCoatRoughness;
+};
+
+void PhysicalMaterial_RE_DirectLight( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight directReflectedLight ) {
+
+ float dotNL = saturate( dot( geometry.normal, directLight.direction ) );
+
+ directReflectedLight.diffuse += dotNL * directLight.color * BRDF_Diffuse_Lambert( material.diffuseColor );
+ directReflectedLight.specular += dotNL * directLight.color * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );
+
+}
+#define Material_RE_DirectLight PhysicalMaterial_RE_DirectLight
+
+
+void PhysicalMaterial_RE_DiffuseIndirectLight( const in vec3 indirectDiffuseColor, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight indirectReflectedLight ) {
+
+ //float dotNL = saturate( dot( geometry.normal, indirectLight.direction ) ); not required because result is always 1.0
+
+ indirectReflectedLight.diffuse += indirectDiffuseColor * BRDF_Diffuse_Lambert( material.diffuseColor );
+
+}
+
+#define Material_RE_IndirectDiffuseLight PhysicalMaterial_RE_DiffuseIndirectLight
+
+
+void PhysicalMaterial_RE_SpecularIndirectLight( const in vec3 indirectSpecularColor, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight indirectReflectedLight ) {
+
+ //float dotNL = saturate( dot( geometry.normal, indirectLight.direction ) ); not required because result is always 1.0
+
+ indirectReflectedLight.specular += indirectSpecularColor * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );
+
+}
+
+// from bhouston - there are other models for this calculation (roughness; not roughnesFactor)
+#define Material_LightProbeLOD( material ) (pow( ( material.specularRoughness - 0.5 ) * 2.0, 0.5 ) * 7.0)
+
+#define Material_RE_IndirectSpecularLight PhysicalMaterial_RE_SpecularIndirectLight
diff --git a/src/renderers/shaders/ShaderChunk/lights_template.glsl b/src/renderers/shaders/ShaderChunk/lights_template.glsl
new file mode 100644
index 00000000000000..5b522a6f9256f1
--- /dev/null
+++ b/src/renderers/shaders/ShaderChunk/lights_template.glsl
@@ -0,0 +1,92 @@
+//
+// This is a template that can be used to light a material, it uses pluggable RenderEquations (RE)
+// for specific lighting scenarios.
+//
+// Instructions for use:
+// - Ensure that both Material_RE_DirectLight, Material_RE_IndirectDiffuseLight and Material_RE_IndirectSpecularLight are defined
+// - If you have defined a Material_RE_IndirectSpecularLight, you need to also provide a Material_LightProbeLOD.
+// - Create a material parameter that is to be passed as the third parameter to your lighting functions.
+//
+// TODO:
+// - Add area light support.
+// - Add sphere light support.
+// - Add diffuse light probe (irradiance cubemap) support.
+//
+
+GeometricContext geometry = GeometricContext( -vViewPosition, normalize( normal ), normalize(vViewPosition ) );
+
+#if ( MAX_POINT_LIGHTS > 0 ) && defined( Material_RE_DirectLight )
+
+ for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {
+
+ IncidentLight directLight = getPointDirectLight( pointLights[ i ], geometry );
+
+ Material_RE_DirectLight( directLight, geometry, material, directReflectedLight );
+
+ }
+
+#endif
+
+#if ( MAX_SPOT_LIGHTS > 0 ) && defined( Material_RE_DirectLight )
+
+ for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {
+
+ IncidentLight directLight = getSpotDirectLight( spotLights[ i ], geometry );
+
+ Material_RE_DirectLight( directLight, geometry, material, directReflectedLight );
+
+ }
+
+#endif
+
+#if ( MAX_DIR_LIGHTS > 0 ) && defined( Material_RE_DirectLight )
+
+ for ( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {
+
+ IncidentLight directLight = getDirectionalDirectLight( directionalLights[ i ], geometry );
+
+ Material_RE_DirectLight( directLight, geometry, material, directReflectedLight );
+
+ }
+
+#endif
+
+#if defined( Material_RE_IndirectDiffuseLight )
+
+ {
+
+ vec3 indirectDiffuseColor = ambientLightColor;
+
+#ifdef USE_LIGHTMAP
+
+ indirectDiffuseColor += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;
+
+#endif
+
+#if ( MAX_HEMI_LIGHTS > 0 )
+
+ for ( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {
+
+ indirectDiffuseColor += getHemisphereIndirectLightColor( hemisphereLights[ i ], geometry );
+
+ }
+
+#endif
+
+ Material_RE_IndirectDiffuseLight( indirectDiffuseColor, geometry, material, indirectReflectedLight );
+
+ }
+
+#endif
+
+#if defined( USE_ENVMAP ) && defined( Material_RE_IndirectSpecularLight )
+
+ {
+
+ vec3 indirectSpecularColor = getSpecularLightProbeIndirectLightColor( /*specularLightProbe,*/ geometry, Material_LightProbeLOD( material ) );
+
+ Material_RE_IndirectSpecularLight( indirectSpecularColor, geometry, material, indirectReflectedLight );
+
+ }
+
+#endif
\ No newline at end of file
diff --git a/src/renderers/shaders/ShaderLib.js b/src/renderers/shaders/ShaderLib.js
index 947bc1b935e0e5..6fc01a2d8500d7 100644
--- a/src/renderers/shaders/ShaderLib.js
+++ b/src/renderers/shaders/ShaderLib.js
@@ -67,6 +67,12 @@ THREE.ShaderLib = {
"uniform vec3 diffuse;",
"uniform float opacity;",
+ "#ifndef FLAT_SHADED",
+
+ " varying vec3 vNormal;",
+
+ "#endif",
+
THREE.ShaderChunk[ "common" ],
THREE.ShaderChunk[ "color_pars_fragment" ],
THREE.ShaderChunk[ "uv_pars_fragment" ],
@@ -82,9 +88,7 @@ THREE.ShaderLib = {
"void main() {",
- " vec3 outgoingLight = vec3( 0.0 );",
" vec4 diffuseColor = vec4( diffuse, opacity );",
- " vec3 totalAmbientLight = vec3( 1.0 );", // hardwired
" vec3 shadowMask = vec3( 1.0 );",
THREE.ShaderChunk[ "logdepthbuf_fragment" ],
@@ -93,15 +97,17 @@ THREE.ShaderLib = {
THREE.ShaderChunk[ "alphamap_fragment" ],
THREE.ShaderChunk[ "alphatest_fragment" ],
THREE.ShaderChunk[ "specularmap_fragment" ],
+
+ " ReflectedLight indirectReflectedLight = ReflectedLight( vec3( 0.0 ), diffuseColor.rgb );",
+
THREE.ShaderChunk[ "aomap_fragment" ],
THREE.ShaderChunk[ "shadowmap_fragment" ],
-
- " outgoingLight = diffuseColor.rgb * totalAmbientLight * shadowMask;",
+ "indirectReflectedLight.diffuse *= shadowMask;",
+
+ "vec3 outgoingLight = indirectReflectedLight.diffuse;",
THREE.ShaderChunk[ "envmap_fragment" ],
-
THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
-
THREE.ShaderChunk[ "fog_fragment" ],
" gl_FragColor = vec4( outgoingLight, diffuseColor.a );",
@@ -143,6 +149,7 @@ THREE.ShaderLib = {
THREE.ShaderChunk[ "uv_pars_vertex" ],
THREE.ShaderChunk[ "uv2_pars_vertex" ],
THREE.ShaderChunk[ "envmap_pars_vertex" ],
+ THREE.ShaderChunk[ "bsdfs" ],
THREE.ShaderChunk[ "lights_pars" ],
THREE.ShaderChunk[ "color_pars_vertex" ],
THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
@@ -223,18 +230,18 @@ THREE.ShaderLib = {
" #ifdef DOUBLE_SIDED",
" if ( gl_FrontFacing )",
- " outgoingLight += diffuseColor.rgb * ( vLightFront * shadowMask + totalAmbientLight ) + emissive;",
+ " outgoingLight += diffuseColor.rgb * ( vLightFront * shadowMask ) + emissive;",
" else",
- " outgoingLight += diffuseColor.rgb * ( vLightBack * shadowMask + totalAmbientLight ) + emissive;",
+ " outgoingLight += diffuseColor.rgb * ( vLightBack * shadowMask ) + emissive;",
" #else",
- " outgoingLight += diffuseColor.rgb * ( vLightFront * shadowMask + totalAmbientLight ) + emissive;",
+ " outgoingLight += diffuseColor.rgb * ( vLightFront * shadowMask ) + emissive;",
" #endif",
THREE.ShaderChunk[ "envmap_fragment" ],
-
+
THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
THREE.ShaderChunk[ "fog_fragment" ],
@@ -340,7 +347,7 @@ THREE.ShaderLib = {
"uniform float shininess;",
"uniform float opacity;",
- THREE.ShaderChunk[ "common" ],
+ THREE.ShaderChunk[ "common" ],
THREE.ShaderChunk[ "color_pars_fragment" ],
THREE.ShaderChunk[ "uv_pars_fragment" ],
THREE.ShaderChunk[ "uv2_pars_fragment" ],
@@ -351,6 +358,7 @@ THREE.ShaderLib = {
THREE.ShaderChunk[ "emissivemap_pars_fragment" ],
THREE.ShaderChunk[ "envmap_pars_fragment" ],
THREE.ShaderChunk[ "fog_pars_fragment" ],
+ THREE.ShaderChunk[ "bsdfs" ],
THREE.ShaderChunk[ "lights_pars" ],
THREE.ShaderChunk[ "lights_phong_pars_fragment" ],
THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
@@ -361,12 +369,11 @@ THREE.ShaderLib = {
"void main() {",
- " vec3 outgoingLight = vec3( 0.0 );",
" vec4 diffuseColor = vec4( diffuse, opacity );",
- " vec3 totalAmbientLight = ambientLightColor;",
+ " ReflectedLight directReflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ) );",
+ " ReflectedLight indirectReflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ) );",
" vec3 totalEmissiveLight = emissive;",
- " vec3 shadowMask = vec3( 1.0 );",
-
+
THREE.ShaderChunk[ "logdepthbuf_fragment" ],
THREE.ShaderChunk[ "map_fragment" ],
THREE.ShaderChunk[ "color_fragment" ],
@@ -374,29 +381,32 @@ THREE.ShaderLib = {
THREE.ShaderChunk[ "alphatest_fragment" ],
THREE.ShaderChunk[ "specularmap_fragment" ],
THREE.ShaderChunk[ "normal_phong_fragment" ],
- THREE.ShaderChunk[ "lightmap_fragment" ],
- THREE.ShaderChunk[ "hemilight_fragment" ],
- THREE.ShaderChunk[ "aomap_fragment" ],
THREE.ShaderChunk[ "emissivemap_fragment" ],
+ // accumulation
THREE.ShaderChunk[ "lights_phong_fragment" ],
- THREE.ShaderChunk[ "shadowmap_fragment" ],
+ THREE.ShaderChunk[ "lights_template" ],
+ THREE.ShaderChunk[ "lightmap_fragment" ],
- "totalDiffuseLight *= shadowMask;",
- "totalSpecularLight *= shadowMask;",
+ // modulation
+ THREE.ShaderChunk[ "aomap_fragment" ],
+
+ "vec3 shadowMask = vec3( 1.0 );",
+ THREE.ShaderChunk[ "shadowmap_fragment" ],
+ "directReflectedLight.diffuse *= shadowMask;",
+ "directReflectedLight.specular *= shadowMask;",
"#ifdef METAL",
- " outgoingLight += diffuseColor.rgb * ( totalDiffuseLight + totalAmbientLight ) * specular + totalSpecularLight + totalEmissiveLight;",
+ " vec3 outgoingLight = ( directReflectedLight.diffuse + indirectReflectedLight.diffuse ) * specular + directReflectedLight.specular + indirectReflectedLight.specular + totalEmissiveLight;",
"#else",
- " outgoingLight += diffuseColor.rgb * ( totalDiffuseLight + totalAmbientLight ) + totalSpecularLight + totalEmissiveLight;",
+ " vec3 outgoingLight = ( directReflectedLight.diffuse + indirectReflectedLight.diffuse ) + directReflectedLight.specular + indirectReflectedLight.specular + totalEmissiveLight;",
"#endif",
THREE.ShaderChunk[ "envmap_fragment" ],
-
THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
THREE.ShaderChunk[ "fog_fragment" ],
@@ -509,6 +519,14 @@ THREE.ShaderLib = {
"uniform float envMapIntensity;", // temporary
+ "varying vec3 vViewPosition;",
+
+ "#ifndef FLAT_SHADED",
+
+ " varying vec3 vNormal;",
+
+ "#endif",
+
THREE.ShaderChunk[ "common" ],
THREE.ShaderChunk[ "color_pars_fragment" ],
THREE.ShaderChunk[ "uv_pars_fragment" ],
@@ -520,8 +538,9 @@ THREE.ShaderLib = {
THREE.ShaderChunk[ "emissivemap_pars_fragment" ],
THREE.ShaderChunk[ "envmap_pars_fragment" ],
THREE.ShaderChunk[ "fog_pars_fragment" ],
+ THREE.ShaderChunk[ "bsdfs" ],
THREE.ShaderChunk[ "lights_pars" ],
- THREE.ShaderChunk[ "lights_phong_pars_fragment" ], // use phong chunk for now
+ THREE.ShaderChunk[ "lights_physical_pars_fragment" ], // use phong chunk for now
THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
THREE.ShaderChunk[ "bumpmap_pars_fragment" ],
THREE.ShaderChunk[ "normalmap_pars_fragment" ],
@@ -532,11 +551,10 @@ THREE.ShaderLib = {
"void main() {",
- " vec3 outgoingLight = vec3( 0.0 );",
" vec4 diffuseColor = vec4( diffuse, opacity );",
- " vec3 totalAmbientLight = ambientLightColor;",
+ " ReflectedLight directReflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ) );",
+ " ReflectedLight indirectReflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ) );",
" vec3 totalEmissiveLight = emissive;",
- " vec3 shadowMask = vec3( 1.0 );",
THREE.ShaderChunk[ "logdepthbuf_fragment" ],
THREE.ShaderChunk[ "map_fragment" ],
@@ -548,20 +566,23 @@ THREE.ShaderLib = {
//THREE.ShaderChunk[ "reflectivitymap_fragment" ],
THREE.ShaderChunk[ "metalnessmap_fragment" ],
THREE.ShaderChunk[ "normal_phong_fragment" ], // use phong chunk for now
- THREE.ShaderChunk[ "lightmap_fragment" ],
- THREE.ShaderChunk[ "hemilight_fragment" ],
- THREE.ShaderChunk[ "aomap_fragment" ],
THREE.ShaderChunk[ "emissivemap_fragment" ],
+ // accumulation
THREE.ShaderChunk[ "lights_physical_fragment" ],
- THREE.ShaderChunk[ "shadowmap_fragment" ],
+ THREE.ShaderChunk[ "lights_template" ],
+ THREE.ShaderChunk[ "lightmap_fragment" ],
+ THREE.ShaderChunk[ "envmap_physical_fragment" ],
- "totalDiffuseLight *= shadowMask;",
- "totalSpecularLight *= shadowMask;",
+ // modulation
+ THREE.ShaderChunk[ "aomap_fragment" ],
- "outgoingLight += diffuseColor.rgb * ( totalDiffuseLight + totalAmbientLight ) + totalSpecularLight + totalEmissiveLight;",
+ "vec3 shadowMask = vec3( 1.0 );",
+ THREE.ShaderChunk[ "shadowmap_fragment" ],
+ "directReflectedLight.diffuse *= shadowMask;",
+ "directReflectedLight.specular *= shadowMask;",
- THREE.ShaderChunk[ "envmap_physical_fragment" ],
+ "vec3 outgoingLight = directReflectedLight.diffuse + indirectReflectedLight.diffuse + directReflectedLight.specular + indirectReflectedLight.specular + totalEmissiveLight;",
THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
diff --git a/src/renderers/shaders/UniformsLib.js b/src/renderers/shaders/UniformsLib.js
index 4c2894416a3921..7dc42f877ec5d5 100644
--- a/src/renderers/shaders/UniformsLib.js
+++ b/src/renderers/shaders/UniformsLib.js
@@ -95,25 +95,34 @@ THREE.UniformsLib = {
"ambientLightColor" : { type: "fv", value: [] },
- "directionalLightDirection" : { type: "fv", value: [] },
- "directionalLightColor" : { type: "fv", value: [] },
-
- "hemisphereLightDirection" : { type: "fv", value: [] },
- "hemisphereLightSkyColor" : { type: "fv", value: [] },
- "hemisphereLightGroundColor" : { type: "fv", value: [] },
-
- "pointLightColor" : { type: "fv", value: [] },
- "pointLightPosition" : { type: "fv", value: [] },
- "pointLightDistance" : { type: "fv1", value: [] },
- "pointLightDecay" : { type: "fv1", value: [] },
-
- "spotLightColor" : { type: "fv", value: [] },
- "spotLightPosition" : { type: "fv", value: [] },
- "spotLightDirection" : { type: "fv", value: [] },
- "spotLightDistance" : { type: "fv1", value: [] },
- "spotLightAngleCos" : { type: "fv1", value: [] },
- "spotLightExponent" : { type: "fv1", value: [] },
- "spotLightDecay" : { type: "fv1", value: [] }
+ "directionalLights" : { type: "sa", value: [], properties: {
+ "direction": { type: "v3" },
+ "color": { type: "c" }
+ } },
+
+ "hemisphereLights" : { type: "sa", value: [], properties: {
+ "direction": { type: "v3" },
+ "skyColor": { type: "c" },
+ "groundColor": { type: "c" }
+ } },
+
+ "pointLights" : { type: "sa", value: [], properties: {
+ "color": { type: "c" },
+ "position": { type: "v3" },
+ "decay": { type: "f" },
+ "distance": { type: "f" }
+ } },
+
+ "spotLights" : { type: "sa", value: [], properties: {
+ "color": { type: "c" },
+ "position": { type: "v3" },
+ "direction": { type: "v3" },
+ "distance": { type: "f" },
+ "angleCos": { type: "f" },
+ "exponent": { type: "f" },
+ "decay": { type: "f" }
+ } }
+
},
diff --git a/src/renderers/webgl/WebGLProgram.js b/src/renderers/webgl/WebGLProgram.js
index f4cee3f4396458..f39699c22d00ee 100644
--- a/src/renderers/webgl/WebGLProgram.js
+++ b/src/renderers/webgl/WebGLProgram.js
@@ -1,6 +1,11 @@
THREE.WebGLProgram = ( function () {
var programIdCount = 0;
+
+ // TODO: Combine the regex
+ var structRe = /^([\w\d_]+)\.([\w\d_]+)$/;
+ var arrayStructRe = /^([\w\d_]+)\[(\d+)\]\.([\w\d_]+)$/;
+ var arrayRe = /^([\w\d_]+)\[0\]$/;
function generateDefines( defines ) {
@@ -25,20 +30,58 @@ THREE.WebGLProgram = ( function () {
var uniforms = {};
var n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS );
-
+
for ( var i = 0; i < n; i ++ ) {
var info = gl.getActiveUniform( program, i );
var name = info.name;
var location = gl.getUniformLocation( program, name );
- // console.log("THREE.WebGLProgram: ACTIVE UNIFORM:", name);
+ //console.log("THREE.WebGLProgram: ACTIVE UNIFORM:", name);
+
+ var matches = structRe.exec(name);
+ if( matches ) {
+
+ var structName = matches[1];
+ var structProperty = matches[2];
+
+ var uniformsStruct = uniforms[ structName ];
+ if( ! uniformsStruct ) {
+ uniformsStruct = uniforms[ structName ] = {};
+ }
+ uniformsStruct[ structProperty ] = location;
+
+ continue;
+ }
+
+ matches = arrayStructRe.exec(name);
+ if( matches ) {
+
+ var arrayName = matches[1];
+ var arrayIndex = matches[2];
+ var arrayProperty = matches[3];
+
+ var uniformsArray = uniforms[ arrayName ];
+ if( ! uniformsArray ) {
+ uniformsArray = uniforms[ arrayName ] = [];
+ }
+ var uniformsArrayIndex = uniformsArray[ arrayIndex ];
+ if( ! uniformsArrayIndex ) {
+ uniformsArrayIndex = uniformsArray[ arrayIndex ] = {};
+ }
+ uniformsArrayIndex[ arrayProperty ] = location;
+
+ continue;
+ }
+
+ matches = arrayRe.exec(name)
+ if( matches ) {
- var suffixPos = name.lastIndexOf( '[0]' );
- if ( suffixPos !== - 1 && suffixPos === name.length - 3 ) {
+ var arrayName = matches[1];
- uniforms[ name.substr( 0, suffixPos ) ] = location;
+ uniforms[ arrayName ] = location;
+ continue;
}
uniforms[ name ] = location;
diff --git a/utils/build/includes/common.json b/utils/build/includes/common.json
index cd19e349cecd8d..b602a0b5521f4e 100644
--- a/utils/build/includes/common.json
+++ b/utils/build/includes/common.json
@@ -111,6 +111,7 @@
"src/renderers/shaders/ShaderChunk/aomap_pars_fragment.glsl",
"src/renderers/shaders/ShaderChunk/begin_vertex.glsl",
"src/renderers/shaders/ShaderChunk/beginnormal_vertex.glsl",
+ "src/renderers/shaders/ShaderChunk/bsdfs.glsl",
"src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl",
"src/renderers/shaders/ShaderChunk/color_fragment.glsl",
"src/renderers/shaders/ShaderChunk/color_pars_fragment.glsl",
@@ -125,20 +126,19 @@
"src/renderers/shaders/ShaderChunk/envmap_fragment.glsl",
"src/renderers/shaders/ShaderChunk/envmap_pars_fragment.glsl",
"src/renderers/shaders/ShaderChunk/envmap_pars_vertex.glsl",
- "src/renderers/shaders/ShaderChunk/envmap_physical_fragment.glsl",
"src/renderers/shaders/ShaderChunk/envmap_vertex.glsl",
"src/renderers/shaders/ShaderChunk/fog_fragment.glsl",
"src/renderers/shaders/ShaderChunk/fog_pars_fragment.glsl",
- "src/renderers/shaders/ShaderChunk/hemilight_fragment.glsl",
- "src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl",
- "src/renderers/shaders/ShaderChunk/lightmap_pars_fragment.glsl",
"src/renderers/shaders/ShaderChunk/lights_pars.glsl",
+ "src/renderers/shaders/ShaderChunk/lightmap_pars_fragment.glsl",
"src/renderers/shaders/ShaderChunk/lights_lambert_vertex.glsl",
"src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl",
"src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl",
"src/renderers/shaders/ShaderChunk/lights_phong_pars_vertex.glsl",
"src/renderers/shaders/ShaderChunk/lights_phong_vertex.glsl",
"src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl",
+ "src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl",
+ "src/renderers/shaders/ShaderChunk/lights_template.glsl",
"src/renderers/shaders/ShaderChunk/linear_to_gamma_fragment.glsl",
"src/renderers/shaders/ShaderChunk/logdepthbuf_fragment.glsl",
"src/renderers/shaders/ShaderChunk/logdepthbuf_pars_fragment.glsl",