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

Conversation

N8python
Copy link
Contributor

@N8python N8python commented Sep 2, 2022

With the new mapping capabilities of spotlights, many people will want to use them as movie-projectors. However, their shape is purely circular - this pull request allows you to set the projector boolean on a spot light to have it attenuate based off its shadowcam's frustum. It also includes the projectorAspect attribute to allow varying the width of the projection.

It also supports the use of the penumbra parameter for attenuation (see image 3). This is accomplished via a signed distance function.

Screen Shot 2022-09-02 at 4 09 04 PM

Screen Shot 2022-09-02 at 4 09 30 PM

Screen Shot 2022-09-02 at 4 11 12 PM

@mrdoob
Copy link
Owner

mrdoob commented Sep 2, 2022

We'll have to refactor the code a bit...
I think it'd be more intuitive to introduce a RectLight but we'll still need to a aspect property.

@mrdoob
Copy link
Owner

mrdoob commented Sep 2, 2022

Btw... Make sure to not include the builds nor changes to package.json in the PR.

@mrdoob mrdoob added this to the r145 milestone Sep 2, 2022
@N8python
Copy link
Contributor Author

N8python commented Sep 2, 2022

Sorry about that! Still very new to the whole pull-requesting thing 😓

@N8python
Copy link
Contributor Author

N8python commented Sep 2, 2022

All right the files are no longer being overwritten! How would you recommend I refactor things?

I would be against a RectLight - One, because there's already RectAreaLight, and two, adding another light type would mean a large codebase overhaul.

@gkjohnson
Copy link
Collaborator

Are we against calling this something like "ProjectorLight", then, if a SpotLight modification isn't acceptable? I agree that "RectLight" is a bit confusing.

@N8python
Copy link
Contributor Author

N8python commented Sep 7, 2022

Are we against calling this something like "ProjectorLight", then, if a SpotLight modification isn't acceptable? I agree that "RectLight" is a bit confusing.

I think ProjectorLight would make the most sense. Another thing I was thinking is perhaps having an attenuation mode for spotlights that can toggle between this and the traditional circle attenuation - maybe THREE.CircleAttenuation and THREE.RectAttenuation. Maybe that would be more "idiomatic", or in the style of threejs.

As I said before, I'm not sure the additional code complexity warranted by a ProjectorLight would be worth it - given how simple the modifications to the SpotLight are.

@gkjohnson
Copy link
Collaborator

As I said before, I'm not sure the additional code complexity warranted by a ProjectorLight would be worth it - given how simple the modifications to the SpotLight are.

If an "attenuation" field like you've suggested is not acceptable for the public API then I would think it would still be okay to implement it that way internally while the public facing API separates the lights into "Spot" and "Projector" lights. Best of both worlds!

@N8python
Copy link
Contributor Author

N8python commented Sep 8, 2022

As I said before, I'm not sure the additional code complexity warranted by a ProjectorLight would be worth it - given how simple the modifications to the SpotLight are.

If an "attenuation" field like you've suggested is not acceptable for the public API then I would think it would still be okay to implement it that way internally while the public facing API separates the lights into "Spot" and "Projector" lights. Best of both worlds!

You, my friend, are a genius. ProjectorLight is a subclass of SpotLight that internally is just a SpotLight with an attenuated field.

Copy link
Collaborator

@gkjohnson gkjohnson left a comment

Choose a reason for hiding this comment

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

Probably worth waiting for approval from @mrdoob on the path forward for the PR but I've added a few comments on code style to the review.

Comment on lines -401 to +404
// WebGL 2
// WebGL 2ÍÍ
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

Comment on lines -437 to +447
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 ) {
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.

Comment on lines +166 to +169
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);
}
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

Comment on lines +151 to +155
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);
}
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

@@ -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

@@ -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

Comment on lines +258 to +265
lightHelperProjector.update();
if (spotLight.projector) {
lightHelper.visible = false;
lightHelperProjector.visible = true;
} else {
lightHelper.visible = true;
lightHelperProjector.visible = false;
}
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)

@mrdoob mrdoob modified the milestones: r145, r146 Sep 29, 2022
@mrdoob mrdoob modified the milestones: r146, r147 Oct 27, 2022
@mrdoob mrdoob modified the milestones: r147, r148 Nov 30, 2022
@mrdoob mrdoob modified the milestones: r148, r149 Dec 22, 2022
@mrdoob mrdoob modified the milestones: r149, r150 Jan 26, 2023
@mrdoob mrdoob modified the milestones: r150, r151 Feb 23, 2023
@mrdoob mrdoob modified the milestones: r151, r152 Mar 30, 2023
@mrdoob mrdoob removed this from the r152 milestone Apr 27, 2023
@mrdoob mrdoob added this to the r170 milestone Sep 26, 2024
@mrdoob mrdoob modified the milestones: r170, r171 Oct 31, 2024
@mrdoob mrdoob modified the milestones: r171, r172 Nov 29, 2024
@mrdoob mrdoob modified the milestones: r172, r173 Dec 31, 2024
@mrdoob mrdoob modified the milestones: r173, r174 Jan 31, 2025
@mrdoob mrdoob modified the milestones: r174, r175 Feb 27, 2025
@mrdoob mrdoob modified the milestones: r175, r176 Mar 28, 2025
@WREQI
Copy link

WREQI commented Apr 15, 2025

@N8python @gkjohnson Hello, has the rectangular projection been completed and can it be used simply by merging the code? Do you have any cases? How can I extract it as a plugin and use it locally?

@paulzhu0903
Copy link

Rectangular Spotlight Leaking
I appreciate your library for the rectangular spotlight—it's been very helpful.
However, I’ve noticed some light leakage occurring behind the light source. I’m wondering if I might be using it incorrectly. I even tried placing a plane behind it to block the light, but unfortunately, that didn’t solve the issue.
Could you please advise me on how to fix this?
Thank you in advance for your help.

@WREQI
Copy link

WREQI commented Apr 21, 2025

@paulzhu0903 Do you support the latest version?

@WREQI
Copy link

WREQI commented Apr 21, 2025

Can we share code? @paulzhu0903

@paulzhu0903
Copy link

Sorry, I am a newbie. I just modified N8python's code to create a scene with a projector. I found the light leakage issue. The code is similar to N8python's demo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants