• Hey! Guest! The 37th GMC Jam will take place between May 28th, 12:00 UTC and June 1st, 12:00 UTC. Why not join in! Click here to find out more!

(SOLVED) shader layer excluding GUI layer

Hi everyone.
I'm trying to build a lighting system using shaders.

I have multiple tile layers, and a couple of instance layers per room.
I also have a system instance layer at depth 0 just to have some layer
where my system instances need to go and be nicely grouped together.
This last layer contains some of my important system things, like pause menu's, mouse sprites, user interface, inventory sprites, etc...

What I want to do is have every layer and every non-gui-instance be affected by a
lighting shader.
I do not want whatever is drawn on the GUI layer to be affected.
For example, I have an inventory object that draws the player inventory using
its draw GUI event. I also have a pausesystem instance that draws a pause menu in its
draw GUI event when the game is paused, there's things like healthbars, and so on.

Naturally, I don't want whatever is drawn as GUI to be affected by the lighting shader.

I can do it however, using a very tedious strategy:
Per room, have a layer_shader do the shader magic per layer.
Then, in each instance, have its draw event go through the same shader.

This works, but it doesn't allow me do to point--lighting i think. For example, have a torch on a
wall light up the entire surrounding area surrounding area, instances included.

What I'd want to do, and what I'm asking here,
is if it is at all possible to send everything through a shader, but not things that are rendered on the GUI layer, or things that are drawn using draw GUI events. Instead of treating each layer and each instance separately, have it all be treated as one thing to change, while keeping all the GUI stuff unaffected.

I'm sure this has something to do with surfaces, but I'm afraid my scaled camera will be a real chore to fix that.

Still, is this doable? Send everything indiscriminately through a shader, but not anything draw GUI event related?

The reason I'm asking is because I can't seem to find a way to "grab" the GUI layer, like I do with any other layer using layer_shader(layer_id) for example.

I'm also a noob when it comes to surfaces, so I know i will need to learn that probably.
 

Simon Gust

Member
The alternative to layer shaders is to set shader, draw every layer that needs lighting and then reset shader.
Code:
shader_set();

// draw layers that are affected by lighting

shader_reset();

// draw layers unaffected
I have no idea how layers work, but to handle the timing you could make use of layer_script_begin, in which you choose the first layer and set the shader.
Then in the last layer that is affected you can reset the shader using layer_script_end.

If you have gaps (unaffected layers between affected layers) I see no way to achieve this without having the shader set and reset multiple times.
Even a surface wouldn't help then.
 
The alternative to layer shaders is to set shader, draw every layer that needs lighting and then reset shader.
Code:
shader_set();

// draw layers that are affected by lighting

shader_reset();

// draw layers unaffected
I have no idea how layers work, but to handle the timing you could make use of layer_script_begin, in which you choose the first layer and set the shader.
Then in the last layer that is affected you can reset the shader using layer_script_end.

If you have gaps (unaffected layers between affected layers) I see no way to achieve this without having the shader set and reset multiple times.
Even a surface wouldn't help then.
is it possible however, to build a surface from literally everything in the game except the gui layer? I'm already keeping point light sources in mind, and i'd rather do something that needs to change only 1 surface instead of having to change each individual tile layer, instance,... in a room.
 

Simon Gust

Member
is it possible however, to build a surface from literally everything in the game except the gui layer? I'm already keeping point light sources in mind, and i'd rather do something that needs to change only 1 surface instead of having to change each individual tile layer, instance,... in a room.
Read up on the application_surface. before entering the GUI draw phase, the application_surface will hold everything drawn in that frame and can be affected by a shader.
As long as you reset the shader before the GUI layer begins to draw you should be fine.

You are required to take over control of the automatic drawing of the application surface.
https://docs2.yoyogames.com/source/_build/3_scripting/4_gml_reference/drawing/surfaces/application_surface_draw_enable.html

You can draw the application surface in the post draw event.
https://docs2.yoyogames.com/index.html?page=source/_build/3_scripting/4_gml_reference/drawing/surfaces/application_surface.html
 
Read up on the application_surface. before entering the GUI draw phase, the application_surface will hold everything drawn in that frame and can be affected by a shader.
As long as you reset the shader before the GUI layer begins to draw you should be fine.

You are required to take over control of the automatic drawing of the application surface.
https://docs2.yoyogames.com/source/_build/3_scripting/4_gml_reference/drawing/surfaces/application_surface_draw_enable.html

You can draw the application surface in the post draw event.
https://docs2.yoyogames.com/index.html?page=source/_build/3_scripting/4_gml_reference/drawing/surfaces/application_surface.html
Quick and easy to follow answer. I tried it and it works!
I now use my camera object's post-draw event to disable application surface drawing, then use draw_surface_ext to draw it back scaled, and send it through my shader.
All my GUI elements are intact!

Thanks :)
 
Read up on the application_surface. before entering the GUI draw phase, the application_surface will hold everything drawn in that frame and can be affected by a shader.
As long as you reset the shader before the GUI layer begins to draw you should be fine.

You are required to take over control of the automatic drawing of the application surface.
https://docs2.yoyogames.com/source/_build/3_scripting/4_gml_reference/drawing/surfaces/application_surface_draw_enable.html

You can draw the application surface in the post draw event.
https://docs2.yoyogames.com/index.html?page=source/_build/3_scripting/4_gml_reference/drawing/surfaces/application_surface.html
Extra comment: REALLY thank you. Pointing me to that simple solution just opened up the world of shaders to me.
Now i'm going to... I don't know :D Maybe make a deep day and night system or something :D
 
Top