Shaders Outline Shader w/o Separate Texture Pages

Arconious

Member
(I am using GameMaker Studio 2)

Hello all,

I'm currently trying to learn about Shaders and how to use/construct them, and as part of that I have been trying to piece together a simple outline shader.

The code I've managed to get together almost works perfectly, however the outermost pieces do not get outlined. See here (the edges of the gauntlets/plumes): outlineKnight.png

The issue appears to be related to it being on a texture page (that much I'm certain) and I believe it has to do with the way information is saved about the individual images on the page. If I add an practically invisible pixel to the top left of any of the images (with an alpha of 1), it fixes the issue for that image -- I'm assuming by adding the necessary padding to the sprite info.

The quick fix is to have any necessary sprites use the "Separate Texture Page" option, but this would rapidly increase the number of texture swaps (especially considering the number of animations I would like to apply this shader to).

Xor in a different thread stated this:
...The other option is to use the uvs from sprite_get_uvs(), but this is much more complicated. In order to use the uvs you need to convert them from the range of 0 to 1 into the new minimum and maximum uvs and then pass them in using a uniform.
I believe that what he is talking about would work here (provided the problem doesn't lie explicitly with the way the images are arranged on the texture page), but I simply don't understand the conversion that is necessary.

Thank you in advance for any potential advice or guidance!

The code I'm currently using:
Code:
/// Create Event -- oEntity
spriteScale = shader_get_uniform(shdOutline, "spriteSize");
tex = sprite_get_texture(sprite_index,image_index);
texW = texture_get_texel_width(tex);
texH = texture_get_texel_height(tex);
Code:
/// Draw Event -- oEntity
shader_set(shdOutline);
shader_set_uniform_f(spriteScale, texW, texH);
draw_sprite_ext(sprite_index, image_index, floor(x), floor(y), image_xscale, image_yscale, image_angle, image_blend, image_alpha);
shader_reset();
Code:
/// Fragment Shader -- shdOutline
varying vec2 v_vTexcoord;
varying vec4 v_vColour;

uniform vec2 spriteSize;

void main()
{
    float alpha = 0.0;
 
    //Now add alpha depending on the pixels surround it
    alpha = max(alpha, texture2D( gm_BaseTexture, v_vTexcoord + vec2(-spriteSize.x, 0.0) ).a); //Left
    alpha = max(alpha, texture2D( gm_BaseTexture, v_vTexcoord + vec2(spriteSize.x , 0.0) ).a); //Right
    alpha = max(alpha, texture2D( gm_BaseTexture, v_vTexcoord + vec2(0.0, -spriteSize.y) ).a); //Up
    alpha = max(alpha, texture2D( gm_BaseTexture, v_vTexcoord + vec2(0.0,  spriteSize.y) ).a); //Down
 
    gl_FragColor = v_vColour * texture2D( gm_BaseTexture, v_vTexcoord );
    gl_FragColor.a = alpha;
}
 

Juju

Member
Turn off "texture page cropping" - this is found in Global Game Settings for GMS1 or Tools/Texture Groups for GMS2.
 

Arconious

Member
Turn off "texture page cropping" - this is found in Global Game Settings for GMS1 or Tools/Texture Groups for GMS2.
Yup, that would end up being all it takes. Completely forgot about looking into the actual texture group, thank you so much, hate missing things so small like that.
 

Juju

Member
It's not an option that's used regularly so it flies under the radar a bit. Don't forget to crop your sprites manually to get nice texture packing!
 
Top