Skip to content

Create Option to Have Spotlights Use Rectangular Projection #24589

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

Open
wants to merge 5 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 25 additions & 4 deletions examples/webgl_lights_spotlight.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

let renderer, scene, camera;

let spotLight, lightHelper;
let spotLight, lightHelper, lightHelperProjector;

init();

Expand Down Expand Up @@ -93,7 +93,7 @@
spotLight.decay = 2;
spotLight.distance = 100;
spotLight.map = textures[ 'disturb.jpg' ];

spotLight.projector = true;
spotLight.castShadow = true;
spotLight.shadow.mapSize.width = 1024;
spotLight.shadow.mapSize.height = 1024;
Expand All @@ -104,6 +104,8 @@

lightHelper = new THREE.SpotLightHelper( spotLight );
scene.add( lightHelper );
lightHelperProjector = new THREE.CameraHelper( spotLight.shadow.camera );
scene.add( lightHelperProjector );

//

Expand Down Expand Up @@ -151,7 +153,9 @@
penumbra: spotLight.penumbra,
decay: spotLight.decay,
focus: spotLight.shadow.focus,
shadows: true
shadows: true,
projector: true,
projectorAspect: 1
};

gui.add( params, 'map', textures ).onChange( function ( val ) {
Expand All @@ -171,6 +175,16 @@
spotLight.intensity = val;

} );
gui.add( params, 'projector' ).onChange( function ( val ) {

spotLight.projector = val;

} );
gui.add( params, 'projectorAspect', 0.1, 10).onChange( function ( val ) {

spotLight.projectorAspect = val;

} );


gui.add( params, 'distance', 50, 200 ).onChange( function ( val ) {
Expand Down Expand Up @@ -241,7 +255,14 @@
spotLight.position.z = Math.sin( time ) * 25;

lightHelper.update();

lightHelperProjector.update();
if (spotLight.projector) {
lightHelper.visible = false;
lightHelperProjector.visible = true;
} else {
lightHelper.visible = true;
lightHelperProjector.visible = false;
}
Comment on lines +258 to +265
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: code style (spaces inside parentheses and newlines within braces)

renderer.render( scene, camera );

}
Expand Down
3 changes: 2 additions & 1 deletion src/lights/SpotLight.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ class SpotLight extends Light {
this.angle = angle;
this.penumbra = penumbra;
this.decay = decay; // for physically correct lights, should be 2.

this.projector = false;
this.projectorAspect = 1;
this.map = null;

this.shadow = new SpotLightShadow();
Expand Down
2 changes: 1 addition & 1 deletion src/lights/SpotLightShadow.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class SpotLightShadow extends LightShadow {
const camera = this.camera;

const fov = MathUtils.RAD2DEG * 2 * light.angle * this.focus;
const aspect = this.mapSize.width / this.mapSize.height;
const aspect = ( this.mapSize.width / this.mapSize.height ) * ( light.projector ? light.projectorAspect : 1 );
const far = light.distance || camera.far;

if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default /* glsl */`
export default /* glsl */ `
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: same unnecessary change

/**
* This is a template that can be used to light a material, it uses pluggable
* RenderEquations (RE)for specific lighting scenarios.
Expand Down Expand Up @@ -95,8 +95,6 @@ IncidentLight directLight;

spotLight = spotLights[ i ];

getSpotLightInfo( spotLight, geometry, directLight );

// spot lights are ordered [shadows with maps, shadows without maps, maps without shadows, none]
#if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )
#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX
Expand All @@ -105,6 +103,11 @@ IncidentLight directLight;
#else
#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )
#endif
#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )
getSpotLightInfo( spotLight, geometry, vSpotLightCoord[ i ], directLight );
#else
getSpotLightInfo( spotLight, geometry, vec4(0.0), directLight );
#endif

#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )
spotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;
Expand Down
16 changes: 12 additions & 4 deletions src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default /* glsl */`
export default /* glsl */ `
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: unnecessary change

uniform bool receiveShadow;
uniform vec3 ambientLightColor;
uniform vec3 lightProbe[ 9 ];
Expand Down Expand Up @@ -144,12 +144,17 @@ float getSpotAttenuation( const in float coneCosine, const in float penumbraCosi
float decay;
float coneCos;
float penumbraCos;
bool projector;
};

uniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];

float sdBox( in vec2 p, in vec2 b )
{
vec2 d = abs(p)-b;
return length(max(d,0.0)) + min(max(d.x,d.y),0.0);
}
Comment on lines +151 to +155
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: spacing around the function and remove the newline before the first brace

// light is an out parameter as having it as a return value caused compiler errors on some devices
void getSpotLightInfo( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight light ) {
void getSpotLightInfo( const in SpotLight spotLight, const in GeometricContext geometry, const in vec4 spotCoord, out IncidentLight light ) {

vec3 lVector = spotLight.position - geometry.position;

Expand All @@ -158,7 +163,10 @@ float getSpotAttenuation( const in float coneCosine, const in float penumbraCosi
float angleCos = dot( light.direction, spotLight.direction );

float spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );

if (spotLight.projector) {
vec3 spotLightCoord = spotCoord.xyz / spotCoord.w;
spotAttenuation = clamp((-2.0 * sdBox(spotLightCoord.xy - vec2(0.5), vec2(0.5, 0.5))) * (-1.0 / ((1.0 - acos(spotLight.penumbraCos)) - 1.0)), 0.0, 1.0);
}
Comment on lines +166 to +169
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we update this to use the three.js code style and remove the unnecessary parentheses.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@N8python See the guide here, which includes tools for automatically formatting the code:

https://github.com/mrdoob/three.js/wiki/Mr.doob's-Code-Style%E2%84%A2

if ( spotAttenuation > 0.0 ) {

float lightDistance = length( lVector );
Expand Down
31 changes: 17 additions & 14 deletions src/renderers/webgl/WebGLLights.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ function UniformsCache() {
distance: 0,
coneCos: 0,
penumbraCos: 0,
decay: 0
decay: 0,
projector: false
};
break;

Expand Down Expand Up @@ -126,7 +127,7 @@ function ShadowUniformsCache() {
};
break;

// TODO (abelnation): set RectAreaLight shadow uniforms
// TODO (abelnation): set RectAreaLight shadow uniforms

}

Expand Down Expand Up @@ -204,7 +205,9 @@ function WebGLLights( extensions, capabilities ) {

function setup( lights, physicallyCorrectLights ) {

let r = 0, g = 0, b = 0;
let r = 0,
g = 0,
b = 0;

for ( let i = 0; i < 9; i ++ ) state.probe[ i ].set( 0, 0, 0 );

Expand Down Expand Up @@ -289,9 +292,9 @@ function WebGLLights( extensions, capabilities ) {
uniforms.distance = distance;

uniforms.coneCos = Math.cos( light.angle );
uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );
uniforms.penumbraCos = Math.cos( light.angle * ( light.projector ? light.penumbra : 1 - ( light.penumbra ) ) );
uniforms.decay = light.decay;

uniforms.projector = light.projector;
state.spot[ spotLength ] = uniforms;

const shadow = light.shadow;
Expand Down Expand Up @@ -398,7 +401,7 @@ function WebGLLights( extensions, capabilities ) {

if ( capabilities.isWebGL2 ) {

// WebGL 2
// WebGL 2ÍÍ
Comment on lines -401 to +404
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like an inadvertent change


state.rectAreaLTC1 = UniformsLib.LTC_FLOAT_1;
state.rectAreaLTC2 = UniformsLib.LTC_FLOAT_2;
Expand Down Expand Up @@ -434,14 +437,14 @@ function WebGLLights( extensions, capabilities ) {
const hash = state.hash;

if ( hash.directionalLength !== directionalLength ||
hash.pointLength !== pointLength ||
hash.spotLength !== spotLength ||
hash.rectAreaLength !== rectAreaLength ||
hash.hemiLength !== hemiLength ||
hash.numDirectionalShadows !== numDirectionalShadows ||
hash.numPointShadows !== numPointShadows ||
hash.numSpotShadows !== numSpotShadows ||
hash.numSpotMaps !== numSpotMaps ) {
hash.pointLength !== pointLength ||
hash.spotLength !== spotLength ||
hash.rectAreaLength !== rectAreaLength ||
hash.hemiLength !== hemiLength ||
hash.numDirectionalShadows !== numDirectionalShadows ||
hash.numPointShadows !== numPointShadows ||
hash.numSpotShadows !== numSpotShadows ||
hash.numSpotMaps !== numSpotMaps ) {
Comment on lines -437 to +447
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are a few places in the PR where indentation looks off.


state.directional.length = directionalLength;
state.spot.length = spotLength;
Expand Down