A downloadable GameMaker asset

Buy Now$19.99 USD or more


The Eclipse Light Engine is a high-end lighting solution for the GameMaker (GM) engine.  It uses deferred rendering and the metallic/roughness workflow to render PBR lighting.

Features:

  • Dynamic lights
  • Highly configurable light object with prefabs for: point, spot, line, cone, and area
  • Automatic day and night cycle with configurable speed, sun rise/set windows, direction, intensity, and more
  • Soft-shadows with per light shadow hardness
  • Light and material depth for precise scene lighting
  • Bloom lighting and emissive textures
  • Lit and emissive particle system built on GM's built-in particle system
  • 3D calculated shadows with adjustable shadow length
  • Static and dynamic shadows
  • Primitive and polygon shadow shapes (easily created within the GM IDE)
  • Textured material objects (primitive and polygon)
  • Adjustable render resolution
  • Compatible with all platforms (includes GLSL ES shaders)

Learn more about Eclipse:

Eclipse tutorials and information - Learn more about Eclipse and how to configure its various components.

Eclipse tech DEMOFree download which demonstrates many of the engines features.

PBR Material Packer Tool - Free tool for packing materials and baking emissive into normal maps for use in Eclipse (also included in Eclipse download archive).

Blender Texture Exporter - Tool made by Firewatch Games for easy Blender exporting to Eclipse.

Enhance Pixel Art Games!



Hardware Considerations:

Eclipse is highly optimized, GPU bound-lighting solution.  Performance and system requirements are relative to the rendering resolution and target platform.  Consider GPUs such as the following (or newer) when developing with Eclipse:

Maker Low-endRecommended
NVIDIAGeForce GTX 750GeForce GTX 1060
AMDRadeon R8 290xRadeon RX 480

Technical Advantages:

Eclipse packs 1-bit shadow maps into 32-bit maps to achieve a lower sample rate.  This also allows light rendering to performed in batches which lower draw calls and significantly reduces sample rate for PBR lighting. 

On current platforms for which GM supports multiple render targets (MRT) there is also a performance advantage where some of the deferred rendering can be performed in a single draw call.  Emissive and bloom also take advantage of MRT and are pre-composited concurrently during the PBR lighting calculations.

StatusIn development
CategoryTool
Rating
Rated 5.0 out of 5 stars
(3 total ratings)
AuthorBadwrong Games
Tagsdemo, GameMaker, lighting, materials, pbr, Shaders

Purchase

Buy Now$19.99 USD or more

In order to download this GameMaker asset you must purchase it at or above the minimum price of $19.99 USD. You will get access to the following files:

Eclipse Light Engine for GameMaker 128 MB

Development log

Comments

Log in with itch.io to leave a comment.

First off, just wanted to say that I absolutely adore this lighting engine. By far the best on the market.


Now with that said, I am running into a small issue, that I'm sure just stems from my lack of famaliarity with this engine. The error occurs when trying to set le_shadow_precise_static as the parent to one of my own objects:


############################################################################################

ERROR in

action number 1

of Other Event: Room Start

for object light_engine:

Variable <unknown_object>.add_shadow(100740, -2147483648) not set before reading it.

 at gml_Script_shadow_area (line 222) -               _list[| _i].add_shadow(_buff);

############################################################################################

gml_Script_shadow_area (line 222)

gml_Script_init_shadow_grid_gml_Object_light_engine_Create_0 (line 221)

gml_Object_light_engine_Other_4 (line 3) - init_shadow_grid();

Thank you very much for the support.


My guess with the error is you need to include event_inherited(); in the create event of your object.

Is there a discord or somewhere we can ask questions?


I'm unfortunately having issues just getting it to work in my game at all.

(+1)

There is a thread on the GameMaker forums where everyone has been asking and discussing Eclipse: https://forum.gamemaker.io/index.php?threads/eclipse-light-engine-pbr-lighting-f...

You can also just ask here if you want or email me badwronggames@gmail.com

If you are importing it into an existing project with many things already going on you may need to setup a bit of inheritance or the light wont have anything to hit.  Everything drawn should inherit from a type of the __game object so that their normal map and material maps are drawn.  Or if its a shadow caster use one of the various __shadow type objects to inherit from--depending on shape.  

If you use tilemap or asset layers they should be setup too as shown  in the first basic setup video and mentioned in the User Guide: https://drive.google.com/file/d/1dOVpNrsVvod9C8GMnuO6_hSj5hGVmVM-/view

Deleted 56 days ago

So I have an isometric game and I'm using the classic depth = -y to give a sense of "3D" space in my game.


However the entire lighting engine is being rendered under my objects in the room. Only the background layer is covered by the lighting engine.


I can't seem to get the lighting engine to go over my objects. I'm guessing this is related to the layers in the room but how do I get it to go over my instance layers?

I can't seem to test light_set_depth() because no matter what I do, the lighting engine is going underneath all objects anyways. I'm guessing it has to do with the layers in the room?

I have two layers: "Instances" and "Background"

Not sure what options to set in the light_engine object


(+1)

Using depth = -y for depth sorting is the problem.  You lose a lot your layer functions with all those unmanaged layers and that's why YYG advises not to use such a method.


If you must use that method, then don't just set it to negative y.  Set it to a value that will actually fit between the background and the light engine.  That could be as simple as room_height - y and then set the light engine on a layer with depth of -1.  


You could also try setting the depth of the layer the light engine is on to be "-room_height - 1". 

None of these are ideal however because a real depth sorting method should be used.  Eclipse also factors in depth for lighting and your light placement might be difficult if you have everything at random layer depths.

(4 edits)

So I'm now using a priority queue for depth sorting as per your suggestion. The other methods weren't working unfortunately.

But I'm not sure how to draw lights at certain depths now when looping through my sorted depth instance list.
I have a light of type le_light_spot created by my player and it follows my player around, but I'm not sure:

1) How to turn off its default drawing/rendering

2) How to manually render it after my player's draw event call in my depth sorting object

How do I manually render, for example, a spot light using code?

(2 edits)

A priority queue is very costly and not the method I would use personally.  Like I said you can use "depth = something" as long as you have the light engine on a layer lower than the lowest of your instances.  I highly suggest just normalizing the instance depth using room_height.

Lights are all batched and there is no such thing as manually rendering them.  Eclipse uses a deferred renderer so everything is done in as few draw calls as possible. 

You may want to just copy the depth sorting that Eclipse uses, as it passes depth to the shaders for normal and materials maps using the vertex color which gives a range of -16000 to 16000.  That automatically depth sorts things just by a shader while objects remain on the same layer.

Shadow and light depth is normalized from 0 to 1.  This is so that different layer or depth setups will be easy to work.  To match the players depth you can just set the light based on whatever normalized range you use... again room_height is the answer and can easily be translated into the range 0 - 1. 

There are many ways it could be done, but one option would be similar to:

depth = room_height - y;

light/shadow depth =  y / room_height;        // creates a range from 0 to 1

In your case the isometric y value would be used and you may need to account for room_height being a bit bigger in isometric space.

Regardless the light_engine needs to be at a depth or layer lower than everything else.  So, if it is normalized based on 0 - room_height, then the light_engine should be at -1 (or I suppose 0 would work too).

(+1)

Update on rollback issue. The vertex buffer data is stored in managed objects across frames, but static allocation stuff (buffers) are not rolled back in multiplayer. So when the system does a rollback, the static stuff throws an error. I'm still not sure why the first frame needs to be skipped even when the object is unmanaged, since presumably it would not be rolled back ever, but alas.

Thanks for the update.

I have actually been doing a lot with rollback for other reasons, and I'll say right away that it still has many problems to work out.  I cannot even connect with versions past August.

So, I'm not going to stress too much about it as long as it is in beta.  Any good fix added now could break later.  I couldn't even use structs in one version a week or so ago, so...ya.

Once it comes out of beta it will be worth the time to add better support for.  I'll probably even add my objects that handle rollback clients, events, and what not to the example project area.

That’s very reasonable! I can’t even connect on Games.GX on the most recent beta build, so yeah super bugged. I look forward to seeing where this engine goes post rollback beta.

Howdy! Been having tons of fun playing around with the engine. I have a few questions:

 Is there any way to get soft edge shadows, as in those shadows cast from the edge of a rectangle in 2D? Even with soft shadows at max they are still straight lines. 

How do you go about normal mapping for an animated sprite? My game is a pixel art game and I want the lights to appear behind the character, but light the perimeter of them. Hopefully such a thing is possible.

What does ambient color do? No matter what color I set it to it doesn't seem to do anything.

Is the source for the shooter and fantasy example available anywhere?

Sorry for all the questions, and thanks for the awesome engine!

Hey, thanks a ton for the support and glad you like it.

The side edges of cast shadows won't have much softening in the current setup.  You can get a bit more by lowering the shadow map resolution on the light engine object's variables tab.  That will obscure things a bit and the bloom blur passes would then soften them up some, and increasing the bloom amount would add to it as well.  They won't be the same as how they taper towards the far end of the shadow due to the current GameMaker shader implementation.  Eclipse has a lot of custom solutions due to the 10+ year old graphics API that GameMaker uses.  There is hope in the larger runtime update this year that I will be able to use newer techniques for Eclipse in that area.

For animated sprites I use this program: https://www.codeandweb.com/spriteilluminator

It was totally worth the price.  You do not want to do it frame-by-frame of course, and sprite strips are better to do an entire animation at once.  You can also do multiple images at once so that they all get the same settings.  Just drag them all into the images panel and highlight them all (shift click or something).  Then when you use the normal map tools like bevel and emboss it will apply to them all.

You can use light depth to place lights behind other things.  I show it in this video

The ambient color needs to also have the ambient light value turned up to do  much.  In the next update I will be improving how the ambient light works along with adding directional lighting and there will be a larger difference in those settings.

Glad to hear this is still being actively developed! The ambient color update will be a huge help. I find that having relatively good control over the ambient color helps set the mood of a scene. I'll check out that normal mapping tool, looks really helpful. 

(+1)

Greetings. Great work on this engine. I've been messing around with the new rollback multiplayer functionality (GM beta) and noticed that the engine doesn't work with managed objects. The new multiplayer function won't allow global or local variables (basically anything beyond temporary variables) to be set or modified within the draw function of objects. This causes an error to be thrown. 

I switched the light_engine to be unmanaged and avoided the above error (from the multiplayer issue), but  a new error was thrown.


############################################################################################

ERROR in

action number 1

of Other Event: User Defined 11

for object light_engine:

vertex_submit: Illegal vertex buffer specified.

 at gml_Object_light_engine_Other_21 (line 72) -                                    vertex_submit(_v_buffer, pr_trianglelist, -1);

############################################################################################

gml_Object_light_engine_Other_21 (line 72)

gml_Object_light_engine_Draw_0 (line 3)



Perhaps this is an issue with the beta version of game maker, just curious if you've got this engine working in beta or if you plan on fixing some of these issues given the limitations of the new rollback system.

(+1)

The illegal vertex buffer error seems to get thrown when my multiplayer object starts an online game. The engine works prior to any multiplayer functionality.

The shadow objects use a lot of local variables as well and are very likely not submitting proper vertexes if rollback does not allow that. 

The entire shadow grid which sub-divides the static shadow casters also builds a grid of structs which use a large number of local variables. 

I do have the beta and have messed with rollback, but not with my light engine.  I will check it out sometime, but the entire engine would have to be modified to accommodate something like that if it is the case.

Hopefully it is possible to not manage the shadow casters as well to get it working.

(+1)

So, I switched everything to unmanaged and I still got the illegal buffer error, so I digged a little deeper and tried to understand what was going on with vertex submit. It was fine if it returned a 0 for the local variable vertex_buffer, but it was throwing -4 when multiplayer started. What is weird is it only returns -4 for a single step. So what I did was create a local timer variable, set to 0, and add 1 in the step event. Then in the light_engine user event 11 - lighting SS (this is the event that was throwing the illegal buffer error), I had it only run if the timer variable was above 1. It actually worked and now there is no error.

(+1)

Ah, that would mean something isn't initialized fast enough.  I suspect "room start" is not the same when using rollback.

The shadow buffer variable is just a pointer that is first set to "noone" which is -4.  In the end step event it should check with the shadow grid for which static buffer to use and then append any dynamic shadows to that as a vertex buffer.  So, if that does not happen it would remain as -4. 

In the next update I will add dummy buffer that renders a single triangle with no area.  That is faster than adding checks for validity since the vast majority of the time it the buffer will always have something there.

Chances are the shadow grid is actually created and ready, but depending on the position of the view it could grab nothing from the grid depending on how your game is setup.  So, this will add a failsafe for that.  I'll add the dummy buffer in the next update and you won't need to do anything like you did.  Thanks for bringing that to my attention.

(+1)

No problem! I think you may be right about room create during rollback. The manual says that the event order for rollback is room end, clean up for defined players, and then room start.

I look forward to the update! Thanks!

Update: I've encountered a new problem. While running the game from Windows there is no problem and the lighting engine works. However, running the game from OperaGX completely disables the entire lightning system. I'm not sure if OperaGX does not support some of the graphical rendering by the engine or what is going on. Have you been able to get it to work on OperaGX?

(+1)

Thanks for the update.

I also have not found it working on OperaGX, and really most things with shaders and surfaces seem to have issues there.

I know WebGL is totally capable of the type of deferred renderer which Eclipse does, but the older API implementation that GameMaker currently uses is indeed lacking some key things.

I have and will be looking into it more because I do want it supporting everything.  Most likely the big changes to GM that are coming soon will be the best solution since at that point it sounds like the graphics API will be much more up to date and fully support MRT.

Also, in the last update I did add a special place holder buffer so that the illegal vertex submit error will not happen.  It also turned out, after rigorous testing, that GM has some internal issues with destroying vertex buffers and how they are indexed which cause memory leaks.  That was also a factor in the error you originally had, but has been fixed now as far as Eclipse goes.