-
-
Notifications
You must be signed in to change notification settings - Fork 35.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add penumbra angle to spotLight #5078
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<title>three.js webgl - lights - spot lights - penumbra</title> | ||
<meta charset="utf-8"> | ||
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> | ||
<style> | ||
body { | ||
background-color: #000; | ||
margin: 0px; | ||
overflow: hidden; | ||
} | ||
|
||
#info { | ||
position: absolute; | ||
top: 0px; width: 100%; | ||
color: #ffffff; | ||
padding: 5px; | ||
font-family: Monospace; | ||
font-size: 13px; | ||
text-align: center; | ||
} | ||
|
||
a { | ||
color: #ff0080; | ||
text-decoration: none; | ||
} | ||
|
||
a:hover { | ||
color: #0080ff; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
|
||
<div id="container"></div> | ||
<div id="info"> | ||
<a href="http://threejs.org" target="_blank">three.js</a> - spot lights penumbra WebGL demo.<br /> | ||
</div> | ||
|
||
<script src="../build/three.js"></script> | ||
|
||
<script src="js/loaders/BinaryLoader.js"></script> | ||
|
||
<script src="js/Detector.js"></script> | ||
|
||
<script> | ||
|
||
if ( ! Detector.webgl ) Detector.addGetWebGLMessage(); | ||
|
||
var camera, scene, renderer, lights; | ||
|
||
init(); | ||
animate(); | ||
|
||
function init() { | ||
|
||
var container = document.getElementById( 'container' ); | ||
|
||
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 ); | ||
camera.position.y = 4; | ||
camera.position.z = 3; | ||
camera.lookAt(new THREE.Vector3(0, 0, 0)); | ||
|
||
scene = new THREE.Scene(); | ||
|
||
var createTexture = function(url) { | ||
var texture = THREE.ImageUtils.loadTexture("textures/" + url); | ||
texture.wrapS = texture.wrapT = THREE.RepeatWrapping; | ||
texture.repeat.set(100, 100); | ||
return texture | ||
}; | ||
|
||
var geometry = new THREE.PlaneGeometry(100, 100, 100, 100); | ||
var material = new THREE.MeshPhongMaterial({ | ||
map: createTexture("WoodFloor_DIF.png"), | ||
specularMap: createTexture("WoodFloor_SPC.png"), | ||
normalMap: createTexture("WoodFloor_NRM.png"), | ||
side: THREE.DoubleSide, | ||
shininess: 150 | ||
}); | ||
|
||
var floor = new THREE.Mesh(geometry, material); | ||
floor.rotation.x = Math.PI / 2; | ||
|
||
scene.add( floor ); | ||
|
||
lights = []; | ||
|
||
var light = new THREE.SpotLight(); | ||
light.position.set( 0, 1.8407174058250002, 1.8 ); | ||
light.target.position.set( 0, 0.9746920020405615, 1.3 ); | ||
lights.push( light ); | ||
|
||
var light = new THREE.SpotLight(); | ||
light.position.set( 0, 1.8407174058250002, -1.8 ); | ||
light.target.position.set( 0, 0.9746920020405615, -1.3 ); | ||
lights.push( light ); | ||
|
||
var light = new THREE.SpotLight(); | ||
light.position.set( 1.8, 1.8407174058250002, 0 ); | ||
light.target.position.set( 1.3, 0.9746920020405615, 0 ); | ||
lights.push( light ); | ||
|
||
var light = new THREE.SpotLight(); | ||
light.position.set( -1.8, 1.8407174058250002, 0 ); | ||
light.target.position.set( -1.3, 0.9746920020405615, 0 ); | ||
lights.push( light ); | ||
|
||
for (i in lights) { | ||
var light = lights[ i ]; | ||
light.color.setHex( 0xffffff ); | ||
light.intensity = 0.5; | ||
light.angle = (5 * Math.PI) / 24; // 75 degrees | ||
light.exponent = 0 | ||
|
||
scene.add( light ); | ||
} | ||
|
||
renderer = new THREE.WebGLRenderer(); | ||
renderer.setSize( window.innerWidth, window.innerHeight ); | ||
container.appendChild( renderer.domElement ); | ||
|
||
// | ||
|
||
window.addEventListener( 'resize', onWindowResize, false ); | ||
|
||
} | ||
|
||
function onWindowResize() { | ||
|
||
camera.aspect = window.innerWidth / window.innerHeight; | ||
camera.updateProjectionMatrix(); | ||
|
||
renderer.setSize( window.innerWidth, window.innerHeight ); | ||
|
||
} | ||
|
||
// | ||
|
||
function animate() { | ||
|
||
// Toggle the display of the penumbra effect every 5 seconds | ||
var togglePenumbra = Math.round(new Date().getTime() / 5000) % 2; | ||
|
||
for (i in lights) { | ||
if (togglePenumbra) { | ||
lights[ i ].penumbraAngle = 0.174532925; // 10 degrees in radians | ||
} else { | ||
lights[ i ].penumbraAngle = 0; | ||
} | ||
} | ||
|
||
requestAnimationFrame( animate ); | ||
|
||
render(); | ||
|
||
} | ||
|
||
function render() { | ||
|
||
renderer.render( scene, camera ); | ||
|
||
} | ||
|
||
</script> | ||
</body> | ||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 ]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can result in a divide-by-zero. Is that an issue? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nope, doesn't cause any problems. |
||
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 | ||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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: [] }, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps the difference can be computed in the shader, instead. This may be more efficient, but it seems strange to me to pass in redundant information. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I need to actually benchmark the performance difference, but at first glance it seemed pretty significant |
||
"spotLightExponent" : { type: "fv1", value: [] } | ||
|
||
}, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These cosines can be negative. What are the range of values for the relevant
SpotLight
parameters that make sense to you?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My thought was that
penumbraAngle
would always be positive, and you'd decreaseangle
appropriately if you want an inner fade instead of an outer fade. However, I wouldn't be opposed to handling negativepenumbraAngle
values.