If you're having trouble or run into any bugs with the code, post a comment here! I will try to get back to you within a few days.
Apply dynamic outlines in-engine to buttons, images, and more. · By
Hello! As mentioned in the compatibility section, shaders require GL2, which isn't present in versions before 7.4. If you can update your engine version to 7.4 or later, then you will be able to use the shader, but it is not compatible with earlier version like 7.3.2. It does work with `show`; you can use it as an ATL transform the same way as `show character at left`.
Hello! I got the shader, using it in version 7.4.11. I just dropped the file in my game folder and I am getting a parsing script failed error:
```
I'm sorry, but errors were detected in your script. Please correct the
errors listed below, and try again.
File "game/outline_shader.rpy", line 182: ATL statement contains two expressions in a row; is one of them a misspelled property? If not, separate them with pass.
gl_drawable_resolution drawable_res
^
File "game/outline_shader.rpy", line 211: ATL statement contains two expressions in a row; is one of them a misspelled property? If not, separate them with pass.
mesh True mesh_pad (20, 20, 20, 20) gl_drawable_resolution False
^
Ren'Py Version: Ren'Py 7.4.11.2266
Tue Feb 27 17:46:04 2024
```
Hello! As mentioned in the page the lowest version the shader has been tested on is 7.5; it seems like one of those properties is more recent - likely gl_drawable_resolution. You can comment out those properties until it works, or what I recommend, is updating your engine version (at least to 7.5). 7.4.11 came out in 2021 and we're currently on 7.7/8.2.
Hello again! Using the shader and I was wondering a few things.
I have applied the shader to the characters in our game before, and the results are different when I apply them when showing the character or when defining the character. It seems the gradient is calculated differently, and it looks like it starts the gradiant close to the outside edge of the shader. I attached a screenshot of one of my poor characters struggling with his spiky hair, and the transform applied. If I apply the shader after the character has been defined, the gradiant seems to look better. Is there a way to smoothly transition from the two colors when defining a character with this shader?
Thank you!
transform shadowOne:
outline_transform(30, "#0000002f", 4.0, end_color="#00000000", num_passes=1.0, gradient_smoothing=1.0, is_mesh=True, mesh_pad=True, drawable_res=True, offset=(0, 0))
image low Normal A cape:
"Lowri/LowAHNormal.png"
shadowOne
zoom .25
yoffset 200
Hello! I'm afraid I don't quite understand what you're asking - can you elaborate on what difference you are seeing between the two methods? What are the two colours you want to transition between? If you prefer the look of one method, is there a reason you can't use that method for the effect you want?
Hello! Sorry for the confusion. I want a drop-shadow effect on each character (to make them standout from the background), and I would prefer not to have to apply the transformation every time I show a character, but on the character definition. As you can see in the screenshot I attached, the dropshadow effect is not displaying correctly when attaching to the character definition. The two colors are black, one with a bit of transparency, and one with full transparency. I want a smooth transtion between the two, but I am getting a transition only at the edge of the outline. This was not the case when applying the transformation when showing the character for some reason, but if I had to apply the transform on every time I show a character... it would take a really long time, and it would break some of my existing transformations.
I think there's perhaps a mismatching of expectations here - there's always going to be a visible seam where the gradient ends because it's a set size and at some points the step between "can make out the outline" and "outline is too transparent to reliably discern" will be visible simply because of how perception works. You can make glowing outlines in an editor like photoshop and you'll still see where the glow ends.
As for applying the outline to a character, you can use a LayeredImageProxy or just apply it right to the image declaration, depending on how you've set up things. For example, image eileen outline = LayeredImageProxy("eileen", outline_transform(...)) will automatically apply the transform to the layered image "eileen" for whatever attribute combinations you need just by show eileen outline, or if you don't want it toggleable then just add an at outline_transform(...) right at the top of the layeredimage declaration itself.
mmm I understand the outline will be visible. I am more trying to reproduce the soft shadow effect I see on the dagger example on the page of this plugging, but for me it is looking different. It is like the gradiant is only being applied to the outside border of the outline, instead of the entire width of the outline. Lets say the width of the outline is 20px, the gradiant seems to only apply to the last 5pixels of the outline.
As for applying the transform on a proxy, let me try that and see if it changes the behavior of the outline. Thanks!
Thanks! Only thing I can say right now looking at the code is that it seems the current blending is depending on the scale of the image, instead of the outline width. That is probably why if I apply the outline after the existing transformation or before it changes the smoothness of the border. (my characters are zoomed out so the scale changes quite a bit). I still have to try the proxy transformation. That might solve my issues as it applies the outline transform after my zoom transform.
Oh I think I understand what you mean now - yes order of operations matters. If you apply the shader to a zoomed image, the outline won't be zoomed. If you apply the shader and then zoom the image, the outline gets zoomed as well. You can see the property order here: https://www.renpy.org/doc/html/atl.html#property-order So if you want to go out of order, you'll have to make an image that's got the shader already applied and then zoom that, for example.
Hey this works perfectly on pc but when I'm making the android version it breaks the game with the error :"renpy.gl2.gl2shader.program.load ShaderError:b'L0001 "variable u_model_size does not match the vertex variable u_model_size
I'm using renpy 8.2 and android should support gl2. In compatability you write "This tool requires config.gl2 to be True" It seems that 8.2 has removed this config because now it will always use gl2. Any help is appreciated
This is the transform I'm using:
transform glow_outline_black_thin(width=3, color= '#000000ff', mesh_pad=False, num_passes=None): outline_transform(width, color, 3.0, '#000000ff', (num_passes or width*2.0), mesh_pad=mesh_pad)
Hello! Thanks for the report. I believe I should have this fixed in an upcoming update I've been planning for this shader - if you don't mind waiting a week or so, I hope to have it released by then. This is an issue I've seen when using the ANGLE2 renderer instead of GL2; usually systems default to GL2 but some phones may not. I'll put out a devlog once the update is out, and then please let me know if it fixes your problem!
Hello! Someone playing the android version of my game ran into an error and I'm not sure how to help them:
I did(do?) have a gradient that was slightly edited from tom's example gradient shader code on the documentation page -- though the android version doesn't/shouldn't be using it at all at this point....
I think it's only on android, though the phone I used to test was fine + the PC builds arent having an issue-- At this point I think I might have to wait for the person who got this to get back to me (though I'll update the android dl to have absolutely nothing else shader-wise.)
Thank you for helping me narrow it down! ><
Yep, you can apply the outline shader to just about anything! I do also recommend you try playing around with Ren'py's built in outlines to see if you can get the effect you want, as the outline shader will be somewhat similar; you can apply outlines with decreasing transparency and increasing size through the outlines text property. Notably your example image is more a blobish suggestion behind each letter, whereas the outline shader (and built in text outlines) will be more like *glowing*. You might also be interested in my gradient shader tool if you want more blended gradients generally.
Hey there, Fen! I've run into the following error:
```
I'm sorry, but an uncaught exception occurred.
Executing ATL code at game/image_tools/outline_shader.rpy:274
File "game/image_tools/outline_shader.rpy", line 67, in script
TypeError: 'bool' object is not iterable
-- Full Traceback ------------------------------------------------------------
Full traceback:
File "game/image_tools/outline_shader.rpy", line 67, in script
File "C:\Users\olive\Desktop\renpy-8.3.7-sdk\renpy\ast.py", line 1124, in execute
show_imspec(self.imspec, atl=getattr(self, "atl", None))
File "C:\Users\olive\Desktop\renpy-8.3.7-sdk\renpy\ast.py", line 1087, in show_imspec
renpy.config.show(name,
File "C:\Users\olive\Desktop\renpy-8.3.7-sdk\renpy\exports\displayexports.py", line 503, in show
sls.add(layer, img, key, zorder, behind, at_list=at_list, name=name, atl=atl, default_transform=default_transform, transient=transient)
File "C:\Users\olive\Desktop\renpy-8.3.7-sdk\renpy\display\scenelists.py", line 444, in add
if not self.hide_or_replace(layer, remove_index, "replaced"):
File "C:\Users\olive\Desktop\renpy-8.3.7-sdk\renpy\display\scenelists.py", line 508, in hide_or_replace
d = oldsle.displayable._in_current_store()._hide(now - st, now - at, prefix)
File "C:\Users\olive\Desktop\renpy-8.3.7-sdk\renpy\display\transform.py", line 945, in _hide
self.update_state()
File "C:\Users\olive\Desktop\renpy-8.3.7-sdk\renpy\display\transform.py", line 1235, in update_state
fr = self.execute(self, fst, fat)
File "C:\Users\olive\Desktop\renpy-8.3.7-sdk\renpy\atl.py", line 798, in execute
action, arg, pause = block.execute(trans, timebase, self.atl_state, events)
File "C:\Users\olive\Desktop\renpy-8.3.7-sdk\renpy\atl.py", line 1043, in execute
action, arg, pause = stmt.execute(trans, target - start, child_state, events)
File "C:\Users\olive\Desktop\renpy-8.3.7-sdk\renpy\atl.py", line 1660, in execute
value = interpolate(complete, old, new, PROPERTIES[k])
File "C:\Users\olive\Desktop\renpy-8.3.7-sdk\renpy\atl.py", line 249, in interpolate
return tuple(interpolate(t, i, j, ty) for i, j, ty in zip(a, b, typ))
TypeError: 'bool' object is not iterable
Windows-10-10.0.22631 AMD64
Ren'Py 8.3.7.25031702
introLUCAS 0.1.7
Sun May 18 01:28:29 2025
```
Please advise! ; -; / <3
That's good to know! Unfortunately it does mean that it's interacting with something in your project then, which I can't debug. Note that shaders can interact with each other in odd ways sometimes, in case that gives you an idea of where to look. If you find any more information, let me know in case there are compatibility changes I can make!
Hi, no expectation of you solving this as it could easily have to do with other things in my set-up!
Upon updating to 8.4.0.25060301+nightly, I noticed that the outlines around my sprites are appearing more jagged. I should note that my sprites are scaled down by half currently. I added define config.mipmap = True, but it didn't seem to have an effect on the outlines.
Were there any changes in the update that would affect the shader? Or is it likely something else in my game that's causing it?
Interesting! As that's the nightly version, it's also possible it has some unresolved bugs etc, so it's not something I'll really be looking into solving unless it makes it into the public 8.4 release. Though, engine updates generally should not retroactively change the behaviour of shaders, so it would likely be an engine regression of some kind in that case. If you can reproduce the behaviour change from 8.3 to 8.4 in a basic project, it might be worth a bug report in the Ren'Py GitHub.