Shaders Outine Shader help

S

skeptile

Guest
Like many people (based on my Googling), I watched this Shaun Spaulding video but have questions about getting it to work just the way I need it to.

The problem I have is that I need the outline to consistently draw a one-pixel-wide outline even when a sprite is stretched (its image_xscale and image_yscale change). With the shader in the video, the result on a stretched sprite is something like this:

The outline is the same scale as the sprite.

What I'm going for is this: (In this image, the outline is drawn by drawing the sprite 5 times: 4 times in black at a slight offset to form the outline, then once for the actual sprite. This method is quite hard on framerate, which is why I'm looking for a shader-based solution)


Any help you can offer is appreciated. Forgive me if I'm missing something; I'm fairly new to shaders and don't fully understand everything about how they work. Alternatively, if you have any non-shader methods of obtaining this result, feel free to share, as long as they're not taxing on framerate.

Here's the code in the shader:
Vertex
Code:
attribute vec3 in_Position;                  // (x,y,z)
//attribute vec3 in_Normal;                  // (x,y,z)     unused in this shader.
attribute vec4 in_Colour;                    // (r,g,b,a)
attribute vec2 in_TextureCoord;              // (u,v)

varying vec2 v_vTexcoord;
varying vec4 v_vColour;

void main()
{
    vec4 object_space_pos = vec4( in_Position.x, in_Position.y, in_Position.z, 1.0);
    gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * object_space_pos;
    
    v_vColour = in_Colour;
    v_vTexcoord = in_TextureCoord;
}
and Fragment
Code:
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
uniform float pixelH;
uniform float pixelW;

void main()
{
    vec2 offsetx;
    offsetx.x = pixelW;
    vec2 offsety;
    offsety.y = pixelH;
    
    float alpha = texture2D( gm_BaseTexture, v_vTexcoord ).a;
    
    alpha += ceil(texture2D( gm_BaseTexture, v_vTexcoord + offsetx ).a);
    alpha += ceil(texture2D( gm_BaseTexture, v_vTexcoord - offsetx ).a);
    alpha += ceil(texture2D( gm_BaseTexture, v_vTexcoord + offsety ).a);
    alpha += ceil(texture2D( gm_BaseTexture, v_vTexcoord - offsety ).a);
    
    gl_FragColor = v_vColour * texture2D( gm_BaseTexture, v_vTexcoord );
    gl_FragColor.a = alpha;
}
 
Last edited by a moderator:

CMAllen

Member
Shaun's sampling code does not take image scale into account, so you get a sampling size equal to the size of each individual pixel in the image. You'll need to adjust your sample size to the final scale of the sprite being drawn.
 
S

skeptile

Guest
Shaun's sampling code does not take image scale into account, so you get a sampling size equal to the size of each individual pixel in the image. You'll need to adjust your sample size to the final scale of the sprite being drawn.
Sorry for my lack of knowledge on the subject, but what is the sampling size, and how can I adjust it?
 
S

skeptile

Guest
Never mind, I think I got it!
I changed this
Code:
texelW = texture_get_texel_width(sprite_get_texture(argument0, argument1));
texelH = texture_get_texel_height(sprite_get_texture(argument0, argument1));
to this:
Code:
texelW = texture_get_texel_width(sprite_get_texture(argument0, argument1))/image_xscale;
texelH = texture_get_texel_height(sprite_get_texture(argument0, argument1))/image_yscale;
And that solved my problem!

However, I just noticed that when I apply the shader, image_alpha is not taken into account. When I draw the same sprite with an alpha of 0.5, it draws at full alpha. Any idea what's causing that?

EDIT: I managed to fix that, too. Turns out GLSL is a lot easier to intuit than I initially thought!

One final question, if anybody sees this: is there a way to apply this shader to text?
 
Last edited by a moderator:
The only way i found to apply a shader to text is to draw the text to a surface first and apply the shader to the surface.
 
Top