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",