Skip to main content

On Sale: GamesAssetsToolsTabletopComics
Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

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).

(3 edits)

So I'm now pretty confused. I also have no idea where the depth sorting even is in the Eclipse objects. Nor do I fully understand how to set a light's depth or how I'd incorporate instance depths into it or how to incorporate light depths into my own depth sorter above.  I don't mind using a different method but I don't know how to incorporate light depth (or set light depths) into a depth sorter in general.

I've reverted back to setting the depth for my objects as per your suggestion.

Controller create event (setting layer depths):

layer_depth("Instances", -1);
layer_depth("Light_Layer", 0); // <-- light_engine object placed on this layer
layer_depth("Background", 1);

Player create event:
light = instance_create(x, y, le_light_spot);

Player/Solid Objects step event:
depth = room_height - y; // this works, my player is going under and over other objects properly and vice versa

As well in my Player step event for their light:
light.x = x; light.y = y+1; // so the light always goes over my player
light.depth = y / room_height;

light.light_depth = light.depth;

Expected Results:
If the player goes above the building  (y < building.y), the player should be drawn underneath it. The player's light should be drawn over the player, but underneath the building.
If the player goes below the building (y > building.y) the player should be drawn overtop of it. The player's light should should be drawn over the player as well as the building

Results:
Positives: The lighting system successfully goes over my background and instances layers (I will refer to this as the "darkness")
Negatives: My player's light is always under my player/all other instances but above the background. Setting the Light_Layer depth to -2 puts it over everything. Setting light.depth or light.light_depth doesn't appear to change anything. It doesn't matter where my light's y is set to, it will get drawn over all instances at all times, even if my player goes under (y < building.y) a building.

What am I doing wrong?

(1 edit)

Here is a tutorial I made about normalizing your depth sorting: 

You'll want to also reference the Eclipse User Manual: https://drive.google.com/file/d/1dOVpNrsVvod9C8GMnuO6_hSj5hGVmVM-/view?usp=shari...

You need to use the functions for changing things like depth or updating it which the user guide explains.  For lights and normal objects inherited from __le_game or something you will want to use such functions.

Setting things manually with "instance.depth" will not work.

Also, you mentioned isometric coordinates.  So, you would most likely want to use the isometric y value plus the distance to the bbox bottom from the origin because your bbox_bottom will not be the same in isometric coordinates.  You still would do all your normal logic with collisions and interactions using normal x/y coordinates, but for drawing in an isometric game everything is drawn at a different coordinate along with their depth sorting.

(3 edits)

Another thing that you may need to consider is setting static objects depth in their create event "before" event_inherited.  This is because static objects like shadow casters add their shadow depth when created to a the buffer used for casting shadows.  So, depending on your depth sorting method you would put in the create event:

depth = room_height - bbox_bottom;

event_inherited();  // After setting depth

Then for objects which change depth often you would put in their step event or where ever:

depth = room_height - bbox_bottom;

update_depth();  // Explained in the user manual

Light depth on the other hand is normalized so where the light is updated you would put:

light_id.y = new_y_value;

light_id.set_depth(room_height/new_y_value);

Or use a "with statement" or something to avoid all the extra id lookups, etc.

(2 edits)

I've set the origin of my sprites at the lowest isometric point so I don't have to use bbox_bottom I don't think.


I watched the video, I'm normalizing the depths now (in my player and solid objects):

Function calculate_depth():
depth = room_height - y + 100;

Controller Create Event
layer_depth("Instances", -1);
layer_depth("Light_Layer", 100);
layer_depth("Background", room_height + 100);

Solid Objects Step Event:
calculate_depth();

Player Create Event:
light = instance_create_layer(x, y,"Light_Layer", le_light_spot);


Player Step Event:
calculate_depth();
with(light) {
    x = other.x; y = other.y + 1;

    set_depth(y / room_height);
}

My player and the light objects unfortunately don't have the function "update_depth()"

--
I still don't understand what I'm doing wrong. I'm using set_depth() now but the light is still going under my player and above the background. The light is going under everything except the background.

I haven't touched shadows and nothing is inheriting from a shadow object yet, I'm just trying to get the light to go in the proper depth (same depth as my player but above my player).

Player depth is working fine still. I just don't understand. How do I set the light's depth? What am I doing wrong?

Did you read the manual or watch the videos?  You have to inherit from one of the light engine objects for your things like players, enemies, and other entities.  In most cases __le_game should be inherited from.  Unless of course it is a shadow caster.

(4 edits)

I did but it's a very complicated system honestly at first glance. I'm very sorry I'm trying to understand it. I don't know what objects need to inherit from what to get depth working properly, I understand depth is a recent addition you added?

I now have my player and my building objects inheriting from __le_game. I think things are starting to work a bit better.

I now have two small issues though:

- Light is emitting very strong whiteness against my players and objects that are inheriting from __le_game. I was just hoping it could brighten up the scene the way it would be drawn if there was no darkness. It's lighting up the background layer perfectly fine but the player/solid objects are turning white
--

- The light is not going behind my building now, it's always above it
--

But I'm guessing this is because I need to somehow get the le_light_spot object to inherit from __le_game as well so I can call update_depth? It's already inheriting from _le_light_cull which inherits from __light. So I tried making __light inherit from __le_game but now I get this error:
"
Variable le_light_spot.normal(101661, -2147483648) not set before reading it.

 at gml_Object___le_game_Other_25 (line 3) - draw_sprite_ext(normal_map, image_index, x, y, image_xscale, image_yscale, image_angle, normal, LE_NORMAL_ANGLE);
"