• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

GameMaker Outlining on asset layers?

LazyTomato

Member
So I'm working on a platformer... A platformer where I wanted to have more "free" terrain, not bound to tilesets and grids and the like.
And so I decided to use asset layers to make up the visual part of the terrain, since it seemed just appropriate for this; just have sprites for the terrain, both the flat colors and the details, and spread them around in asset layers to make up the terrain on top of the invisible collision pieces.

And that works perfectly, of course, there's just one issue.
And that issue is that, well, using basic flat color pieces for the bulk of the terrain doesn't really look good at the edges without an outline that marks the end of the terrain (and outlines would also match the game's artstyle, since it's going to be hand-drawn)

I thought to resort to shaders, since I know for a fact these can be assigned to asset layers; I'm already using one to darken terrain pieces set in the background, so players can make out what's actual terrain and what's decoration (see spoiler).

Both the building and the blocks below are actually the same color, but things in the background layer are darkened
upload_2019-11-4_0-0-44.png

So those kinds of shaders work fine, but when I tried using an outline shader (following the classic examples of those on the community), it just didn't work; it didn't do anything.
Granted, outlines work perfectly on actual objects, but assigning said shader to an asset layer just straight up doesn't work (again, the image above is an example of the lighter terrain blocks, flat and outlineless).
I think I can safely assume this is because of asset layer shaders being handled differently than on actual objects with their own sprites?

And if that's the case, is there any alternative? Could I somehow automate that terrain outlining process in some other way? Or would i have to use even more sprites to do the outlining manually? (...which would be doable, but would take an insane amount of work for larger maps)
 

YellowAfterlife

ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ
Forum Staff
Moderator
For the correct result you would want to set the layer to draw into a surface in layer_script_begin, then draw that surface with a shader in layer_script_end
 

LazyTomato

Member
For the correct result you would want to set the layer to draw into a surface in layer_script_begin, then draw that surface with a shader in layer_script_end
Okay, umm... I don't exactly have much experience using the layer_script functions...
So let me get this straight: I'd have to create a surface beforehand, then set it as the drawing target along with the shader in layer_script_begin (or recreate it if it doesn't exist, because that's something that surfaces like to do somethimes), then have another script that resets the shader and the target surface in layer_script_end?

EDIT EDIT EDIT:
(I'm just gonna remove the rambling I had here, everything's explained better in my other post)
 
Last edited:

LazyTomato

Member
Alright sorry for the bump, but I did make a bit of progress... Figured I'd at least share my code to see if anyone can tell what I'm doing wrong exactly.
(also i changed the surface size to the camera one because i realized I was an idiot trying to make it use a 10k-pixel-wide one in a bigger room)

First off I have a script I called "layer_set_surface", which goes like this:
Code:
if (event_type == ev_draw)
{
 if (event_number == 0)
 {
  if !(surface_exists(global.surf)) global.surf=surface_create(1280,720);
  surface_set_target(global.surf);
  camera_apply(view_camera[view_current]);
  shader_set(shd_outline);
  draw_surface(global.surf,camera_get_view_x(view_camera[0]),camera_get_view_y(view_camera[0]))
 }
}
(the surface is already created by that other persistent object at the start of the game which also manually recreates it on its own if it's missing but I left that here anyway just to make sure)

Then for the ending script i just did a simple resetting one:
Code:
if event_type == ev_draw
{
 if event_number == 0
 {
  shader_reset();
  surface_reset_target();
 }
}
To set those scripts, I use a background-handling object (that's also in charge of drawing the in-game backgrounds), which is automatically created at the start of every relevant room (i.e. rooms that are actual in-game levels and not menus or whatever):
Code:
//(this goes after everything else in the create event)
if !(surface_exists(global.surf)) global.surf=surface_create(1280,720);
var lay_id = layer_get_id("terrain");

layer_script_begin(lay_id,layer_set_surface);
layer_script_end(lay_id,layer_end_surface);
(yes, i did check that the layer name is correct; if it wasn't then the layer would probably not be affected at all instead of just being turned invisible)

This, uh... Doesn't crash the game at least, but it's still making that layer not draw at all. And, mind you, I didn't have the draw_surface statement at first, I assumed it'd draw the layer automatically; I added it afterwards thinking that would fix the drawing issue but it's still not drawing the layer at all.
Same goes for the camera_apply statement, since I looked up this topic and saw someone suggesting that too; it didn't fix anything though.

EDIT: Yes, I did try changing the shader for another one to see if this one was broken; it's not that because no matter what shader I try to apply, it's still not drawing anything.
 
Top