diff --git a/docs/api/lights/SpotLight.html b/docs/api/lights/SpotLight.html index 0d3c6b41e45caf..0a6b25363f6820 100644 --- a/docs/api/lights/SpotLight.html +++ b/docs/api/lights/SpotLight.html @@ -77,6 +77,12 @@

.[page:Float angle]

Default — *Math.PI/3*. +

.[page:Float penumbraAngle]

+
+ Additional angle, in radians, for the light to smoothly fall off.
+ Default — 0. +
+

.[page:Float exponent]

Rapidity of the falloff of light from its target direction.
diff --git a/examples/index.html b/examples/index.html index 103459b9e51d10..9051137c9a66bf 100644 --- a/examples/index.html +++ b/examples/index.html @@ -166,6 +166,7 @@

three.js / examples

"webgl_lights_hemisphere", "webgl_lights_pointlights", "webgl_lights_pointlights2", + "webgl_lights_spotlights_penumbra", "webgl_lines_colors", "webgl_lines_cubes", "webgl_lines_dashed", diff --git a/examples/textures/WoodFloor_DIF.png b/examples/textures/WoodFloor_DIF.png new file mode 100755 index 00000000000000..e9e91803713449 Binary files /dev/null and b/examples/textures/WoodFloor_DIF.png differ diff --git a/examples/textures/WoodFloor_NRM.png b/examples/textures/WoodFloor_NRM.png new file mode 100755 index 00000000000000..59983c6ad403b9 Binary files /dev/null and b/examples/textures/WoodFloor_NRM.png differ diff --git a/examples/textures/WoodFloor_SPC.png b/examples/textures/WoodFloor_SPC.png new file mode 100755 index 00000000000000..05a991a3dbe83c Binary files /dev/null and b/examples/textures/WoodFloor_SPC.png differ diff --git a/examples/webgl_lights_spotlights_penumbra.html b/examples/webgl_lights_spotlights_penumbra.html new file mode 100644 index 00000000000000..895e02e14436ea --- /dev/null +++ b/examples/webgl_lights_spotlights_penumbra.html @@ -0,0 +1,168 @@ + + + + three.js webgl - lights - spot lights - penumbra + + + + + + +
+
+ three.js - spot lights penumbra WebGL demo.
+
+ + + + + + + + + + diff --git a/src/lights/SpotLight.js b/src/lights/SpotLight.js index 79d0b928e6755b..0240526a34bd06 100644 --- a/src/lights/SpotLight.js +++ b/src/lights/SpotLight.js @@ -12,6 +12,7 @@ THREE.SpotLight = function ( color, intensity, distance, angle, exponent ) { this.intensity = ( intensity !== undefined ) ? intensity : 1; this.distance = ( distance !== undefined ) ? distance : 0; this.angle = ( angle !== undefined ) ? angle : Math.PI / 3; + this.penumbraAngle = 0; this.exponent = ( exponent !== undefined ) ? exponent : 10; this.castShadow = false; diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index e1712f986aaf78..af6c05c8363505 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -170,7 +170,7 @@ THREE.WebGLRenderer = function ( parameters ) { ambient: [ 0, 0, 0 ], directional: { length: 0, colors:[], positions: [] }, point: { length: 0, colors: [], positions: [], distances: [] }, - spot: { length: 0, colors: [], positions: [], distances: [], directions: [], anglesCos: [], exponents: [] }, + spot: { length: 0, colors: [], positions: [], distances: [], directions: [], anglesCos: [], outerAnglesCos: [], angleCosDiffs: [], exponents: [] }, hemi: { length: 0, skyColors: [], groundColors: [], positions: [] } }; @@ -4728,6 +4728,8 @@ THREE.WebGLRenderer = function ( parameters ) { uniforms.spotLightDistance.value = lights.spot.distances; uniforms.spotLightDirection.value = lights.spot.directions; uniforms.spotLightAngleCos.value = lights.spot.anglesCos; + uniforms.spotLightOuterAngleCos.value = lights.spot.outerAnglesCos; + uniforms.spotLightAngleCosDiff.value = lights.spot.angleCosDiffs; uniforms.spotLightExponent.value = lights.spot.exponents; uniforms.hemisphereLightSkyColor.value = lights.hemi.skyColors; @@ -5208,6 +5210,8 @@ THREE.WebGLRenderer = function ( parameters ) { spotDistances = zlights.spot.distances, spotDirections = zlights.spot.directions, spotAnglesCos = zlights.spot.anglesCos, + spotOuterAnglesCos = zlights.spot.outerAnglesCos, + spotAngleCosDiffs = zlights.spot.angleCosDiffs, spotExponents = zlights.spot.exponents, hemiSkyColors = zlights.hemi.skyColors, @@ -5350,6 +5354,8 @@ THREE.WebGLRenderer = function ( parameters ) { spotDirections[ spotOffset + 2 ] = _direction.z; spotAnglesCos[ spotLength ] = Math.cos( light.angle ); + spotOuterAnglesCos[ spotLength ] = Math.cos( light.angle + light.penumbraAngle ); + spotAngleCosDiffs[ spotLength ] = spotAnglesCos[ spotLength ] - spotOuterAnglesCos[ spotLength ] spotExponents[ spotLength ] = light.exponent; spotLength += 1; diff --git a/src/renderers/shaders/ShaderChunk/lights_lambert_pars_vertex.glsl b/src/renderers/shaders/ShaderChunk/lights_lambert_pars_vertex.glsl index 511c1a83ec33eb..2bebc94d95dc86 100644 --- a/src/renderers/shaders/ShaderChunk/lights_lambert_pars_vertex.glsl +++ b/src/renderers/shaders/ShaderChunk/lights_lambert_pars_vertex.glsl @@ -34,6 +34,8 @@ uniform vec3 ambientLightColor; uniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ]; uniform float spotLightDistance[ MAX_SPOT_LIGHTS ]; uniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ]; + uniform float spotLightOuterAngleCos[ MAX_SPOT_LIGHTS ]; + uniform float spotLightAngleCosDiff[ MAX_SPOT_LIGHTS ]; uniform float spotLightExponent[ MAX_SPOT_LIGHTS ]; #endif diff --git a/src/renderers/shaders/ShaderChunk/lights_lambert_vertex.glsl b/src/renderers/shaders/ShaderChunk/lights_lambert_vertex.glsl index c67bc2c953ab87..e474c920fca6c7 100644 --- a/src/renderers/shaders/ShaderChunk/lights_lambert_vertex.glsl +++ b/src/renderers/shaders/ShaderChunk/lights_lambert_vertex.glsl @@ -117,9 +117,14 @@ for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) { float spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - worldPosition.xyz ) ); - if ( spotEffect > spotLightAngleCos[ i ] ) { + if ( spotEffect > spotLightOuterAngleCos[ i ] ) { + + float falloff = 0.0; + falloff = (spotEffect - spotLightOuterAngleCos[ i ]) / spotLightAngleCosDiff[ i ]; + falloff = clamp( falloff, 0.0, 1.0 ); spotEffect = max( pow( max( spotEffect, 0.0 ), spotLightExponent[ i ] ), 0.0 ); + spotEffect *= falloff; float lDistance = 1.0; if ( spotLightDistance[ i ] > 0.0 ) @@ -199,4 +204,4 @@ vLightFront = vLightFront * diffuse + ambient * ambientLightColor + emissive; vLightBack = vLightBack * diffuse + ambient * ambientLightColor + emissive; -#endif \ No newline at end of file +#endif diff --git a/src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl b/src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl index 49d949d1820468..d23f204498857e 100644 --- a/src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl +++ b/src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl @@ -85,9 +85,14 @@ vec3 viewPosition = normalize( vViewPosition ); float spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) ); - if ( spotEffect > spotLightAngleCos[ i ] ) { + if ( spotEffect > spotLightOuterAngleCos[ i ] ) { + + float falloff = 0.0; + falloff = (spotEffect - spotLightOuterAngleCos[ i ]) / spotLightAngleCosDiff[ i ]; + falloff = clamp( falloff, 0.0, 1.0 ); spotEffect = max( pow( max( spotEffect, 0.0 ), spotLightExponent[ i ] ), 0.0 ); + spotEffect *= falloff; // diffuse @@ -275,4 +280,4 @@ vec3 totalSpecular = vec3( 0.0 ); gl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient ) + totalSpecular; -#endif \ No newline at end of file +#endif diff --git a/src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl b/src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl index 54228c49bd5b8d..dcabf87b179b44 100644 --- a/src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl +++ b/src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl @@ -30,6 +30,8 @@ uniform vec3 ambientLightColor; uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ]; uniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ]; uniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ]; + uniform float spotLightOuterAngleCos[ MAX_SPOT_LIGHTS ]; + uniform float spotLightAngleCosDiff[ MAX_SPOT_LIGHTS ]; uniform float spotLightExponent[ MAX_SPOT_LIGHTS ]; uniform float spotLightDistance[ MAX_SPOT_LIGHTS ]; @@ -49,4 +51,4 @@ uniform vec3 ambientLightColor; #endif varying vec3 vViewPosition; -varying vec3 vNormal; \ No newline at end of file +varying vec3 vNormal; diff --git a/src/renderers/shaders/UniformsLib.js b/src/renderers/shaders/UniformsLib.js index e84336bde82b8d..3dd83da07f00e4 100644 --- a/src/renderers/shaders/UniformsLib.js +++ b/src/renderers/shaders/UniformsLib.js @@ -69,6 +69,8 @@ THREE.UniformsLib = { "spotLightDirection" : { type: "fv", value: [] }, "spotLightDistance" : { type: "fv1", value: [] }, "spotLightAngleCos" : { type: "fv1", value: [] }, + "spotLightOuterAngleCos" : { type: "fv1", value: [] }, + "spotLightAngleCosDiff" : { type: "fv1", value: [] }, "spotLightExponent" : { type: "fv1", value: [] } },