Lens flare system, easily usable by builders or scripters

Hello all,

Today I’m releasing a simple lens flare system I wrote for an upcoming game of mine. This uses ParticleEmitters to achieve a lens flare effect, which also gives nice bloom and also allows for additive blending. This system is meant to be simple to use, so customization of lens flares is mainly achieved by using CollectionService to tag parts to put flares on, as well as attributes to customize flare type, distance, and strength.

Video Demonstration

Using Lens Flares

To start, just put the LensFlare folder into ReplicatedStorage.
Tag parts that you want to attach lens flares to with LensFlare. You can configure the type of lens flare added with the LensFlareStyle attribute. By default, the system comes with two types: Default and SmallLight.

You can further customize the flare with LensFlareDistance and LensFlareStrength.

  • Distance adjusts the fade for the flare as you get further away from it. A value of 0 will make the flare visible from everywhere.
  • Strength adjusts the opacity of the lens flare. 1 is the maximum opacity.

By default, a lens flare effect is also applied to the sky.

Creating Lens Flare Styles

Simply clone one of the existing folders under LensFlare.Assets to get started. As stated before, this system uses ParticleEmitters, so you should only use those when creating lens flares.

You can set up ParticleEmitters as you normally would, except for Size, Transparency, and Squash. These are controlled by Attributes you will apply which are listed below.

Positional Attributes

  • Position: A Vector3 / vector attribute that describes how the emitter will be placed on screen. Note: Z position is not used.
    • The value of the X, Y coordinates determines whether the emitter is placed opposite of the source. A position of 1, 1 places the emitter right at the source of the flare while a position of -1, -1 places the emitter at the opposite end from the flare’s source, which is useful for lens flare ghosts.
    • A position of -1, 1 can be useful for anamorphic effects - it aligns it with the Y coordinate of the flare but on the opposite X coordinate.

  • PositionMult: A number scalar value which multiplies Position by this amount. An easier way to describe the distance from the source of the flare.

Sequence Attributes

Note: Time 0 describes how the emitter looks when looking directly at the flare - time 1
describes how the emitter looks when it is off-screen.
All sequence attributes can simply just be set to one number if you want it to be consistent no matter the viewing angle.

  • SizeFade: A NumberSequence that describes the size of the emitter depending on the angle the flare is viewed from.
  • TransparencyFade: A NumberSequence that describes the transparency of the emitter depending on the angle the flare is viewed from.
  • SquashFade: A NumberSequence that describes the squash of the emitter depending on the angle the flare is viewed from.

Miscellanous Attributes

  • ColorBlend: A number attribute describing how much the ParticleEmitter inherits the hue of the Part the lens flare is attached to. For example, setting ColorBlend to 1 on a flare attached to a red part results in the emitter being turned red.
  • Rotates: A boolean attribute that determines whether or not the emitter rotates as the viewing angle changes.

All attributes can be changed at run-time for easier experimentation!

Scripting API

There is a small scripting API associated with the system.

LensFlare.new(camera: Camera, flareStyle: string, part: BasePart): LensFlare
Creates a new Lens Flare object with specified camera, flare style, and part.

LensFlare.Destroy(self: LensFlare)
Destroys the Lens Flare and unhooks connections.

LensFlare.Update(self: LensFlare)
Updates all emitters and positions of attachments, and also checks for obstruction between flare source and camera. Note: a function hooking to RunService already calls this when you instantiate a new LensFlare.

Properties

LensFlare.Enabled: Determines whether the Lens Flare will be updated and rendered. This doesn’t affect LensFlare.Update, only the function inside the constructor that calls it.

LensFlare.Alpha: Strength of the lens flare taking into account distance and viewing angle.

Get it here!

https://create.roblox.com/store/asset/89532403908041/Lens-Flare-System

Demo place

If you have any feedback about the system, please let me know! This is my first post here, so there’s probably bound to be some issues. I’ll try and respond in a timely manner!

Attribution

Giving credit is not required, but appreciated!

415 Likes

Hello. This is simply amazing. Truly is. I have been working on lens flares for more than two years and this is the best I’ve seen yet. That’s awesome.
Thanks for sharing it !
Bless you

13 Likes

This feels like early Christmas. The default anamorphic lens flare is also chef’s kiss

9 Likes

thats just gorgeous isnt it, great work

5 Likes

thank you goat :pray:
there are not enough good-looking lens flare resources out there, for whatever reason.

6 Likes

looks amazing great work :+1:

3 Likes

i have been staring at the sun and trying to create the lens flares in my eyes for 30 years. this is a great resource

17 Likes

This is absolutely stunning. Amazing work.

3 Likes

This is one of the best modules I have ever seen! Gonna use it for sure!

1 Like

Great resources! They look really great overall. I have a couple questions however. Would it be possible for you to move these lens flares into parallel?

In your scene it seems like even a couple of them tend to add up quite quickly so parallelism should be able to offload them onto multiple cpu threads.

Another thing im wondering about is whenever or not it is possible for you to cache the attributes of these instanes.
image
Personally i have been working on a pretty fancy project i think a lot of people may like and i have been using some pretty extensive tricks for optimization including caching attributes. Cutting down on those calls will offer you free compute. What i am basically doing for my project is basically gathering ALL attributes via the GetAttributes method (to initialize all of them of course) only to set up an even attribute changed signal specifically for the attributes my project uses.

I also believe that you may be able to squeeze more performance by first checking to see whenever or not you actually need to update an instance property.
image
For example, you can try caching all of the properties and verify any potential new ones against those same cached ones. If there is any change THEN you can apply them to the actual instances. Keep in mind, applying the same property to an instance will still take resources even IF the new and old values are the same!

As for the raycasting i recommend adding a couple optional performance settings designed to dumb down the raycasts. I can already see scenarios in which developers may not specifically need maximum accuracy for obstruction blending so i think it would be nice to offer them a way to reduce the raycast count for individual lens flares.

Hopefully this information is of help to you. I wish you luck on this project!

7 Likes

I’ll look into your concerns. Thanks! I didn’t do much profiling so any performance gains will help lol.

3 Likes

Version 1.1

  • Minor lens flare optimizations (thanks @XenoDenissboss1).
  • Added config file, and lowered default number of raycasts.

Old version

New version

Hotfix 1.1.1

  • Fixed emitters with no / zero ColorBlend being greyscale
6 Likes

holy saint of cows… You DESERVE some kind of award for this!

3 Likes

This is really awesome, but how good is it on draw calls? If we plan to use this for a larger scale project, there could be overdraw on it. However, I’m still learning a lot about optimizing so maybe you could point me towards the right direction

2 Likes

Overdraw can be pretty bad with this system seeing as how it is a bunch of ParticleEmitters stacked on top of each other. If you keep the complexity of the lens flare styles low and don’t use too many though you can still get decent mileage out of it.

3 Likes

Thanks for the prompt response, I’ll definitely try out a simpler particle style!

3 Likes

magnificient. it’s very good especially for your first post here! well done

2 Likes

this looks amazing! nice job !!

2 Likes

Crazy work! I do wanna ask, how does it look in 1 graphic and max graphic?

2 Likes

There’s not much difference. Graphics level 1 doesn’t have bloom so you don’t get some of the glow on the lens flare, but otherwise it’s pretty identical.

3 Likes